-
metaclass
Metaclasses are an espteric OOP concept, lurking behind virtually all Python code.
The use of custom metaclasses is somewhat controvesial, as suggested by the following quote from Tim Peters, the Python guru who authored the Zen of Python:
Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don’t (the people who actually need them know with certainty that they need them, and don’t need an explanation about why)
Even most programmers rarely have to think about metaclasses, Still, understanding Python metaclasses is worthwhile, because it leads to a better understanding of the internals of Python classes in general. You never know: you may one day find yourself in one of those situations where you just know that a custom metaclass is what you want.
-
Old-style vs. New-Style Classes
-
old-style classes
With old-style classes, class and type are not quite the same thing. An instance of an old-style class is always implemented from a single built-in type called
instance
.If
obj
is an instance of an old-style class,obj.__class__
designates the class, buttype(obj)
is alwaysinstance
. -
new-style classes
New-style classes unify the concepts of
class
andtype
.If
obj
is an instance of a new-style class,type(obj)
is the same asobj.__class__
-
-
Type and Class
In Python3, all classes are new-style classes. Thus , in Python3 it is reasonable to refer to an object’s type and its class interchangeably.
Everything in Python is an object, a class must have a type.
>>> class Foo: ... pass ... >>> x = Foo() >>> type(x) <class '__main__.Foo'> >>> type(Foo) <class 'type'>
The type of
x
is classFoo
, But the type ofFoo
istype
always(likeint
,str
,float
, …).For the matter, the
type
oftype
istype
as well.type
is ametaclass
, of whichclasses
areinstances
. Just as an ordinary object is an instance of a class, any new-style class in Python, and thus any class in Python 3, is an instance of thetype
metaclass
.In the above case:
x
is an instance of classFoo
Foo
is an instance of thetype
metaclasstype
is also an instance of thetype
metaclass, so it is an instance of itself
-
Defining a Class Dynamically
The built-in
type()
function, when passed one argument, returns the type of an object. For new-style classes, that is generally the same as the object’s__class__
attributeYou can also call type() with three arguments –
type(<name>, <bases>, <dct>)
:<name>
specifies the class name. This becomes the__name__
attribute of the class.<bases>
specifies a tuple of the base classes from which the class inherits. This becomes the__bases__
attribute of the class.<dct>
specifies a namespace dictionary containing definitions for the class body. This becomes the__dict__
attribute of the class.
Calling
type()
in this manner creates a new instance of thetype
metaclass. In other words, it dynamically creates a new class. -
Class initialization
When the interpreter encounters a custom Class
Foo
, the following occurs:- The
__call__()
method ofFoo's
parent class is called. Which means thetype
metaclass, sotype
's__call__()
method is invoked. - The
__call__()
method in turn invokes the following:__new__()
__init__()
If
Foo
does not define__new__()
and__init__()
, default methods are inherited fromFoo
's ancestry. But ifFoo
does define these methods, they override those from the ancestry, which allows for customized behavior when instantiatingFoo
.This modifies the instantiation behavior of class
Foo
: each time an instance ofFoo
is created, by default it is initialized with an attribute calledattr
, which has a value of 100.Code like this would more usually appear in the
__inti__()
method.You can’t change the
type
's__new__()
since it’s metaclass. But you can make a custom metaclass which derives from type. - The
-
References
理解metaclass||metadata in Python
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.