# 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

---------------------------------