25.Python编程:@property详解

作者: TensorFlow开发者 | 来源:发表于2018-05-30 20:51 被阅读19次

在前面学习访问权限一文中,我们设计了一个SmartPhone类,

# 定义一个SmartPhone类
class SmartPhone(object):
    __os = ""  # 私有属性:系统
    __type = ""  # 私有属性:品牌
    __memory = "4GB"  # 私有属性:内存大小 默认单位GB

    # 构造方法
    def __init__(self, os, type, memory):
        self.__os = os
        self.__type = type
        self.__memory = memory

    def print_phone_info(self):
        print('os:', self.__os, '\n品牌:', self.__type, '\n内存大小:', self.__memory)

    #  对外界提供获取__os的值的方法
    def get_os(self):
        return self.__os

    #  对外界提供设置__os的值的方法
    def set_os(self, os):
        self.__os = os

    #  对外界提供获取__type的值的方法
    def get_type(self):
        return self.__type

    #  对外界提供设置__type的值的方法
    def set_type(self, types):
        self.__type = types

    #  对外界提供获取__memory的值的方法
    def get_memory(self):
        return self.__memory

    #  对外界提供设置__memory的值的方法
    def set_memory(self, memory):
        self.__memory = memory

如果你观察的足够仔细,你会发现,例子中我们属性只有3个,增加了3对get\set方法,也就是6个方法。我们已经知道,当把属性设置为私有属性时,通过添加对应的get方法获取其值,通过添加对应的set方法设置值,还可以通过set方法做数据的有效性校验、过滤等操作。

那么,如果属性非常多时,我们上面的做法又会显得非常麻烦,这有没有好的解决方案呢?答案是有的。python中给我们提供了一些关键词@property,专门帮我们解决上面的问题,我们今天就详细学习这些知识。

@property

@property是Python内置的一种装饰器。(什么是装饰器,暂时可以理解为给函数动态加上功能的一种语法)。@property的内部实现是比较复杂的。现在我们先学会如何使用,等以后有了一定的分析源码的能力,再回过头分析其内部实现。

从今天以后,在Python编程中,你一看到@property,第一反应就是:@property专门负责把一个方法变成同名属性的。

# 定义一个Car类
class Car(object):

    @property
    def price(self):
        print("调用了:@property修饰的price方法")
        return self.__price

    @price.setter
    def price(self, price):
        if price < 0:
            price = 0
        print("调用了: @price.setter修饰的price方法")
        self.__price = price

解释:上面我们用@property修饰了方法price(self):,此时@property会把方法price直接变成同名属性。当我们获取price属性的值时,实际上就是调用的此方法。

此时,@property本身又自动创建了另一个装饰器@price.setter,负责把一个方法变成属性赋值,即:price的setter方法。于是,@price.setter修饰的price其实是set方法,当我们给price赋值时,实际上就是调用的此方法。

   @price.setter
   def price(self, price):
        if price < 0:
            price = 0
        print("调用了: @price.setter修饰的price方法")
        self.__price = price

接下来验证上面的解析:

# 创建一个Car类型的对象
c = Car()
c.price = -100000 # 故意设置为负值,
print("小汽车的价格:price = ", c.price)

运行结果:

调用了: @price.setter修饰的price方法
调用了:@property修饰的price方法
小汽车的价格:price =  0

可见,我们给price设置非法的数值时,会被@price.setter修饰的price方法,即:set方法过滤处理。我们设置一个合法的价格,重新运行:

调用了: @price.setter修饰的price方法
调用了:@property修饰的price方法
小汽车的价格:price =  100000

@property补充

1.我们还可以定义只读属性,即只定义getter方法,不定义setter方法就是一个只读属性。
例如:我们给上面的Car类,新增一个轮胎个数的只读属性:

# 定义一个Car类
class Car(object):

    @property
    def price(self):
        print("调用了:@property修饰的price方法")
        return self.__price

    @price.setter
    def price(self, price):
        if price < 0:
            price = 0
        print("调用了: @price.setter修饰的price方法")
        self.__price = price

    @property
    def tire_count(self):
        return 4

读取该轮胎个数属性,用下面代码进行验证:

# 创建一个Car类型的对象c2
c2 = Car()
print("轮胎个数:", c2.tire_count)

运行结果:

轮胎个数: 4

读取成功。我们尝试设置轮胎个数为5,代码如下:

# 创建一个Car类型的对象c2
c2 = Car()
print("轮胎个数:", c2.tire_count)

c2.tire_count = 5
print("更改后,轮胎个数:", c2.tire_count)

运行结果如下:

轮胎个数: 4
Traceback (most recent call last):
  File "F:/python_projects/oop/23SmartPhone.py", line 78, in <module>
    c2.tire_count = 5
AttributeError: can't set attribute

会报错:AttributeError:can't set attribute,

只读属性示例
如果你也在用PyChar编辑器,细心的你可以发现:当我们给一个只读属性赋值时,编辑器会提示:属性tire_count不能被赋值。

2.@property修饰的方法名可以和@property自动生成的装饰器修饰的方法名必须相同。
上面例子中,我们采用了相同的方法名price。下面我们尝试修改@price.setter修饰的方法名为:price_test

# 定义一个Car类
class Car(object):

    @property
    def price(self):
        print("调用了:@property修饰的price方法")
        return self.__price

    @price.setter
    def price_test(self, price):
        if price < 0:
            price = 0
        print("调用了: @price.setter修饰的price方法")
        self.__price = price

# 创建一个Car类型的对象
c = Car()
c.price = 100000
print("小汽车的价格:price = ", c.price)

运行结果:

Traceback (most recent call last):
  File "F:/python_projects/oop/23SmartPhone.py", line 71, in <module>
    c.price = 100000
AttributeError: can't set attribute

这样尝试修饰的方法一个为:price,一个为price_test让方法名不同后,再给price赋值时,就会报错AttributeError: can't set attribute。并且编译器会提示:

修饰的方法名不相同时的提示语

小结

@property广泛应用在Python类的定义中非常常见。这即可以让调用者写出简短的代码,同时又起到了对参数进行必要的检查,这样程序运行时就减少了出错的可能性,这一节知识务必熟练掌握。


更多了解,可关注公众号:人人懂编程


微信公众号:人人懂编程

相关文章

  • 25.Python编程:@property详解

    在前面学习访问权限一文中,我们设计了一个SmartPhone类, 如果你观察的足够仔细,你会发现,例子中我们属性只...

  • python @property

    参考 Python进阶之“属性(property)”详解 - Python - 伯乐在线

  • iOS开发---属性关键字详解

    iOS开发—属性关键字详解 @Property 什么是属性? 属性(property)是Objective-C的一...

  • python元编程详解

    注:采转归档,自己学习查询使用 python元编程详解(1)python元编程详解(2)python元编程详解(3...

  • property and ivar 详解

    property and ivar 详解 简述 ivar 全名叫做 instance variable, 即实例变...

  • Masonry 控件详解

    Masonry 控件详解 1.Masonry的属性 @property (nonatomic,strong,rea...

  • CAEmitterLayer-粒子效果属性记录

    CAEmitterLayer---属性详解 /*这里面是粒子发射单元的集合. */ @property(nulla...

  • iOS property详解

    property是OC的一项特性,主要的作用在于封装对象中的数据。官方文档对property的定义是: A dec...

  • @property 详解1

    我们申请一个类,在这个类如Person的时候申请一个属性,我们习惯性使用@property,如: @propert...

  • @property 详解2

    @property 详解1讲解了@property内部做了的3件事以及它的两个属性的作用。 下面我们讲解一下修饰词...

网友评论

    本文标题:25.Python编程:@property详解

    本文链接:https://www.haomeiwen.com/subject/kwhslftx.html