The following methods can be defined to customize the meaning of attribute access (use of, assignment to, or deletion of x.name) for class instances.
- 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).
例子(Python Recipe6.1):
class Temperature(object):
coefficients = {'c': (1.0, 0.0, -273.15), 'f': (1.8, -273.15, 32.0),
'r': (1.8, 0.0, 0.0)}
def __init__(self, **kwargs):
# default to absolute (Kelvin) 0, but allow one named argument,
# with name being k, c, f or r, to use any of the scales
try:
name, value = kwargs.popitem()
except KeyError:
# no arguments, so default to k=0
name, value = 'k', 0
# error if there are more arguments, or the arg's name is unknown
if kwargs or name not in 'kcfr':
kwargs[name] = value # put it back for diagnosis
raise TypeError, 'invalid arguments %r' % kwargs
setattr(self, name, float(value))
def __getattr__(self, name):
# maps getting of c, f, r, to computation from k
print '__getattr__: %s' % str(name)
try:
eq = self.coefficients[name]
except KeyError:
# unknown name, give error message
raise AttributeError, name
return (self.k + eq[1]) * eq[0] + eq[2]
def __setattr__(self, name, value):
# maps settings of k, c, f, r, to setting of k; forbids others
print '__setattr__: name = %s, value = %s' % (str(name), str(value))
if name in self.coefficients:
# name is c, f or r -- compute and set k
eq = self.coefficients[name]
self.k = (value - eq[2]) / eq[0] - eq[1]
elif name == 'k':
# name is k, just set it
object.__setattr__(self, name, value)
else:
# unknown name, give error message
raise AttributeError, name
def __str__(self):
# readable, concise representation as string
return "%s K" % self.k
def __repr__(self):
# detailed, precise representation as string
return "Temperature(k=%r)" % self.k
if __name__ == '__main__':
t = Temperature(f=70)
print t.__dict__
print t.c
print t.f
print t.k
输出为:
simplyzhao@simplyzhao-laptop:~/code/python$ ./recipe2ed_6_1.py
__setattr__: name = f, value = 70.0
__setattr__: name = k, value = 294.261111111
{'k': 294.26111111111106}
__getattr__: c
21.1111111111
__getattr__: f
70.0
294.261111111