python元编程 实际应用_Python元编程

元编程是一种编写计算机程序的技术, 这些程序可以将自己看做数据, 因此可以在运行时可以对它进行内省, 生成, 修改.

因此我们可以区分Python元编程的两种主要方法

专注于语言对基本元素(函数, 类, 类型)内省的能力和对运行时创建或修改的能力

允许程序直接处理代码本身, 例如原始的纯文本格式, 或是抽象语法树(AST)

在python中与之相关的工具有:

第一类方法:

装饰器, 允许向现有函数、方法、类中添加附加功能.

类的特殊方法/属性, 允许修改实例的创建过程, 或是访问和修改类/实例的属性.

元类, 允许完全重新设计python面向对象编程范式的实现

第二类方法:

动态代码生成相关

装饰器

一个装饰器, 接收一个函数, 并返回一个新的函数.

典型的装饰器定义如下:

1

2

3

4

5def (func):

def warpper(*args,**kw):

...

return func(*args,**kw)

rerurn warpper

装饰器语法

1

2

3def func(*args, **kwargs):

...

等同于

1func = decorator(func)

一个装饰器函数至少接收一个函数参数func, 并在内部定义新函数warpper, 在warpper的函数体中调用func函数以完成func原本的功能, 并将func的返回值作为自己的返回值, 然后还可以添加其他代码完成额外功能, 最后将warpper函数返回,并赋值给原函数名

注意装饰器语法完全等同于func = decorator(func), 现在func这个变量名已经指向了新函数warpper,即增强版的func, 在完成func原本的功能之余, 还增加了新的特性. 为了保证warpper函数可以接收任何类型和任意数量的参数, 其参数定义为(*args, **kwargs), 并解构传递至func中.

我们的目的是让warpper函数完美替代原本的func, 现在func变量指向了warpper函数, 但是warpper的一些元数据未改变, 例如__name__属性仍然为”warpper”而不是”func”, 即func.__name__ = warpper.

这显然是不合适的. 为了使warpper函数看起来完全就是func, functools模块中提供了一个装饰器@functools.warps, 该装饰器接收一个额外的参数, 该参数应当传入一个函数, 该装饰器会将被装饰的函数的所有元属性更改为与额外参数(另一个函数)完全相同.

所以一个典型的装饰器定义可能如下:

1

2

3

4

5

6def (func):

@functools.warps(func)

def wapper(*args,**kws):

...

return func(*args,**kws)

return wapper

类的特殊方法

使用new方法来覆写实例创建过程

在类的实例化过程中, __init__是一个实例方法, 它接收一个实例(self), 并将其初始化

而创建该类实例的是另一个方法, __new__方法

__new__方法是用来创建实例的静态方法, 因为其特殊性, 所以无需使用@staticmethod来声明.

__new__方法至少接收一个cls参数, 代表当前类

__new__方法必须返回一个实例, 否则实例不会被创建

__new__方法一般返回当前类的实例, 但也可以返回其他类的实例

__new__方法如果返回的不是当前类的实例, __init__方法不会被调用

如果要覆写__new__, 一般使用super().__new__()来获取实际生成的实例, 并在完成自定义逻辑后将其返回. 例如实现单例模式:

1

2

3

4

5

6

7

8class Singleton:

_instance = None

def __new__(cls, *args, **kwargs):

if not cls._instance:

cls._instance = super().__new__(cls, *args, **kwargs)

return cls._instance

以上单例模式的实现有两个重要缺陷:线程不安全以及子类实例化异常

在python中实现单例模式应该直接使用模块的单例性, 将模块级变量定义为需要单例的类的实例

其他可以访问类/实例属性的一些方法

内置函数dir()和vars()

dir(cls) 返回继承自基类的和自己的所有属性的列表

dir(obj) 返回实例和从类中继承的所有属性的列表

vars(cls) 返回类自己的(不包含继承的)所有属性的键和值, 与实际属性相关联, 写有效

vars(obj) 返回实例自己的所有属性的键和值, 与实际属性相关联, 写有效

类和实例的属性

cls.__dict__ 一个字典, 包含类自己的所有属性的键和值, 与实际属性相关联, 写有效

obj.__dict__ 一个字典, 包含实例自己的所有属性的键和值, 与实际属性相关联, 写有效

实际上, vars调用就是返回__dict__属性的值

元类

元类(metaclass)是一个python特性.

元类是定义其他类的原型. 在python中一切皆对象, 所以定义了实例对象的类本身, 也是对象. 进一步考虑, 如果它也是对象, 那么一定有与之相关联的类, 事实上, 所有类定义的基类都是内置的type类.

普通类是type的实例, 而元类是type的子类.

一个继承而不是实例化自type的类, 我们称之为元类(metaclass)

一般语法:

type()可以作为class语句的动态等效.

1

2

3

4def method(self):

return 1

klass = type('MyClass', (object, ), {'method':method})

等效于

1

2

3class klass:

def method(self):

return 1

元类中有四个方法需要关注:

__prepare__(mcs, name, bases, **kwargs) 返回一个空的命名空间

__new__(mcs, name, bases, namespace, **kwargs) 创建一个类

__init__(cls, name, bases, namespace, **kwargs) 初始化一个类

__call__(cls, *args, **kwargs) 让一个类成为callable

参数解释:

mcs 指元类本身, 调用此参数的方法接收的是元类本身

cls 指创建的类, 接收此参数的方法时对类的操作方法

name 指要创建的类的name属性

bases 要创建的类的父类, 元组

namespace 命名空间, 即attrs

动态代码生成exec(object, globals, locals): 用于手动执行代码

eval(expression, globals, locals):用于求表达式值

complie(source, filename, mode):编译任意Python代码

Python语法首先被转换为抽象语法树(Abstract Syntax Tree, AST),然后被编译为字节码. 抽象语法树是对源代码抽象语法结构的一种树状表示. 使用内置的ast模块可以得到Python代码的原始AST, 在传递给complie() 调用之前, 可以对AST进行修改, 以便向现有语法中添加新的语义. 也可以使用纯人工方式创建AST, 不需要解析任何源码, 这样就可以为自定义的领域特定语言创建Python字节码.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值