# Python二十八、元编程-元类 type
# 元类:通过调用元类的初始化函数或metaclass关键字创建一个新的类(动态的创建类)
# 元类用来描述类的行为,类用来描述实例的行为
# 面向过程 语法->语句 元(Meta
抽象的) 抽象的语法变成语句
# 面向函数 类->对象 元类,元编程 抽象的类变成对象
# 面向对象 元类->类 具有某些特性的类为元类,通过元类可以造出具体的类
# type的用途
# Type(name,bases,attrs) name:类名字符串,bases:父类元组,attrs:属性字典
#例1:
A = type("A",(object,),{"b":1}); #定义一个类
a = A();
print(A)
print(a.b)
#例2:(通过函数返回一个类)
def fun(name,bases,attrs):
attrs["c"] = 200
#增加一个属性
return
type(name,bases,attrs)
A = fun("A",(object,),{"a":100})
a = A()
print(a.a)
print(a.c)
打印:
1
100
200
#例子3:
def like(self,you):
print("like "+ you
)
MyList =
type("MyList",(list,),dict(x=2,like=like)) #MyList的父类是list,传入了一个字典作为属性,也可以是方法
mylist = MyList() #直接调用继承自list的方法
mylist.append("c++")
mylist.append("python")
print(mylist)
print(mylist.x)
mylist.like("js")
打印:
['c++', 'python']
2
like js
# 用type作为父类再生成一个新的元类
#函数方式创建元类
class SimpleMeta1(type): #继承type #在这里实现元类的功能
def __init__(cls, name,
bases, atts):
super(SimpleMeta1, cls).__init__(name, bases,
atts) #调用父类的__init__方法,也就是type的init方法
cls.test = lambda self : "Yes! This is a
test." #匿名函数方式指定一个方法 cls的属性相当于单例 static
cls.att=1
if __name__ == "__main__":
A=SimpleMeta1('A',(),{})
a=A()
print(a.test())
print(a.att)
b=A()
print(b.test())
print(b.att)
print(dir(a))
打印:
Yes! This is a test.
1
Yes! This is a test.
1
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__',
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', 'att', 'test']
In [126]:
#class,metaclass方式创建元类,建议用这种方式
class SimpleMeta1(type): #继承type
#在这里实现元类的功能
def __init__(cls, name,
bases, atts):
super(SimpleMeta1, cls).__init__(name, bases,
atts)
cls.test = lambda self : "Yes! This is a
test."
cls.att=1
class A(metaclass = SimpleMeta1):
#利用metaclass创建元类(元类具体内容由继承type的类实现)
pass
if __name__ == "__main__":
a=A()
a=A()
print(a.test())
print(a.att)
b=A()
print(b.test())
print(b.att)
print(dir(a))
打印:
Yes! This is a test.
1
Yes! This is a test.
1
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__',
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', 'att', 'test']
#实例应用
class RegisterClasses(type):
def __init__(cls, name,
bases, atts):
super(RegisterClasses, cls).__init__(name,
bases, atts) #调用父类type的init方法
if not hasattr(cls,
'registry'): #判断cls里有没有registry属性(因为cls调用属性,所以属性是static的(单例))
cls.registry = set() #如果reistyr属性不存在,赋值registry等于一个不能重复数据的集合
cls.registry.add(cls) #把本次调用init方法的类的放入集合中
cls.registry -= set(bases) # 在集合中移除父类
# Metamethods, called on
class objects:
def __iter__(cls):
print(cls.__name__,"触发迭代器方法")
return iter(cls.registry) #吧set()集合转换成迭代器
def __str__(cls):
#toString所有的类名
print(cls.__name__,"触发toString方法")
if cls in cls.registry: #如果类在列表里已存在,返回类名
return
cls.__name__
return cls.__name__ + ": " + ",
".join([sc.__name__ for sc in cls])
def test():
print(cls.__name__,"触发test方法")
class Shape(metaclass=RegisterClasses): #创建元类Shape
pass
class Round(Shape): pass #继承元类
class Square(Shape): pass
class Triangular(Shape): pass
class Boxy(Shape): pass
print(Shape)
class Circle(Round): pass
class Ellipse(Round): pass
print("---------------------------------")
for s in Shape: # 触发Shape的迭代器方法 __iter__(cls),返回一个迭代器
print(s)
print("---------------------------------")
打印:
Shape 触发toString方法
Shape 触发迭代器方法
Shape: Triangular, Round, Boxy, Square
---------------------------------
Shape 触发迭代器方法
Triangular 触发toString方法
Triangular
Ellipse 触发toString方法
Ellipse
Circle 触发toString方法
Circle
Boxy 触发toString方法
Boxy
Square 触发toString方法
Square
---------------------------------
class RegisterClasses(type):
def __init__(cls, name,
bases, atts):
super(RegisterClasses, cls).__init__(name,
bases, atts)
cls.childrens = set() #用来存放子类
for base in bases:
if
hasattr(base,'childrens'):
#如果当前这个类的父类有childrens属性
base.childrens.add(cls) #把当前类放入父类的子类集合中
#print(base.__name__)
def __iter__(cls):
return iter(cls.childrens)
def __str__(cls):
if len(cls.childrens)>0:
return
cls.__name__ + ": " + ", ".join([child.__name__ for child in
cls])
else:
return
cls.__name__
class Shape(metaclass=RegisterClasses):
pass
class Round(Shape): pass
class Square(Shape): pass
class Triangular(Shape): pass
print("打印shape:",Shape) #打印出Shape,并打印出Shape的子类
class Circle(Round): pass
class Ellipse(Round): pass
print("打印Round:",Round)
print("---------------------------------")
for s in Shape: # Iterate over subclasses
print(s)
print("---------------------------------")
打印:
打印shape: Shape: Round, Triangular, Square
打印Round: Round: Circle, Ellipse
---------------------------------
Round: Circle, Ellipse
Triangular
Square
---------------------------------