yann-qu

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

记录一次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'
posted on 2021-11-22 20:47  yann-qu  阅读(30)  评论(0编辑  收藏  举报