python元编程

前言

元编程概念来自LISP和smalltalk。

举个简单的栗子:
我们写程序是直接写代码,是否能够用代码来生成未来我们需要的代码呢?这就是元编程, ‘类’的’类’,也就是比类更高级的东西。

用来生成代码的程序成为元程序metaprogram,编写这种程序就称为元编程metaprogramming。
python通过反射来实现元编程。

python中,所有非object对象都继承自object类
所有类的类型包括type类,都是type
type类继承自object类, object类的类型也是type类

元编程

type构建类

class type(object):
    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

查看type文档很清楚的可以看到:

type(object) => the object’s type

type(name, bases, dict) => a new type 返回一个新的类型

xclass = type("a", (object,), {"a":1})  # 这里xclass只是标识符, 生成的类的真正的名字是'a'

print(xclass.__name__) #查看类的__name__
print(xclass.a)  # 1 查看类属性'a'
print(xclass().a)  # 1 查看实例属性'a'
print(xclass.__bases__)  # object, 查看继承的类
print(xclass.mro())  # 查看mro(方法解析顺序)
print(xclass.__dict__) # 查看类的__dict__

构建元类

一个类可以继承自tyoe类, 注意不是继承自object类了。

class Meta(type):
    def __new__(cls, name, bases, attrs:dict):
        print(cls)
        print(name)
        print(bases)
        print(attrs)
        return super().__new__(cls, name, bases, attrs)

参数含义
cls通过元类创建的类或者继承自通过元类创建的类
name通过元类创建的类的__name__
bases通过元类创建的类所继承的类
attrs通过元类创建的类的__dict__

继承自type, Meta就是元类,它可以创建其他类。

分析下面通过不同方式创建类的区别:

class Metaclass(type):
    def __new__(cls, name, bases, attrs:dict):
        print(cls)
        print(name)
        print(attrs)
        return super().__new__(cls, name, bases, attrs)


class A(metaclass=Metaclass): # 类型是元类,但是还是继承自Object
    pass


class B(A):  # 类型还是元类,但是继承自A类,A类继承自object类
    pass


C = type("C", (), {}) # 这就是元类

D = Metaclass("D", (), {}) # 这就是元类


class E: # 创建的普通类
    pass


class F(Metaclass): # 继承自Metaclass类
    pass


print("A", type(A), A.__bases__)

print("B", type(B), B.__bases__)

print("C", type(C), C.__bases__)

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

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

print("F", type(F), F.__bases__)

-----------------------------------------------
<class '__main__.Metaclass'>
A
{'__module__': '__main__', '__qualname__': 'A'}
<class '__main__.Metaclass'>
B
{'__module__': '__main__', '__qualname__': 'B'}
<class '__main__.Metaclass'>
D
{}
A <class '__main__.Metaclass'> (<class 'object'>,)
B <class '__main__.Metaclass'> (<class '__main__.A'>,)
C <class 'type'> (<class 'object'>,)
D <class '__main__.Metaclass'> (<class 'object'>,)
E <class 'type'> (<class 'object'>,)
F <class 'type'> (<class '__main__.Metaclass'>,)

从运行结果可以看出, 只要通过一个元类创建类对象时, 就是调用元类中的__new__方法。

元类的应用

ORM编程中使用的框架sqlalchemy中就广泛使用了元编程,下面尝试使用元编程来实现sqlalchemy框架中元编程涉及到的部分功能。

class Column:
    def __init__(self, filedname= None, primary_key=False, nullable=False):
        self.filedname = filedname
        self.primary_key = primary_key
        self.nullable = nullable


class Metaclass(type): # 创建一个元类
    def __new__(cls, name, bases, attrs:dict):
        if "__tablename__" not in attrs:
            attrs["__tablename__"] = name.lower() # 添加表名

        primarykey = []
        for k,v in attrs.items():
            if isinstance(v, Column):
                if v.filedname is None or v.filedname.strip() == "": # 如果创建的mapping类没有添加字段名,
                    v.filedname = k
                if v.primary_key:
                    primarykey.append(v)
        attrs["primary_key"] = primarykey

        return super().__new__(cls, name, bases, attrs)


class Base(metaclass=Metaclass): # 创建一个元类,
    pass


class Student(Base):
    __tablename__ = "student"
    id = Column(primary_key=True, nullable=False) # 使用默认filename=None构造Column类
    name = Column("ben", nullable=False) #
    age = Column()


# 本来构造Column实体对象的时候,参数没有填写完整,想利用元类的__new__方法,构造完整
print(Student.__dict__)
print(Student().age.filedname)

元编程总结

元类是制造类的工厂,是用来构造类的类。
构造好元类,就可以在类的定义时,使用关键字参数metaclass指定一个元类,可以使用最原始的metatype(name, bases, dict)的方式构造一个类。

元类的__new__方法中,可以获取元类信息、当前类、基类、类属性字典。

元编程一般广泛用于开发框架中。例如Django、SQLALchemy等

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值