property()函数和@property装饰器¶
property()函数¶
我们一直使用对象.属性的方式访问类中定义的属性, 其实这种做法是欠妥的, 因为它破坏了封装的原则.
正常情况下, 类包含的属性应该是隐藏的, 只允许通过类提供的方法来间接实现对类属性的访问和操作.
因此, 在不破坏类封装原则的基础上, 为了能够有效操作类中的属性, 类中应包含读/写类属性的多个getter/setter方法, 这样就可以通过对象.方法的方式操作属性.
但是这样的操作比较繁琐, 没有直接使用对象.属性方便.
Python中提供了property()函数, 可以在不破坏类的封装原则的前提下, 依然可以使用对象.属性的方式操作类中的属性.
property()函数的基本使用格式如下:
属性名 = property(fget=None, fset=None, fdel=None, doc=None)
其中, fget参数用于指定获取该属性值的方法, fset参数用于指定设置该属性值的方法,
fdel参数用于指定删除该属性值的方法, 最后的doc是该属性的文档字符串.
- 如果指定了
fget, 则该属性是可读的;- 如果指定了
fset, 则该属性是可写的;- 如果指定了
fdel, 则该属性是可删除的.
Example:
class Student:
# 构造函数
def __init__(self, name):
self.__name = name
# name属性的setter
def setname(self, name):
self.__name = name
# name属性的getter
def getname(self):
return self.__name
# name属性的deleter
def delname(self):
self.__name = 'xxx'
name = property(fget=getname, fset=setname, fdel=delname, doc='hello')
# 显示属性的文档字符串的两种方式
print(Student.name.__doc__)
help(Student.name)
s1 = Student('sylar')
# 调用getname()方法
print(s1.name)
# 调用setname()方法
s1.name = 'John'
print(s1.name)
# 调用delname()方法
del s1.name
print(s1.name)
需要注意的是, 在上面的代码中, getname()方法中需要返回name属性, 如果使用self.name的话, 其本身又将调用getname(),这样会进入无限递归.
为了避免这种情况, 代码中的name属性必须设置为私有属性, 即使用__name.
注解
在没有为属性设置property()函数之前, 对属性读/写/删除, 都是直接对属性的操作.
为属性设置了property()函数之后, 对属性的读/写/删除, 都是调用property()函数中定义的方法.
@property装饰器¶
除了使用property()函数之外, Python还提供了@property装饰器.
通过@property装饰器, 可以定义属性并同时定义该属性的getter方法.
@property的语法格式如下:
@property
def 属性名(self):
代码块
- setter装饰器
使用@property装饰器定义一个属性之后, 可以使用setter装饰器定义该属性的setter方法.
@属性名.setter
def 属性名(self, value):
代码块
- deleter装饰器
使用@property装饰器定义一个属性之后, 可以使用deleter装饰器定义该属性的deleter方法.
@属性名.deleter
def 属性名(self):
代码块
Example:
class Student:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
@name.deleter
def name(self):
self.__name = 'xxx'
s1 = Student('sylar')
# 调用getter方法
print(s1.name)
# 调用setter方法
s1.name = 'John'
print(s1.name)
# 调用deleter方法
del s1.name
print(s1.name)