Python MetaClass

python type中,可以使用type来动态创建类,和使用class本质是一致的。

class X:
    a = 1
X = type('X', (object,), dict(a=1))

除了使用type方法来创建类,我们还可以使用metacalss=type来自定义类的创建,当我们在定义类的时候,默认省略了metaclass=type

class Person(object,metaclass=type):
    def __init__(self, age): 
        self.age = 1

Person类使用metaclass=type时,本质就是使用了Person = type('Person', (object,), dict(age=1))。那么我们就可以通过继承type类并重新实现其__new__方法来实现创建类的个性化操作。

class New_type(type):
    # 因为继承type,所以第一个参数是类的名称,第二个是基类,第三个是属性
    def __new__(cls, clsname, bases, attrs):
    	# 在这里添加一些对clsname,bases,和attrs的操作
		new_clsname = clsname
		new_bases = bases
		new_attrs = attrs
		 
        return type(new_clsname, new_bases, new_attrs)
        # return type.__new__(cls, new_clsname, new_bases, new_attrs) # 更oop的写法
        # return super().__new__(cls, new_clsname, new_bases, new_attrs) # 最oop的写法

class Foo(metaclass=New_type):
    bar = 'bip'

具体应用可以看python metaclass应用

辅助教程

我们使用class创建object,那class本质又是objectclass是谁创建的呢,答案是metaclass
metaclass就是classclass

python所有东西都是对象,由不同的类来创建,如下代码:

age = 35
age.__class__ # <type 'int'> 是int类
name = 'bob' 
name.__class__ # <type 'str'> 是str类
def foo(): pass 
foo.__class__ # <type 'function'> 是function类
class Bar(object): pass
b = Bar()
b.__class__ # <class '__main__.Bar'> 是class类

那么创建这些对象的类的类是谁呢,既__class____class__是谁呢,答案是type注意这里type是小写,(一般类都是大写Type,估计这是为了和type()方法统一)

a.__class__.__class__ # <type 'type'>
age.__class__.__class__ # <type 'type'>
foo.__class__.__class__ # <type 'type'>
b.__class__.__class__ # <type 'type'>

class Foo(object, metaclass=something):

注意:之前python2中使用__metaclass__属性,已经废弃了
创建类的过程中,python做了以下的工作:
1.通过Foo类的metaclass创建一个Foo类对象.如果在Foo中没有找到metaclass则会在父类中寻找,如果在父类中还是找不到,则会在模块中寻找metaclass.如果最终还是找不到,则会使用type作为metaclass.既是说默认metaclass=type

可以以继承的方式重写type来改写类的创建方式

class Foo(metaclass=type):
	pass 

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

	def __call__(self, *args, **kwargs):
		print('call本质:调用类的__new__,再调用类的__init__')
		return super(MyType,self).__call__( *args, **kwargs)
		
class Foo(metaclass=MyType): 
	pass

class Bar(Foo):
	pass

obj = Bar()

例子

利用metaclass使得创建类时,将属性都大写:
记住type(metaclass)也是一个class,所以我们可以继承他

class UpperAttrMetaclass(type):
    def __new__(cls, name, bases, dct):
        attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
        uppercase_attr = dict((name.upper(), value) for name, value in attrs)
        return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)

参考:
https://www.cnblogs.com/Simon-xm/p/4034416.html

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass

https://docs.python.org/3/reference/datamodel.html?highlight=metaclass#metaclasses

https://www.cnblogs.com/Simon-xm/p/4034416.html
https://zhuanlan.zhihu.com/p/98440398
https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python/6581949#6581949
https://blog.csdn.net/jiguanglong/article/details/93204314
https://blog.csdn.net/wwx890208/article/details/80644400

object(class)是具有创建其他object(instance)的能力的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值