元类
object是类的基类,type是类的元类
type
类的类
class Foo: pass print(type(Foo)) # <class 'type'>
我们可以通过type来实例一个类,一个类创建的过程就是类的类被调用的过程
def fn(self, name='world'): # 假如我们有一个函数叫fn print('Hello, %s.' % name) Hello = type('Hello', (object,), dict(say_hello=fn)) # 第一个参数是类名字,第二个参数是父类的集合, # 第三个参数是类的方法和属性的字典,键是属性或方法名, # 上面的写法就相当于 class Hello(): def say_hello(self, name='world'): print('Hello, %s.' % name)
上面的类并没有声明自己的元类,默认就是type,
class Moo(type): pass class Aoo(): pass class Foo(metaclass=Moo): pass print(type(Moo)) # <class 'type'> print(type(Aoo)) # <class 'type'> print(type(Foo)) # <class '__main__.Moo'>
另外还有很重要的一点,一个类继承了指定元类的类,那么这个类的元类就会是继承类的元类
定义了metaclass的类的子类
在python2中元类的定义时作为类的属性
class Moo(type): pass class Foo(): __metaclass__ = Moo
当一个类继承了Foo时,会向上查找到__metaclass__属性,也就会由__metaclass__指定的类来实例类.
在python3中虽然metaclass是由参数传递的,但他同样拥有这样的性质,一个类继承了指定metaclass的类,都会有指定的metaclass产生.
class a(type): def __init__(self,*args,**kwarsg): print("造了个类") type.__init__(self,*args,**kwarsg) class c(metaclass=a): # 造了个类 pass class d(c): # 造了个类 pass class b(d): # 造了个类 pass
我们也可以通过继承type来重写元类来控制类的产生
自定义的元类也要接收三个参数
同时也要了解一下类的一些方法:
- __new__: 对象的创建,是一个静态方法。第一个參数是cls。(想想也是,不可能是self,对象还没创建,哪来的self)
- __init__ : 对象的初始化, 是一个实例方法,第一个參数是self。
- __call__ : 实例可call。注意不是类,是实例。
先有创建,才有初始化。即先__new__,而后__init__。
class Aoo(): def __call__(self): return "haha" a = Aoo() print(a()) # 哈哈哈
一个简单实例
class a(type): def __new__(cls, *args, **kwargs): print(args) # ('b', (), {'__module__': '__main__', '__qualname__': 'b'}) print(kwargs) # {} return type.__new__(cls, *args, **kwargs) def __init__(cls, name, bases, attrs): type.__init__(cls, name, bases, attrs) print("造了个类") def __call__(cls): type.__call__(cls) print("实例了个类") class b(metaclass=a): # 造了个类 pass b() # 实例了个类
根据__call__实现单例模式:
既然类是元类的实例,那么类被实例化时就就执行了元类的__call__方法,我们可以根据这个来实现单例模式的类
class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): # 他的实例化出来的类实例化时调用了这个方法, if cls not in cls._instances: # 如果这个来没有实例化对象,就去执行type的__call__方法,并且把实例存储在cls._instances中 cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] # 返回实例 class MyClass(metaclass=Singleton): pass a = MyClass()
还可以
MyClass = Singleton("MyClass",(object,),{"name":"pa"}) a = MyClass() b = MyClass() print(a is b) # True
更多方法我也不会