预计阅读本页时间:-
Type Model Changes
In new-style classes, the distinction between type and class has vanished entirely. Classes themselves are types: the type object generates classes as its instances, and classes generate instances of their type. If fact, there is no real difference between built-in types like lists and strings and user-defined types coded as classes. This is why we can subclass built-in types, as shown earlier in this chapter—because subclassing a built-in type such as list qualifies a class as new-style, it becomes a user-defined type.
Besides allowing us to subclass built-in types, one of the contexts where this becomes most obvious is when we do explicit type testing. With Python 2.6’s classic classes, the type of a class instance is a generic “instance,” but the types of built-in objects are more specific:
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
C:\misc> c:\python26\python
>>> class C: pass # Classic classes in 2.6
...
>>> I = C()
>>> type(I) # Instances are made from classes
<type 'instance'>
>>> I.__class__
<class __main__.C at 0x025085A0>
>>> type(C) # But classes are not the same as types
<type 'classobj'>
>>> C.__class__
AttributeError: class C has no attribute '__class__'
>>> type([1, 2, 3])
<type 'list'>
>>> type(list)
<type 'type'>
>>> list.__class__
<type 'type'>
But with new-style classes in 2.6, the type of a class instance is the class it’s created from, since classes are simply user-defined types—the type of an instance is its class, and the type of a user-defined class is the same as the type of a built-in object type. Classes have a __class__ attribute now, too, because they are instances of type:
C:\misc> c:\python26\python
>>> class C(object): pass # New-style classes in 2.6
...
>>> I = C()
>>> type(I) # Type of instance is class it's made from
<class '__main__.C'>
>>> I.__class__
<class '__main__.C'>
>>> type(C) # Classes are user-defined types
<type 'type'>
>>> C.__class__
<type 'type'>
>>> type([1, 2, 3]) # Built-in types work the same way
<type 'list'>
>>> type(list)
<type 'type'>
>>> list.__class__
<type 'type'>
The same is true for all classes in Python 3.0, since all classes are automatically new-style, even if they have no explicit superclasses. In fact, the distinction between built-in types and user-defined class types melts away altogether in 3.0:
C:\misc> c:\python30\python
>>> class C: pass # All classes are new-style in 3.0
...
>>> I = C()
>>> type(I) # Type of instance is class it's made from
<class '__main__.C'>
>>> I.__class__
<class '__main__.C'>
>>> type(C) # Class is a type, and type is a class
<class 'type'>
>>> C.__class__
<class 'type'>
>>> type([1, 2, 3]) # Classes and built-in types work the same
<class 'list'>
>>> type(list)
<class 'type'>
>>> list.__class__
<class 'type'>
As you can see, in 3.0 classes are types, but types are also classes. Technically, each class is generated by a metaclass—a class that is normally either type itself, or a subclass of it customized to augment or manage generated classes. Besides impacting code that does type testing, this turns out to be an important hook for tool developers. We’ll talk more about metaclasses later in this chapter, and again in more detail in Chapter 39.
Implications for type testing
Besides providing for built-in type customization and metaclass hooks, the merging of classes and types in the new-style class model can impact code that does type testing. In Python 3.0, for example, the types of class instances compare directly and meaningfully, and in the same way as built-in type objects. This follows from the fact that classes are now types, and an instance’s type is the instance’s class:
C:\misc> c:\python30\python
>>> class C: pass
...
>>> class D: pass
...
>>> c = C()
>>> d = D()
>>> type(c) == type(d) # 3.0: compares the instances' classes
False
>>> type(c), type(d)
(<class '__main__.C'>, <class '__main__.D'>)
>>> c.__class__, d.__class__
(<class '__main__.C'>, <class '__main__.D'>)
>>> c1, c2 = C(), C()
>>> type(c1) == type(c2)
True
With classic classes in 2.6 and earlier, though, comparing instance types is almost useless, because all instances have the same “instance” type. To truly compare types, the instance __class__ attributes must be compared (if you care about portability, this works in 3.0, too, but it’s not required there):
C:\misc> c:\python26\python
>>> class C: pass
...
>>> class D: pass
...
>>> c = C()
>>> d = D()
>>> type(c) == type(d) # 2.6: all instances are same type
True
>>> c.__class__ == d.__class__ # Must compare classes explicitly
False
>>> type(c), type(d)
(<type 'instance'>, <type 'instance'>)
>>> c.__class__, d.__class__
(<class __main__.C at 0x024585A0>, <class __main__.D at 0x024588D0>)
And as you should expect by now, new-style classes in 2.6 work the same as all classes in 3.0 in this regard—comparing instance types compares the instances’ classes automatically:
C:\misc> c:\python26\python
>>> class C(object): pass
...
>>> class D(object): pass
...
>>> c = C()
>>> d = D()
>>> type(c) == type(d) # 2.6 new-style: same as all in 3.0
False
>>> type(c), type(d)
(<class '__main__.C'>, <class '__main__.D'>)
>>> c.__class__, d.__class__
(<class '__main__.C'>, <class '__main__.D'>)
Of course, as I’ve pointed out numerous times in this book, type checking is usually the wrong thing to do in Python programs (we code to object interfaces, not object types), and the more general isinstance built-in is more likely what you’ll want to use in the rare cases where instance class types must be queried. However, knowledge of Python’s type model can help demystify the class model in general.
All objects derive from “object”
One other ramification of the type change in the new-style class model is that because all classes derive (inherit) from the class object either implicitly or explicitly, and because all types are now classes, every object derives from the object built-in class, whether directly or through a superclass. Consider the following interaction in Python 3.0 (code an explicit object superclass in 2.6 to make this work equivalently):
>>> class C: pass
...
>>> X = C()
>>> type(X) # Type is now class instance was created from
<class '__main__.C'>
>>> type(C)
<class 'type'>
As before, the type of a class instance is the class it was made from, and the type of a class is the type class because classes and types have merged. It is also true, though, that the instance and class are both derived from the built-in object class, since this is an implicit or explicit superclass of every class:
>>> isinstance(X, object)
True
>>> isinstance(C, object) # Classes always inherit from object
True
The same holds true for built-in types like lists and strings, because types are classes in the new-style model—built-in types are now classes, and their instances derive from object, too:
>>> type('spam')
<class 'str'>
>>> type(str)
<class 'type'>
>>> isinstance('spam', object) # Same for built-in types (classes)
True
>>> isinstance(str, object)
True
In fact, type itself derives from object, and object derives from type, even though the two are different objects—a circular relationship that caps the object model and stems from the fact that types are classes that generate classes:
>>> type(type) # All classes are types, and vice versa
<class 'type'>
>>> type(object)
<class 'type'>
>>> isinstance(type, object) # All classes derive from object, even type
True
>>> isinstance(object, type) # Types make classes, and type is a class
True
>>> type is object
False
In practical terms, this model makes for fewer special cases than the prior type/class distinction of classic classes, and it allows us to write code that assumes and uses an object superclass. We’ll see examples of the latter later in the book; for now, let’s move on to explore other new-style changes.