python 元类

元类

# 定义类
class Foo(object):
    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        data = object.__new__(cls)
        return data


# 根据类创建对象
# 1.先执行类的__new__方法,创建对象(空对象)。  [构造方法]  {}
# 2.执行类的__init__方法,初始化对象。        [初始化方法] {"name":"lem"}
obj = Foo("lem")

对象是基于类创建的。

问题:类是由谁创建的?

类默认是由type创建。
# 传统方式创建类 
class Foo(object,metaclass=type):  # 默认继承object,默认metaclass=type,可以不写
    v1 = 123

    def func(self):
        return 666
print(Foo)=====><class '__main__.Foo'>

# 非传统方式(一行)
Fa = type('Foo', (object,), {'v1': 123, 'func': lambda self: 666})
# 创建者(类名,继承关系,成员)
print(Fa)=====><class '__main__.Foo'>
# 由谁创建就是实例化谁的对象,所以Fa就是type的实例化对象
def do(self):
    pass


# 非传统方式(一行)
# 1.创建类型
#         -类名   -继承关系    -成员
Fa = type('Foo', (object,), {'v1': 123, 'func': lambda self: 666, "do": do})

# 2.根据类创建对象
obj = Fa()

# 3.调用对象中v1变量(类变量)
print(obj.v1)

# 4.执行对象的func方法
res = obj.func()
print(res)

类默认由type创建,怎么让一个类的创建改成其他的东西?元类

元类:指定类由谁来创建。

# type创建Foo类型
class Foo(object,metaclass=type):
    pass
# `东西` 创建Foo类型
class Foo(object,metaclass=`东西`):
	pass
class F1:
    def __init__(self):
        print("init")

    def __call__(self, *args, **kwargs):
        print("call")


obj = F1()  # 类加()会执行__new__和__init__方法
obj()  # 对象加()会自动执行__call__方法
class MyType(type):
    def __init__(self, *args, **kwargs):
        print("MyType init")
        super().__init__(*args, **kwargs)

    def __new__(cls, *args, **kwargs):
        # 创建类
        print("MyType new")
        # 调用自己类中的__new__方法
        new_class = super().__new__(cls, *args, **kwargs)
        return new_class

    def __call__(self, *args, **kwargs):
        print("MyType call")
        # 1.调用你自己那个类的__new__方法去创建对象
        empty_obj = self.__new__(self)

        # 2.调用你自己那个类的__init__方法去初始化
        self.__init__(empty_obj, *args, **kwargs)

        return empty_obj

# 假设Foo是一个对象,由MyType创建。
# Foo类其实是MyType的一个对象
# Foo()————> MyType对象()
class Foo(object, metaclass=MyType):
    def __init__(self, name):
        print("Foo init")
        self.name = name
	def __call__(self, *args, **kwargs):
        print("自己")
    

# Foo类由MyType创建

v1 = Foo('lem')
print(v1)
print(v1.name)

wtforms源码

from wtforms import Form
from wtforms.fields import simple


class FormMeta(type):
    def __init__(cls, name, bases, attrs):
        type.__init__(cls, name, bases, attrs)
        cls._unbound_fields = None
        cls._wtforms_meta = None

    def __call__(cls, *args, **kwargs):
        if cls._unbound_fields is None:
            fields = []
            for name in dir(cls):
                if not name.startswith('_'):
                    unbound_field = getattr(cls, name)
                    if hasattr(unbound_field, '_formfield'):
                        fields.append((name, unbound_field))
            # We keep the name as the second element of the sort
            # to ensure a stable sort.
            fields.sort(key=lambda x: (x[1].creation_counter, x[0]))
            cls._unbound_fields = fields

        # Create a subclass of the 'class Meta' using all the ancestors.
        if cls._wtforms_meta is None:
            bases = []
            for mro_class in cls.__mro__:
                if 'Meta' in mro_class.__dict__:
                    bases.append(mro_class.Meta)
            cls._wtforms_meta = type('Meta', tuple(bases), {})
        return type.__call__(cls, *args, **kwargs)


def with_metaclass(meta, base=object):
    #      FormMeta("NewBase",(BaseForm,), {})
    #          type("NewBase",(BaseForm,), {})
    return meta("NewBase", (base,), {})


class NewBase(BaseForm, metaclass=FormMeta):
    pass


class Form(NewBase):
    pass


class Form(with_metaclass(FormMeta, BaseForm)):
    pass


# LoginForm是由FormMeta 创建的。
#  1.创建类时,会执行 FormMeta的 __new__ 和 __init__ 内部在类中添加了两个类变量:cls._unbound_fields = None、cls._wtforms_meta = None
class LoginForm(Form):
    name = simple.StringField(label='用户名', render_kw={'class': 'form-control'})
    pwd = simple.PasswordField(label='密码', render_kw={'class': 'form-control'})


#  2.根据LoginForm去创建对象。 会先执行FormMeta.__call__方法
#    返回 return type.__call__(cls, *args, **kwargs)——>本质是调用LoginForm的__new__去创建对象,__init__去初始化对象
form = LoginForm()

print(form.name)  # 类变量
print(form.pwd)  # 类变量

# 问题1:此时的LoginForm是由 type or FormMeta创建?
"""
类中metaclass,自己类由metaclass定的类来创建
类继承某个类,父类metaclass,自己类由metaclass定义的类来创建

class NewBase(BaseForm, metaclass=FormMeta):
    pass

class Form(NewBase):
    pass
等价于
class Form(with_metaclass(FormMeta, BaseForm)):
    pass
======>
所以Form是由父类NewBase的metaclass定义的类FormMeta创建
"""

学了元类之后,在:

  • 类创建,自定义功能。
  • 对象创建前后,自定义功能。
class MyType(type):
    def __init__(self, *args, **kwargs):
        # 创建类时,进行扩展
        
        print("MyType init")
        super().__init__(*args, **kwargs)

    def __new__(cls, *args, **kwargs):
        # 创建类时,进行扩展
        
        print("MyType new")
        # 调用自己类中的__new__方法
        new_class = super().__new__(cls, *args, **kwargs)
        return new_class

    def __call__(self, *args, **kwargs):
        # 创建对象时,进行扩展
        
        print("MyType call")
        # 1.调用你自己那个类的__new__方法去创建对象
        empty_obj = self.__new__(self)

        # 2.调用你自己那个类的__init__方法去初始化
        self.__init__(empty_obj, *args, **kwargs)

        return empty_obj

# 假设Foo是一个对象,由MyType创建。
# Foo类其实是MyType的一个对象
# Foo()————> MyType对象()
class Foo(object, metaclass=MyType):
    def __init__(self, name):
        print("Foo init")
        self.name = name


# Foo类由MyType创建

v1 = Foo('lem')
print(v1)

单例模式

  • 方式1:模块导入
  • 方式2:并发编程
  • 方式3:单例模式
class MyType(type):
    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)
        cls.instance = None

    def __call__(cls, *args, **kwargs):
        # 1.判断是否已有对象,有,则不创建,没有则创建
        if not cls.instance:
            # 调用自己那个类的__new__创建对象
            cls.instance = cls.__new__(cls)

        # 2.调用你自己那个类的__init__方法去初始化
        cls.__init__(cls.instance, *args, **kwargs)

        return cls.instance


class Singleton(object, metaclass=MyType):
    pass


class Foo(Singleton):
    # # 类变量,创建的对象
    # instance = None
    pass


# print(Foo.instance)
# v1 = Foo()

"""
创建v1=Foo()时会先执行父类的创建类的__new__以及__init__方法初始化
此时Foo中instance=None接着Foo()会继续执行__call__方法
if not cls.instance: 判断是否已有对象
没有则cls.instance = cls.__new__(cls) 调用自己那个类的__new__创建对象
有则不创建对象
cls.instance = cls.__new__(cls) 调用你自己那个类的__init__方法去初始化
return cls.instance 最终返回该对象
"""
v1 = Foo()  # 真正去创建对象并设置instance并返回
v2 = Foo()

print(v1)  # 内存地址
print(v2)  # 内存地址
>>>>>>>>
<__main__.Foo object at 0x000002A87F2DBFA0>
<__main__.Foo object at 0x000002A87F2DBFA0>

"==================================================================================="

class Foo(Singleton):
    # # 类变量,创建的对象
    # instance = None
    def __init__(self, name):
        self.name = name

v1 = Foo('lem')  # 真正去创建对象并设置instance并返回
v2 = Foo('hina')

print(v1.name)  # 内存地址
print(v2.name)  # 内存地址
>>>>>>>>
hina
hina
posted @ 2021-04-26 15:08  橘丶阳菜  阅读(58)  评论(0编辑  收藏  举报