元编程

元编程


元编程概念来自LISP(人工智能语言)和smalltalk。
我们写程序是直接写代码,是否能够用代码来生成未来我们需要的代码吗?这就是元编程。

例如,我们写一个类class A,能否用代码生成一个类出来?

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

python中

  1. 所有非object类都继承自object类
  2. 所有类的类型包括type类都是type(由type构造)
  3. type类继承自object类,object类的类型也是type类

type类

type构建类

python源码

class type(object):
    """
    type(object_or_name, bases, dict)
    type(object) -> the object's type
    type(name, bases, dict) -> a new 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

type(object)-> the object's type,返回对象的类型,例如type(1)

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

x_class = type('newclass',(),{})
print(x_class)
print(x_class.__name__)
print(x_class.__dict__)
print(x_class.mro())

#控制台输出
#<class '__main__.newclass'>
#newclass
#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'newclass' objects>, '__weakref__': <attribute '__weakref__' of 'newclass' objects>, '__doc__': None}
#[<class '__main__.newclass'>, <class 'object'>]

上例比较简单,我们来构建一个更复杂的类

def __init__(self,num):
    print('init~~~~~~~~~')
    self.num = num

def show(self):
    print(self.num)

x_class = type('x',(object,),{'__init__':__init__,'show':show,'y':5})

s = x_class(100)
print(s.y)
s.show()

#控制台输出
#init~~~~~~~~~
#5
#100

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

构建元类

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

class Meta(type):
    def __new__(cls, *args, **kwargs):#该方法是静态方法,需要一个返回值
        print(cls)
        print(args)
        print(kwargs)
        print('*' * 50)
        return super().__new__(cls, *args, **kwargs)

class A(metaclass=Meta):
    def __init__(self):
        print('A -------- init')

class B(A):
    def __init__(self):
        print('B -------- init')

class C(Meta):pass #C类继承Meta元类

class D(metaclass=C):pass #D类由元类C创建

print(A.__bases__,type(A))
print(B.__bases__,type(B))
print(C.__bases__,type(C))
print(D.__bases__,type(D))
<class '__main__.Meta'>
('A', (), {'__module__': '__main__', '__qualname__': 'A', '__init__': <function A.__init__ at 0x000001D6DFEB31F8>})
{}
**************************************************
<class '__main__.Meta'>
('B', (<class '__main__.A'>,), {'__module__': '__main__', '__qualname__': 'B', '__init__': <function B.__init__ at 0x000001D6DFEB3288>})
{}
**************************************************
<class '__main__.C'>
('D', (), {'__module__': '__main__', '__qualname__': 'D'})
{}
**************************************************
(<class 'object'>,) <class '__main__.Meta'>
(<class '__main__.A'>,) <class '__main__.Meta'>
(<class '__main__.Meta'>,) <class 'type'>
(<class 'object'>,) <class '__main__.C'>

从运行结果还可以分析出_ new_ (cls, *args, **kwargs)的参数结构
中间是一个元组('A', (), {'__module__': '__main__', '__qualname__': 'A', '__init__': <function A.__init__ at 0x000001D6DFEB31F8>})
对应(name, bases, dict)
修改代码如下

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

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

元类的应用

元编程一般用于框架开发中。
开发中除非你明确的知道自己在干什么,否则不要随便使用元编程
99%的情况下用不到元类,可能有些程序员一辈子都不会使用元类

元编程总结

元类是制造类的工厂,是用来构造类的类。
构造好元类,就可以在类定义时,使用关键字参数metaclass指定元类,可以使用最原始的
type(name, bases, dict)的方式构造一个类。
元类的new方法中,可以获取元类信息、当前类、基类、类属性字典。

一辈子都不会使用元类**

元编程总结

元类是制造类的工厂,是用来构造类的类。
构造好元类,就可以在类定义时,使用关键字参数metaclass指定元类,可以使用最原始的
type(name, bases, dict)的方式构造一个类。
元类的new方法中,可以获取元类信息、当前类、基类、类属性字典。

Django、SQLAlchemy使用了 元类,让我们使用起来很方便。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值