在Java中,一般在类中定义的成员变量为私有变量,在类的实例中不能直接经过对象.属性
直接操做,而是要经过getter和setter来操做私有变量。
而在Python中,由于有property这个概念,因此不须要写getter和setter一堆重复的代码来操做私有变量。Python“私有变量”一般在变量前加上“_”或者“__”,例如_attr
或者__attr
,这是约定俗成的规范。python
class MyClass: def __init__(self, x): self._x = x
这里定义了一个MyClass
类,它有一个实例变量_x
,绑定了用户传来的x值。_x
是私有变量,经过obj._x
获取私有变量不符合语言规范,进而咱们要使_x
变成property(特性),经过obj.x
直接访问。函数
改造后的代码以下:性能
class MyClass: def __init__(self, x): self._x = x @property def x(self): return self._x >>> obj = MyClass(10) >>> obj.x 10
咱们把_x
变成了property特性,以只读的方式获取x的值。code
咱们如今想为x赋值该怎样作呢?对象
>>> obj.x = 999 Traceback (most recent call last): File "xxx", line 14, in <module> obj.x = 23 AttributeError: can't set attribute
能够看到,抛出了AttributeError: can't set attribute。显然,只读方法不支持赋值。文档
咱们只须要在上述代码改形成:get
class MyClass: def __init__(self, x): self._x = x @property def x(self): return self._x @x.setter def x(self, value): self._x = value >>> obj = MyClass(10) >>> obj.x = 999 >>> obj.x 999
能够看到,咱们为x添加了setter,能够直接为obj.x
赋值操做it
继续上面的代码,咱们看看如下的操做:ast
>>> obj = MyClass(10) >>> obj.__dict__ {'_x': 999} #此时实例变量中有_x的值 >>> obj.__dict__['x'] = 99999 #设置obj的实例变量有x值,跟property属性重名! >>> obj.__dict__ {'_x': 999, 'x': 99999} #此时实例变量中有_x和x的值 >>> obj.x #结果是obj的实例变量仍是property属性? 10
如上代码所示,obj对象有一个_x实例变量和一个x的property属性,咱们又强行为obj增长了一个x实例变量,这个实例变量x和property属性x同名!
经过obj.x
咱们得知,返回的是property属性,说明property属性会遮盖实例属性!也能够理解为property属性的优先级更大!class
咱们一般使用内置的@property装饰器。但其实property是一个类,python中类和函数的调用方式都差很少,他们都是可调用对象
property的构造方法以下:
class property(object): def __init__(self, fget=None, fset=None, fdel=None, doc=None): """"""
它最大接受4个参数,均可觉得空。
第一个为getter,第二个为setter,第三个为delete函数,第四个为文档。
上述代码的另外一种写法
class MyClass: def __init__(self, x): self._x = x def get_x(self): return self._x def set_x(self, value): self._x = value x = property(get_x, set_x) >>> obj = MyClass(10) >>> obj.x 10
如上,x
是property的实例,设置了getter和setter,做为类变量放在MyClass类中。
以上就是property属性的解析。