在python中可以基于类创建对象
# 定义类
class Foo(object):
def __init(self, name):
self.name = name
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
obj = Foo("lucky") # lucky
#根据类创建对象时程序内部的实际步骤
- 执行类的new方法,创建空对象 【构造方法】
- 执行类的init方法,初始化对象 【初始化方法】
可以看出对象是由类创建的,那么类是由谁创建的呢?
答:类默认是由type创建的
# 传统方法创建类
class Foo(object):
v1 = 123
def func(self):
return 666
# 非传统方式创建类(一行)
# 创建类型 类名 继承类 成员
Fa = type("Foo", (object,),{"v1":123,"func":lambda self:666})
# 根据类创建对象
obj = Fa()
# 调用v1的变量(类变量)
print(obj.v1) # 123
# 执行对象中的func方法
result = obj.func() # 666
可以看出type是可以创建类的,那怎么让一个类的创建改成其他的东西呢?
这个时候就引出了元类
元类
: 创建类的类
# type 创建Foo类
class Foo(object):
pass
# 其他东西创建Foo类
class Foo(object, metaclass=其他东西):
pass
那么现在我们就可以创建一个类继承type,再创建另一个类继承前一个类
class MyType(type):
pass
class Foo(object, metaclass=MyType):
pass
# Foo类由MyType创建
这时候其实可以把Foo
假设成一个由MyType
创建的对象,那我们在创建Foo
类时也就是在执行MyType
类中的new
和init
方法
接下来我们可以在MyType
类中写一些方法验证一下调用关系和执行顺序
class MyType(type):
def __init__(self, *args, **kargs):
print('init')
super().__init__(cls, *args, **kwargs)
def __new__(cls, *args, **kwargs):
print('new')
new_cls = super().__new__(cls, *args, **kwargs)
return new_cls
def __call__(self, *args, **kwargs):
# 调⽤⾃⼰的那个类 __new__ ⽅法去创建对象
empty_object = self.__new__(self)
# 调⽤你⾃⼰的__init__ ⽅法去初始化
self.__init__(empty_object, *args, **kwargs)
return empty_object
class Foo(object, metaclass=MyType):
def __init__(self, name):
self.name = name
# 假设Foo是⼀个对象 由MyType创建
# Foo其实是MyType的⼀个对象
# Foo() -> MyType对象()
# 对象+()实际执行就是继承类的__call__方法
v1 = Foo("lucky") # 等价于MyTpe.__call__ 结果为 new init
print(v1.name) # lucky
在学习元类之后,我们可以在
- 类创建时自定义功能(
__new__
,__init__
) - 对象创建前后自定义功能(
__call__
)
拓展(元类实现单例模式):
class MyType(type):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.instance = None
def __call__(self, *args, **kwargs):
# 判断是否有对象,有则不创建,没有则创建
if not self.instance:
self.instance = self.__new__(self)
# 初始化
self.__init__(self.instance, *args, **kwargs)
return self.instance
class Singleton(object, metaclass=MyType):
pass
class Foo1(Singleton):
pass
v1 = Foo1()
v2 = Foo1()
print(v1)
print(v2)