预计阅读本页时间:-
Instance Versus Class Attributes
If you study the classtools module’s self-test code long enough, you’ll notice that its class displays only instance attributes, attached to the self object at the bottom of the inheritance tree; that’s what self’s __dict__ contains. As an intended consequence, we don’t see attributes inherited by the instance from classes above it in the tree (e.g., count in this file’s self-test code). Inherited class attributes are attached to the class only, not copied down to instances.
If you ever do wish to include inherited attributes too, you can climb the __class__ link to the instance’s class, use the __dict__ there to fetch class attributes, and then iterate through the class’s __bases__ attribute to climb to even higher superclasses (repeating as necessary). If you’re a fan of simple code, running a built-in dir call on the instance instead of using __dict__ and climbing would have much the same effect, since dir results include inherited names in the sorted results list:
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
>>> from person import Person
>>> bob = Person('Bob Smith')
# In Python 2.6:
>>> bob.__dict__.keys() # Instance attrs only
['pay', 'job', 'name']
>>> dir(bob) # + inherited attrs in classes
['__doc__', '__init__', '__module__', '__str__', 'giveRaise', 'job',
'lastName', 'name', 'pay']
# In Python 3.0:
>>> list(bob.__dict__.keys()) # 3.0 keys is a view, not a list
['pay', 'job', 'name']
>>> dir(bob) # 3.0 includes class type methods
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__',
...more lines omitted...
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'giveRaise', 'job', 'lastName', 'name', 'pay']
The output here varies between Python 2.6 and 3.0, because 3.0’s dict.keys is not a list, and 3.0’s dir returns extra class-type implementation attributes. Technically, dir returns more in 3.0 because classes are all “new style” and inherit a large set of operator overloading names from the class type. In fact, you’ll probably want to filter out most of the __X__ names in the 3.0 dir result, since they are internal implementation details and not something you’d normally want to display.
In the interest of space, we’ll leave optional display of inherited class attributes with either tree climbs or dir as suggested experiments for now. For more hints on this front, though, watch for the classtree.py inheritance tree climber we will write in Chapter 28, and the lister.py attribute listers and climbers we’ll code in Chapter 30.