最开始时,我们总是将属性作为一个直接可访问的属性。当后续需要对这个属性的访问进行一些控制时,我们可以将其修改为函数触发式属性。在修改前后,调用这个对象属性的代码不用修改,因为还是使用相同的语法来访问这个属性。
可以使用@property 装饰器将一个直接访问的属性转变为函数触发式属性。如下所示,使用@property前的代码为
class Person: def __init__(self, name): self.name = name person = Person("Tom") print(person.name)
代码的输出为:
Tom
此时为直接访问 name
这个属性。当我们需要确保 name
是一个字符串时,可以使用 @property 装饰器将属性转变为一个函数调用,如下所示。
class Person: def __init__(self, name): self.name = name @property def name(self): print("get name called") return self._name @name.setter def name(self, name): print("set name called") if not isinstance(name, str): raise TypeError("Expected a string") self._name = name person = Person("Tom") print(person.name)
代码的输出为:
set name called get name called Tom
可以看出
- 在创建Person对象时(代码的倒数第二行), 用于set name的函数被调用。这个函数会检查输入是否为一个字符串,如不是则raise一个TypeError
- 在获取属性时(代码的最后一行),用于get name的函数被调用
- 在修改前后,使用Person类的代码完全相同
总结
Python中对象访问的语法即可能是直接访问这个属性,也可能是调用一个函数,这取决于类的实现方式。我们可以在不修改调用者代码的前提下,轻松切换这两种方式。可见python原生就提供了添加额外getter和setter所带来的好处。因此没有必要一开始就为对象属性编写getter和setter函数,而是在需要时切换到函数调用式属性。