python高级之元类

python高级之元类

  • 一、Type创建类
    • 1、传统方式创建类
    • 2、非传统方式
  • 二、元类
  • 三、总结

一、Type创建类

class A(object):

    def __init__(self, name):
        self.name = name

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

根据类创建对象
obj=A(‘kobe’)
1、执行类的new方法,创建对象(空对象),【构造方法】 {}
2、执行类的init方法,初始化对象 ,【初始化方法】 {‘name’:‘kobe’}

对象是基于类创建出来的;问题:类是由谁创建的?
类默认是由type创建的

1、传统方式创建类

class A(object):
    v1 = 123

    def func(self):
        return 666


print(A)			#<class '__main__.A'>

2、非传统方式

类名
继承类
成员

A1 = type('A', (object,), {"v1": 123, "func": lambda self: 666})
print(A1)        #<class '__main__.A'>

# 根据类创建对象
obj1 = A1()			#<__main__.A object at 0x0000017049D035E0>
print(obj1)


# 调用对象中的func方法 
print(obj1.func())  #666

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

二、元类

元类:指定类由谁来创建

1、Foo类由MyType创建,代码如下

class MyType(type):
    pass


# Foo类由MyType创建
class Foo(object, metaclass=MyType):
    pass

2、假设Foo是一个对象,它是由MyType类创建。

class MyType(type):

    def __init__(self, *args, **kwargs):
        print('init')
        super().__init__(*args, **kwargs)

    def __new__(cls, *args, **kwargs):
        # 创建类
        print('new')
        new_cls = super().__new__(cls, *args, **kwargs)
        print(new_cls)
        return new_cls


# 假设Foo是一个对象,由MyType类创建。
class Foo(object, metaclass=MyType):
    pass

执行结果

new
<class '__main__.Foo'>
init

3、类加括号得到的是对象,执行的是__init__()和__new__()方法,对象加括号执行__call__()方法

class F1(object):
    def __init__(self):
        print('init')

    # def __new__(cls, *args, **kwargs):
    #     print('new')

    def __call__(self, *args, **kwargs):
        print(111)


# 类加括号得到的是对象,执行的是__init__和__new__方法
obj = F1()

# 对象加括号执行call方法
obj()

执行结果

init
111

4、假设Foo是一个对象,由MyType创建。
Foo类其实是MyType的一个对象。
Foo() 加括号执行的是——》MyType类中的__call__()方法

__call__()方法实现的功能是:
1、调用自己那个类的__new__方法创建对象
empty_object=self.__new__(self)
2、调用你自己那个类__init__方法去初始化对象
self.__init__(empty_object,*args,**kwargs)
3、将创建的对象返回:return empty_object

class MyType(type):

    def __init__(self, *args, **kwargs):
        print('init')
        super().__init__(*args, **kwargs)

    def __new__(cls, *args, **kwargs):
        # 创建类
        print('new')
        new_cls = super().__new__(cls, *args, **kwargs)
        print(new_cls)
        return new_cls

    def __call__(self, *args, **kwargs):
        # 1、调用自己哪个类的__new__方法创建对象
        empty_object=self.__new__(self)
        #2、调用你自己那个类 __init__方法去初始化
        self.__init__(empty_object,*args,**kwargs)

        return empty_object


# 假设Foo是一个对象,由MyType创建。
#  Foo类其实是MyType的一个对象。
# Foo()  ——》MyType对象()
class Foo(object, metaclass=MyType):

    def __init__(self,name):
        self.name=name

v1=Foo('666')

print(v1)
print(v1.name)

三、总结

1、当我们不写MyType类时,Type中已经帮我们定义好了
__init__
__new__
__call__ 方法了
当我定义了MyType类时,
__init__
__new__
__call__ 方法是我们自己定义的

2、这就是为什么实例化对象的时候,先去创建对象再去初始化对象,Type类中已经实现了先 __new__()__init__()


3、代码从上到下执行,当执行到class Foo(object, metaclass=MyType)
先创建这个类,去MyType中的__new__()创建方法
__init__()实例化方法,类在内存中创建好了,
但是MyType中的__call__()方法是不执行的,因为类后面没有加括号
如果类后面加了括号Foo(),会执行MyType的__call__()方法


4、如果自己定义的类中实现了__call__方法,此时是不会执行的,因为Foo是MyType创建出来的


5、如果要执行Foo类的__call__方法,需要实例化Foo类的对象v1,
然后v1加括号

版权声明:本文为博主作者:敲代码敲到头发茂密原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/YZL40514131/article/details/136511428

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2024年4月1日
下一篇 2024年4月1日

相关推荐