在一个类里,属性和方法有着不同的职责:属性代表状态,方法代表行为。二者对外的访问接口也不一样,属性可以通过 inst.attr 的方式直接访问,而方法需要通过inst.method()来调用。
不过,@property 装饰器模糊了属性和方法间的界限,使用它,你可以把方法通过属性的方式暴露出来。
举个例子,在动态修改实例的last_name参数后,根据last_name拼接而成的full_name是没有同步变更的。
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
self.full_name = first_name + ' ' + last_name
p = Person('张', '三')
print(p.first_name) # 张
print(p.last_name) # 三
print(p.full_name) # 张 三
p.last_name = '叁' # 动态修改属性
print(p.first_name) # 张
print(p.last_name) # 叁
print(p.full_name) # 张 三
接下来我们定义一个full_name的方法,将full_name的拼接操作放在方法中来实现。但是这样的话,我们获取full_name就只能通过调用full_name方法的方式来获取,如果我们加上@property装饰器的话,就可以继续把full_name当成属性来调用。
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def full_name(self):
return self.first_name + ' ' + self.last_name
p = Person('张', '三')
print(p.first_name) # 张
print(p.last_name) # 三
print(p.full_name) # 张 三
如果想要通过修改full_name来同步修改last_name和first_name呢?
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def full_name(self):
return self.first_name + ' ' + self.last_name
p = Person('张', '三')
print(p.first_name)
print(p.last_name)
print(p.full_name)
p.full_name = '张 叁'
print(p.first_name)
print(p.last_name)
print(p.full_name)
输出:
会提示无法修改属性。
这时候我们可以用@full_name.setter来解决这个问题。
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def full_name(self):
return self.first_name + ' ' + self.last_name
@full_name.setter
def full_name(self,name):
self.first_name, self.last_name = name.split(' ')
p = Person('张', '三')
print(p.first_name) # 张
print(p.last_name) # 三
print(p.full_name) # 张 三
p.full_name = '张 叁' # 动态修改属性
print(p.first_name) # 张
print(p.last_name) # 叁
print(p.full_name) # 张 叁
使用@full_name.setter需要注意:
1 @full_name.setter修饰的方法需要和@property 修饰的方法具有相同的名字
2 它会将用户传给property的值,作为参数
此时,当用户修改full_name的属性值时,会自动调用@full_name.setter修饰的方法。
当我们需要通过删除full_name属性来同步删除first_name和last_name时,可以使用@full_name.deleteer,代码示例如下:
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def full_name(self):
return self.first_name + ' ' + self.last_name
@full_name.setter
def full_name(self,name):
self.first_name, self.last_name = name.split(' ')
@full_name.deleter
def full_name(self):
self.first_name = None
self.last_name = None
p = Person('张', '三')
print(p.first_name) # 张
print(p.last_name) # 三
print(p.full_name) # 张 三
del p.full_name
print(p.first_name) # None
print(p.last_name) # None