元编程

元编程

type元类构建类

  • type(name, bases, dict) -> a new type,type的另一种使用方式
    1. 使用type元类,构建一个新的类
      • class A():pass 等价于 type('A',(object,),{})
      • class 语句只是语法糖,本质调用的就是type元类
      • 差别,使用class关键字为类注入的属性和type元类构建时为类注入的属性有所不同,但这影响很小
    2. 参数
      • name,类对象的名称,只是给程序员看的字符串
      • bases,元组,类对象的所有直接继承基类
      • dict,字典,存放类对象的属性;Key为字符串,对应类对象的属性变量;vlaue为类属性对应的对象,可以是属性,也可以是方法
class B(type): 
    pass

C = type('C',(object,),{}) # namedtuple使用type元类构建

print(B.__dict__)
print(C.__dict__)

返回值

{'__module__': '__main__', '__doc__': None}
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}

元类继承测试一

  1. 类对象的产生必定使用其指定的元类,且会走指定元类的__new__方法
  2. 指定元类的__new__方法,必须调用type.__new__()方法
  3. 注意:因为__new__是静态方法,super().__new__()和type.__new__效果等同

此处存疑,类走指定元类的__new__方法,返回值为type.__new__,为什么type(A)返回<class ‘__main__.Meta’>

class Meta(type): # Meta继承自type元类,继承了type原类的能力
    def __new__(cls,*args,**kwargs): # 静态方法,不会绑定self和cls
        print(cls) # 返回当前类对象
        print(args) # 元组(name,(),{}),参考type(name,(),{})
        print(kwargs) # 没什么用
        return type.__new__(cls,*args,**kwargs)
        # return super().__new__(cls,*args,**kwargs),效果同上

# metaclass=Meta,设置构建A的原类为Meta;默认是type,但是被Meta截胡
# 类对象的产生必定使用其指定的元类,且会走指定元类的new魔术方法
# 此处指定的是Meta原类,且Meta.__new__必须返回type.__new__(cls,*args,**kwargs),否则type(A)返回'NoneType'
# 此处存疑,调用type.__new__(cls,*args,**kwargs),为什么会返回类对象,而不是类对象实例???
class A(metaclass=Meta):
    id = 1000

    def __init__(self):
        print('A.init~~~~~~~~~~~~~~~~')

print('-' * 30)
print(type(Meta),Meta.__mro__)
print(type(A))

返回值

<class '__main__.Meta'>
('A', (), {'__module__': '__main__', '__qualname__': 'A', 'id': 1000, '__init__': <function A.__init__ at 0x000002191E192D90>})
{}
------------------------------
<class 'type'> (<class '__main__.Meta'>, <class 'type'>, <class 'object'>)
<class '__main__.Meta'>

元类继承测试二

class Meta(type): # Meta继承自type元类,继承了type原类的能力
    def __new__(cls,name,bases,dict):
        print(name) # 返回类对象名,字符串
        print(bases) # 返回类对象基类,元组
        print(dict) # 返回类属性,key为变量,value为对象,字典
        return type.__new__(cls,name,bases,dict)

class A(metaclass=Meta):
    id = 1000

    def __init__(self):
        print('A.init~~~~~~~~~~~~~~~~')

class B(A):
    def __init__(self):
        print('B.init***********')

def test(self):
    print('test')

C = type('C',(B,),{'__init__':test}) # {'__init__':test} 等价 def __init__(self):print('test)

D = type('D',(Meta,),{}) # D类继承自Meta,相当于type的孙子类,也是元类

print('-' * 30)
print(type(B))
print(type(C),C(),C.__mro__)
print(type(D),D.__mro__)

返回值

A
()
{'__module__': '__main__', '__qualname__': 'A', 'id': 1000, '__init__': <function A.__init__ at 0x000002273CE32D90>}
B
(<class '__main__.A'>,)
{'__module__': '__main__', '__qualname__': 'B', '__init__': <function B.__init__ at 0x000002273CE32E18>}
C
(<class '__main__.B'>,)
{'__init__': <function test at 0x000002273CE329D8>}
------------------------------
<class '__main__.Meta'>
test
<class '__main__.Meta'> <__main__.C object at 0x000002273CE35940> (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
<class 'type'> (<class '__main__.D'>, <class '__main__.Meta'>, <class 'type'>, <class 'object'>)

总结

  • type(元类 / 元类子孙类),返回type
  • class Meta(type):passclass A(metaclass=Meta),type(A)返回Meta
    • 且继承自A的类类型都是Meta

type(元类 / 元类子孙类),返回type

  • class Meta(type):passclass A(metaclass=Meta),type(A)返回Meta
    • 且继承自A的类类型都是Meta
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值