0
点赞
收藏
分享

微信扫一扫

Python中的元编程


Python中的元编程

文章目录

  • ​​Python中的元编程​​
  • ​​type类​​
  • ​​构建元类​​
  • ​​元类的应用​​
  • ​​元编程总结​​
  • 元编程概念来自LISP和smalltalk。
  • 如果自己写的代码,能生成我们需要的代码。这就是元编程。即用代码生成代码。或者说用代码生成特定的类。例如:常用的class类,是否能够用代码直接生成class类,而不是用关键字class来定义。
  • 用来生成代码的程序称为元编程metaprogram,编写这种程序就称为元编程metaprogramming
  • Python语言能够通过反射实现元编程。
  1. Python中
  • 所有非object类都继承自object类
  • 所有类的类型包括type类都是type
  • type类继承自object类,object类的类型也是type类

type类

  • type构建类

def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
"""
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
# (copied from class doc)
"""
pass

  1. ​type(object) -> the object's type​​,返回对象的类型,例如type(10)
  2. ​type(name,bases,dict) -> a new type​返回一个新的类型
  • name 新类的类名
  • bases 新类的继承关系,一个元组,默认继承object
  • dict 新类的字典,可以为新类添加类属性
  • 简单示例:

XClass = type("myclass",(object,),{"a":100,"b":"string"}) # 字典是类属性
print(XClass)
print(XClass.__dict__)
print(XClass.__name__)
print(XClass.__bases__)
print(XClass.mro())

  • 使用type构建复查的类

def init(self):
self.x = 1000

def show(self):
print("我是实例方法",self.__dict__)

@classmethod
def show1(cls):
print("类方法",cls)

XClass = type("myclass",(object,),{"a":100,"b":"string",
"show1":show1,"show":show,"__init__":init})

print(XClass)
print(XClass.__name__)
print(XClass.__dict__)
print(XClass.mro())

print("- "*30)
# 使用类方法
XClass.show1()

# 使用实例方法
xclass = XClass()
xclass.show()
print(xclass.x)

  • 可以借助type构造任何类,用代码来生成代码,这就是元编程。

构建元类

  • 如果一个类继承了type类,那么这个类就是个元类。元类可以直接用来使用,元类可以用来创造类。
  • 在定义一个类的时候,会使用该类所指定的元类中的​​__new__​​方法类创建该类。
  • 默认类的元类是​​metaclass = type​​可以在类的继承体系括号中添加该参数为类指定该元类
  • 如果一个类的元类会从父类中继承下来。

class Mode(type):
def __new__(cls,*args,**kwargs):
print(cls)
print(args)
print(kwargs)
print()
return super().__new__(cls,*args,**kwargs) #调用父类方法构建实例

class A(metaclass=Mode): #改变A类的元类,默认元类是type
id = 1000

def __init__(self):
print("A.init--------------")

# 第二种 B继承A后,元类依然是A中所指定的元类
class B(A):
def __init__(self):
print("B.init~~~~~~~~~~~")

# 第三种,元类可以使用下面的方式创建新的类
C = Mode("C",(),{})

# D、E是type的实例
class D:pass #等价于 D = type("D",(),{})
E = type("E",(),{})

class F(Mode):pass

print("= "*40)
print(type(A),A.__bases__)
print(type(B),B.__bases__)
print(type(C),C.__bases__)
print()

print(type(D),D.__bases__)
print(type(E),E.__bases__)
print()

print(type(F),F.__bases__)

Python中的元编程_父类

  • 从运行结果还可以分析出​​__new__(cls,*args,**kwargs)​​​的参数解构。中间是一个元组​​('A', (), {'__module__': '__main__', '__qualname__': 'A', 'id': 1000, '__init__': <function A.__init__ at 0x0000023A6FCCF620>})​​​对应​​(name,bases,dict)​
  • 由此可以修改自定义元类代码为:

class Mode(type):
def __new__(cls,name,bases,dt:dict):
print(cls)
print(name)
print(bases)
print(dt,"--------")
return super().__new__(cls,name,bases,dt) #调用父类方法构建实例

  • 从运行结果可以看出,只要元类是Mode,创建类对象时,就会调用Mode的​​__new__​​方法。
  • 上例中,F也是元类,F–继承自–》Mode–继承自–》type。type(元类)返回type。但是type(被metaclass修改了的元类的类返回其元类。)

元类的应用

  • 本示例模拟sqlAlchemy中标定义时继承的Base,和字段类型Column的原理。(这里不做描述器的演示)

class Column:
def __init__(self,fieldname=None,pk=False,nullable=False):
self.fieldname = fieldname
self.pk = pk
self.nullable = nullable

def __repr__(self):
return "<{} {}>".format(__class__.__name__,self.fieldname)

class ModelMeta(type):
def __new__(cls,name,bases,attrs:dict):
print(name,bases,attrs)

if "__tablename__" not in attrs:
attrs["__tablename__"] = str.lower(name)

primarykeys = []
# 为类动态绑定属性
for k,v in attrs.items():
if isinstance(v,Column):
if v.fieldname is None or v.fieldname.strip() == "":
v.fieldname = k #指段没有名字使用属性名
if v.pk:
primarykeys.append(v)

attrs["__primarykeys__"] = primarykeys
return super().__new__(cls,name,bases,attrs)

class Base(metaclass=ModelMeta):
"""继承Base的类的元类都是ModelMety"""
pass

class Student(Base):
id = Column(pk=True,nullable=False)
name = Column("username",nullable=False)
ags = Column()

print("- "*30)
print(Student.__dict__)

Python中的元编程_类属性_02

元编程总结

  • 元类是制造类的工厂,是用来构造类的类。
  • 构造好元类,就可以在类定义时,使用关键字参数metaclass指定元类,可以使用最原始的metatype(name,bases,dict)的方式构造一类。
  • 元类的​​__new__()​​方法中,可以获取元类信息、当前类、基类、类属性字典。
  • 元编程一般用于框架开发中。
  1. 开发中除非你明确的知道自己在干什么,否则不要随便使用元编程
  • Django、SQLAlchemy使用了元类,让我们使用起来很方便。


举报

相关推荐

0 条评论