class X():
bar=True
class Y(X):
car='TR'```
#you can use the type to define the class X and Y
X=type('X',(),{'bar'=True})
Y=type('Y',(X,),{'car':'TR'})
一个元类的主要目的是当它被创建时,能够自动的该改变类。
例如:当你希望在当前module 里面你创建的所有类的属性都使用大写。那么你可以创建一个元类来实现这个功能,然后通过这个元类创建当前模块中的所有类。
eg1
def upper_attr(future_class_name,future_class_parents,future_class_attr):
"""
return a class object ,with the list of its attribute turned into uppercase
"""
uppercase_attr={}
for name,val in future_class_attr.items():
if name.startswith('__') and name.endswith("__"):
uppercase_attr[name] = val
else:
uppercase_attr[name.upper()] = val
# create the class creation by type
return type(future_class_name,future_class_parents,uppercase_attr)
class Foo(metaclass=upper_attr):
bar='bip'
print(hasattr(Foo,'bar')) # ourput is false
print(hasattr(Foo,'BAR')) # output is True
我们可以重新定义上面的函数为一个真正的类:
class UpperAttrMetaclass(type):
# __new__ is the method called before __init__
# it's the method that creates the object and returns it
# while __init__ just initializes the object passed as parameter
# you rarely use __new__, except when you want to control how the object
# is created.
# here the created object is the class, and we want to customize it
# so we override __new__
# you can do some stuff in __init__ too if you wish
# some advanced use involves overriding __call__ as well, but we won't
# see this
#here upperattr_metaclass is the extra para for __new__,like self for ordinary method
def __new__(upperattr_metaclass,future_class_name,future_class_parents,future_class_attr):
uppercase_attr={}
for name,val in future_class_attr.items():
if name.startswith('__') and name.endswith("__"):
uppercase_attr[name] = val
else:
uppercase_attr[name.upper()] = val
#this usage for type is not oop,just use the parent's magic method
#return type(future_class_name,future_class_parents,uppercase_attr)
# this is basic OOP, ,nothing magic in there and to call the parent's __new__
return type.__new__(upperattr_metaclass,future_class_name,future_class_parents,uppercase_attr)
# this is to use super to do it claearly
#return super(UpperAttrMetaclass,upperattr_metaclass).__new__(upperattr_metaclass,future_class_name,future_class_parents,uppercase_attr)
class Foo1(metaclass=UpperAttrMetaclass):
bar='bip'
print(hasattr(Foo1,'bar')) # ourput is false
print(hasattr(Foo1,'BAR')) # output is True
print(Foo1.__mro__)
print(Foo1.__dict__)
print(Foo1())
在这里我们使用的参数名字都比较长,为了方便起见,可以使用下面格式
class UpperAttrMetaclass(type):
def __new__(cls, clsname, bases, dct):
uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
return type.__new__(cls, clsname, bases, uppercase_attr)
class UpperAttrMetaclass(type):
def __new__(cls, clsname, bases, dct):
uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)
这里的例子,我们是在元类中通过__new__来创建新的需要产生的类,并实现了一些我们想要实现的功能。
为什么需要使用元类来代替某个函数来做上面的事情呢?
There are several reasons to do so:
class MetaSingleton(type):
instance = None
def __call__(cls, *args, **kw):
if cls.instance is None:
cls.instance = super(MetaSingleton, cls).__call__(*args, **kw)
print(cls.instance)
return cls.instance
class Foo(metaclass=MetaSingleton):
#__metaclass__ = MetaSingleton
def __init__(self,a=None,b=None):
self.a=a
self.b=b
print(self.a,self.b)
pass
print("*"*20)
c1 = Foo()
print(c1.a,c1.b)
print("+"*20)
c2 = Foo(2,3)
print(c2.a,c2.b)
c2.a=4
c2.b=5
print(c1.a,c1.b)
print(c2.a,c2.b)
下面的例子通过__init__在元类中工作:
eg3
class MyMeta(type):
counter = 0
def __init__(cls, name, bases, dic):
type.__init__(cls, name, bases, dic)
cls._order = MyMeta.counter
MyMeta.counter += 1
print("$$$$$$$$$$$$$$$$$$$$$$$")
class MyType(metaclass=MyMeta): # Python 3
pass
print(MyMeta.counter) #output is 1
class MyType1(metaclass=MyMeta):
pass
print(MyMeta.counter) #output is 2
对于以上代码理解:
元类中两个特殊的magic函数:
prepare
new
这里列出一个通过元类和描述器来约束类的属性的例子
class ValidateType:
def __init__(self, type):
self.name = None # will be set by metaclass
self.attr = None # will be set by metaclass
self.type = type
def __get__(self, inst, cls):
if inst is None:
return self
else:
return inst.__dict__[self.attr]
def __set__(self, inst, value):
if not isinstance(value, self.type):
raise TypeError('%s must be of type(s) %s (got %r)' %
(self.name, self.type, value))
else:
inst.__dict__[self.attr] = value
class Validator(type):
def __new__(metacls, cls, bases, clsdict):
# search clsdict looking for ValidateType descriptors
for name, attr in clsdict.items():
if isinstance(attr, ValidateType):
attr.name = name
attr.attr = '_' + name
# create final class and return it
return super().__new__(metacls, cls, bases, clsdict)
class Person(metaclass=Validator):
weight = ValidateType(int)
age = ValidateType(int)
name = ValidateType(str)
p=Person()
p.weight=9
print(p.weight)
https://blog.csdn.net/seinedeparis/article/details/79073415
https://stackoverflow.com/users/9951/e-satis