python 对象属性与 getattr & setattr

Python对象的属性可以通过obj.__dict__获得,向其中添加删除元素就可以实现python对象属性的动态添加删除的效果,不过我们应该使用更加正规的getattr和setattr来进行这类操作

getattr(object, name[, default])

Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.

getattr可以动态的获取对象的属性,default可以指定如果名为name的属性不存在时返回的值,如果不指定而object中又没有该属性名称,则返回AttributeError

 1 >>> class Demo(object):
 2 ...     def __init__(self):
 3 ...             self.name = 'Demo'
 4 ...     def count(self):
 5 ...             return len(self.name)
 6 ...
 7 >>> X = Demo()
 8 >>> X.count()
 9 4
10 >>> getattr(X, 'count')()
11 4
12 >>> getattr(X, 'name')
13 'Demo'
14 >>> getattr(X, 'notexist')
15 Traceback (most recent call last):
16   File "<stdin>", line 1, in <module>
17 AttributeError: 'Demo' object has no attribute 'notexist'
18 >>> getattr(X, 'notexist', 'default_value')
19 'default_value'
setattr(object, name, value)

This is the counterpart of getattr(). The arguments are an object, a string and an arbitrary value. The string may name an existing attribute or a new attribute. The function assigns the value to the attribute, provided the object allows it. For example, setattr(x, 'foobar', 123) is equivalent to x.foobar = 123.

 与getattr对应,setattr用来动态的设定一个对象的属性,用来构造配置类对象内非常合适

>>> Y = Demo()
>>> setattr(Y, 'color', 'red')
>>> Y.color
'red'
View Code

当执行以上函数是类内有默认的方法进行响应,返回或者设置obj.__dict__中的属性,我们可以定义自己的这类函数,即为__getattr__, __setattr__,前者在obj.__dict__中找不到时会被调用

object.__getattr__(self, name)

Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name. This method should return the (computed) attribute value or raise an AttributeError exception.

Note that if the attribute is found through the normal mechanism, __getattr__() is not called. (This is an intentional asymmetry between __getattr__() and __setattr__().) This is done both for efficiency reasons and because otherwise __getattr__() would have no way to access other attributes of the instance. Note that at least for instance variables, you can fake total control by not inserting any values in the instance attribute dictionary (but instead inserting them in another object). See the __getattribute__() method below for a way to actually get total control in new-style classes.

object.__setattr__(self, name, value)

Called when an attribute assignment is attempted. This is called instead of the normal mechanism (i.e. store the value in the instance dictionary). name is the attribute name, value is the value to be assigned to it.

If __setattr__() wants to assign to an instance attribute, it should not simply execute self.name = value — this would cause a recursive call to itself. Instead, it should insert the value in the dictionary of instance attributes, e.g., self.__dict__[name] = value. For new-style classes, rather than accessing the instance dictionary, it should call the base class method with the same name, for example, object.__setattr__(self, name, value).

object.__delattr__(self, name)

Like __setattr__() but for attribute deletion instead of assignment. This should only be implemented if del obj.name is meaningful for the object.

通过在类中实现这些方法可以返回一些'计算'(得到的)属性

 1 >>> class Z:
 2 ...     access_cnt = {}
 3 ...     def __getattr__(self, name):
 4 ...             cnt = self.access_cnt.get(name, 0)
 5 ...             print 'access cnt:', cnt + 1
 6 ...             self.access_cnt[name] = cnt + 1
 7 ...
 8 >>> z = Z()
 9 >>> z.hello
10 access cnt: 1
11 >>> z.hello
12 access cnt: 2
13 >>> z.hello
14 access cnt: 3
15 >>> z.world
16 access cnt: 1
17 >>> z.world
18 access cnt: 2
原文地址:https://www.cnblogs.com/lailailai/p/3995474.html