__new__
方法也用于自定义元类(MetaClass),下面先来介绍MetaClass的概念。
metaclass定义为类中的类(the class of a class),Meta 起源于希腊词汇 meta,有“超越”和“改变”的意思,所以metaclass包含了“超越类”和“变形类”的含义。
先来看一个例子:
>>> class MyClass(object): data = 6
...
>>> myobject = MyClass()
>>> print(myobject.__class__)
<class '__main__.MyClass'>
>>> print(MyClass.__class__)
<class 'type'>
>>>
上面的例子中,myobject对象的类为MyClass,MyClass的类是type,也就是说myobject是一个MyClass对象,而MyClass又是一个type对象。
type就是一个元类,它是最常用的元类,是Python中所有类的默认元类,所有的 Python 的用户定义类,都是 type 这个类的实例。
元类被用来构造类(就像类用来构造对象一样)。Python类的创建过程如下:
进行类定义时,Python收集属性到一个字典中
类定义完成后,确定类的元类Meta,执行Meta(name, bases, dct)进行实例化。
可以使用type直接创建类:
>>> myobject = type('MyClass', (), {'data': 6})
>>> print(myobject.__class__)
<class 'type'>
>>> print(myobject.__name__)
MyClass
>>> print(myobject.__bases__)
(<class 'object'>,)
>>> print(myobject.data)
6
>>> print(myobject.__dict__)
{'data': 6, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}
也就是说当定义MyClass类时,真正执行的是:class = type(name, bases, dct) 语句,
如果一个类或它的一个基类有__metaclass__属性,它就被当作元类。否则,type就是元类。对元类的自定义要用到__new__ 和 __init__方法,接下来介绍元类的定义。
元类可以实现在创建类时,动态修改类中定义的属性或者方法,一般使用__new__方法来修改类属性。
下面的例子使用元类来添加属性方法:
class MyMetaClass(type):
def __new__(meta, name, bases, attrs):
print(meta, "__new__ is called")
# 动态添加属性
attrs['name'] = "zhangsan"
attrs['talk'] = lambda self: print("hello")
return super(MyMetaClass, meta).__new__(meta, name, bases, attrs)
@classmethod
def __prepare__(metacls, name, bases, **kwargs):
print(metacls, "__prepare__ is called")
return super().__prepare__(name, bases, **kwargs)
def __init__(cls, name, bases, attrs, **kwargs):
print(cls, "__init__ is called")
super().__init__(name, bases, attrs)
def __call__(cls, *args, **kwargs):
print(cls, "__call__ is called")
return super().__call__(*args, **kwargs)
class Myclass(metaclass=MyMetaClass):
pass
#学习中遇到问题没人解答?小编创建了一个Python学习交流群:725638078
if __name__ == '__main__':
cla = Myclass()
print(cla.name)
cla.talk()
print(cla.__dir__())
执行结果:
<class '__main__.MyMetaClass'> __prepare__ is called
<class '__main__.MyMetaClass'> __new__ is called
<class '__main__.Myclass'> __init__ is called
<class '__main__.Myclass'> __call__ is called
zhangsan
hello
['__module__', 'name', 'talk', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__init__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
可以看到元类MyMetaClass的__new__()
方法动态地为 Myclass 类添加了 name 属性和 talk() 方法。
在元类的创建中,可以对name, bases, attrs进行修改,实现我们想要的功能,可以使用getattr()、setattr()等Python反射函数