参考文档:
https://zhuanlan.zhihu.com/p/149126959
https://www.cnblogs.com/tkqasn/p/6524879.html
https://blog.csdn.net/a2011480169/article/details/87891753
什么是元类
type是Python的一个内建元类,用来直接控制生成类,在python当中任何class定义的类其实都是type类实例化的结果。
只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类,自定义元类可以控制类的产生过程,类的产生过程其实就是元类的调用过程。元类的主要目的是为了控制类的创建行为。
type、class和object的关系
在Python面向对象当中,所有的类的根本来源就是type。也就是说Python当中的每一个类都是type的实例。
使用type动态创建类
一个类由三大组成部分,分别是:
- 类名class_name
- 继承关系class_bases
- 类的名称空间class_dict
type的帮助信息:
type除了可以查看一个对象的类型,还可以用来创建类:type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
构建类
#构建目标代码
class Foo(object):
bar = True
#使用type构建
Foo = type('Foo', (), {'bar':True})
继承类
# 构建目标代码:
class FooChild(Foo):
pass
# 使用type构建
FooChild = type('FooChild', (Foo,),{})
绑定方法
# 构建目标代码:
class FooChild(Foo):
def echo_bar(self):
print(self.bar)
# 使用type构建
def echo_bar(self):
print(self.bar)
FooChild = type('FooChild', (Foo, ), {'echo_bar': echo_bar})
绑定静态方法、类方法
# 构建目标代码:
class TestClass():
@classmethod
def test_classmethod(cls):
print('classmethod')
def test(self):
print('test')
@staticmethod
def test_staticmethod():
print('staticmethod')
# 使用type构建
@classmethod
def test_classmethod(cls):
print('classmethod')
def test(self):
print('test')
@staticmethod
def test_staticmethod():
print('staticmethod')
TT = type('TestClass', (), {'test_staticmethod': test_staticmethod, 'test':test, 'test_classmethod': test_classmethod})
自定义元类
class Foo(object): # py2
__metaclass__ = something…
class Foo(metaclass=something): # py3
__metaclass__ = something…
class Mymeta(type):
def __init__(self, name, bases, dic):
super().__init__(name, bases, dic)
print('===>Mymeta.__init__')
print(name) # 类名
print(bases) # 父类的元组(针对继承的情况,可以为空)
print(dic) # 包含属性的字典(名称和值)
print(self.yaml_tag) # 打印特定属性
def __new__(cls, *args, **kwargs):
print('===>Mymeta.__new__')
print(cls.__name__)
return type.__new__(cls, *args, **kwargs)
def __call__(cls, *args, **kwargs):
print('===>Mymeta.__call__')
obj = cls.__new__(cls)
cls.__init__(cls, *args, **kwargs)
return obj
class Foo(metaclass=Mymeta):
yaml_tag = '!Foo'
def __init__(self, name):
print('Foo.__init__')
self.name = name
def __new__(cls, *args, **kwargs):
print('Foo.__new__')
return object.__new__(cls)
def __call__(cls, *args, **kwargs):
print('FOO.__call__')
def test(text):
print(text)
# Foo = Mymeta('Foo', (), {'yaml_tag ': '!Foo', '__init__': __init__, '__new__': __new__, '__call__': __call__, 'test': test})
print('------------实例化--------------')
foo = Foo('foo')
foo()
输出结果:
===>Mymeta.__new__
Mymeta
===>Mymeta.__init__
Foo
()
{'__module__': '__main__', '__qualname__': 'Foo', 'yaml_tag': '!Foo', '__init__': <function Foo.__init__ at 0x7fd0383c78c8>, '__new__': <function Foo.__new__ at 0x7fd0383c7c80>, '__call__': <function Foo.__call__ at 0x7fd0383c79d8>, 'test': <function Foo.test at 0x7fd0383c7bf8>}
!Foo
------------实例化--------------
===>Mymeta.__call__
Foo.__new__
Foo.__init__
FOO.__call__
使用元类实现单例
import threading
import time
# 普通类
class Foo():
def __init__(self):
print('init!!')
self.log_time = time.time()
# 单例元类
class SingletonType(type):
_instance_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
with SingletonType._instance_lock:
if not hasattr(cls, "_instance"):
cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
return cls._instance
# 使用单例元类
class FooSingleton(metaclass=SingletonType):
def __init__(self):
print('init!!')
self.log_time = time.time()
# 普通任务
def task(arg):
obj = Foo()
print(obj.log_time)
print('普通类实例化')
for i in range(5):
t = threading.Thread(target=task,args=[i,])
t.start()
# 单例任务
def task_single(arg):
obj = FooSingleton()
print(obj.log_time)
print('单例')
for i in range(5):
t = threading.Thread(target=task_single,args=[i,])
t.start()
输出结果:
普通类实例化
init!!
1638345526.2971504
init!!
1638345526.29774
init!!
1638345526.2979605
init!!
1638345526.2982018
init!!
1638345526.2983775
单例
init!!
1638345526.2985206
1638345526.2985206
1638345526.2985206
1638345526.2985206
1638345526.2985206