记录一次python编程中遇见的错误,加深对类和对象、属性和方法的理解
注意: python是动态语言,属性和方法可以随时添加与修改。且python没有重载,重写函数会导致函数的覆盖。使用装饰器后可以吧方法装饰成属性,此时可以创建同名的不同方法,但是这些方法的装饰器必须有差异。
class Person():
def __init__(self, name, age):
self._name = name
self._age = age
# @property
def name(self):
return self._name
# @property
def age(self):
return self._age
# @age.setter
def age(self, value):
# 由于没使用装饰器。该方法会将age(self)方法覆盖
self._age = value
person = Person('yann', 12)
# print(person.age()) # ERROR,因为age(self)方法已经被覆盖
person.age(18) # 调用了age(self, value)方法,将年龄设置为18
print(person.age) # 输出person对象age()方法的地址
person.newage = 18 # person对象本来没有age属性(__init__方法只初始化了_name和_age属性),本操作为person对象添加了一个名字为newage的属性
person.age = 18 # 此操作修改了person的age属性,本身该属性指向了一个函数的地址,此操作将其值修改为18
# person.age(10) # ERROR,'int' object is not callable。age属性已经被修改成18了,导致age(self, value)方法不能再被调用。该错误反映出不能有同名的属性和方法,否则会发生覆盖,无法正常使用。
显然,这种可以随时添加对象所拥有的属性的操作可能带来风险。如果我们需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义__slots__变量来进行限定。需要注意的是__slots__的限定只对当前类的对象生效,对子类并不起任何作用。
例子:
class Person():
__slots__ = ('_name', '_age')
def __init__(self, name, age):
self._name = name
self._age = age
def add_property(self, pro):
self._pro = pro
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, value):
self._age = value
def main():
person = Person('yann', 12)
person.age = 18
# person._name = 'qu' # 也可以直接访问该属性。毕竟不是真正的私有
person.add_property(123) # ERROR,'Person' object has no attribute '_pro'