欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python属性访问

程序员文章站 2022-07-15 22:20:26
...

1. 使用特殊函数__getattribute__,__getattr__,__setattr__,__delattr__

当想要获得(get)属性时,先访问__getattribute__,如果对象不存在该属性,则继续访问__getattr__

当定义或者修改一个属性时,访问__setattr__

当删除一个属性时,访问__delattr__

>>> class C:
    def __init__(self,name='zzw'):
        self.name = name
    def __getattribute__(self,name):   
        print('getattribute')
        return super().__getattribute__(name)
    def __getattr__(self,name):
        print('getattr')
    def __setattr__(self,name,value):
        print('setattr')
        super().__setattr__(name,value)
    def __delattr__(self,name):
        print('delattr')
        super().__delattr__(name)

        
>>> c = C()
setattr
>>> c.name
getattribute
'zzw'
>>> c.x
getattribute
getattr
>>> c.x = 1
setattr
>>> del c.x
delattr

2. 注意一个陷进:定义/修改属性时递归调用自身,从而进入无限循环。

这是因为在__init__中,self.width=width会调用__setattr__方法,name不是‘square’,故执行else语句self.name=value,这还是一条赋值语句,继续调用__setattr__函数。这样调用自身的递归就会运行出错。

>>> class Rectangle:
	def __init__(self,width=0,height=0):
	    self.width = width
	    self.height = height
	def __setattr__(self,name,value):
	    if name == 'square':
		    self.width = value
		    self.height = value
	    else:
		    self.name = value
	def getArea(self):
	    return self.width*self.height

	
>>> r = Rectangle()
Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    r = Rectangle()
  File "<pyshell#41>", line 3, in __init__
    self.width = width
  File "<pyshell#41>", line 10, in __setattr__
    self.name = value
  File "<pyshell#41>", line 10, in __setattr__
    self.name = value
  File "<pyshell#41>", line 10, in __setattr__
    self.name = value
  [Previous line repeated 325 more times]
  File "<pyshell#41>", line 6, in __setattr__
    if name == 'square':
RecursionError: maximum recursion depth exceeded in comparison
解决方法有两个:

第一是把self.name = value这句改为super().__setattr__(name,value),父类的__setattr__函数是封装正确的,运行不会出错

第二是把self.name = value这句改为self.__dict__[name] = value