python笔记76-types.FunctionType 动态创建函数
2023-02-19 12:20:25 时间
前言
types.FunctionType 创建函数有2种方式:
- 从已有函数的基础上,创建一个新函数
- 从一个compile 构建的函数对象上,创建一个新函数
FunctionType 使用
FunctionType 可以用于判断一个对象是不是函数
from types import FunctionType, MethodType
def func():
print("hello")
class Demo:
x = 1
def fun(self):
print(self.x)
@staticmethod
def fun2():
print("f2")
print(type(func)) # <class 'function'>
x = Demo()
print(type(x.fun)) # <class 'method'>
print(type(x.fun2)) # <class 'function'>
# 判断是函数还是方法
print(isinstance(func, FunctionType)) # True
print(isinstance(x.fun, MethodType)) # True
print(isinstance(x.fun2, FunctionType)) # True
创建新函数
从已有函数的基础上,创建一个新函数 5个参数
- code是函数体的code对象
- globals就是当前环境下的globals变量
- name就是函数本身的名字
- argdefs保存了函数的默认参数,这里可以注意到,code里只包含函数执行的逻辑,而默认参数则是在函数声明里
- closure是闭包的变量,换句话说是既不在locals里,也不在globals的变量
import types
def foobar():
return "foobar"
dynamic_fun = types.FunctionType(foobar.__code__, {})
print(dynamic_fun()) # foobar
配合compile函数 创建函数
使用示例
import types
f = """
def foobar():
return "foobar"
"""
# 字符串编译成code
module_code = compile(f, '', 'exec')
# 从编译的code obj 取出CodeType 类型
function_code = module_code.co_consts[0]
foobar = types.FunctionType(function_code, {})
print(foobar())
FunctionType 需传一个CodeType 类型,可以从compile() 函数编译后的code取出编译后的code 类型
动态创建函数
如果通过一个函数动态创建更多的函数,可以参考这篇https://zhuanlan.zhihu.com/p/386276353
import sys
import types
from typing import Any, Callable, Mapping, Sequence
from inspect import Parameter, Signature
def create_function_from_parameters(
func: Callable[[Mapping[str, Any]], Any],
parameters: Sequence[Parameter],
documentation=None,
func_name=None,
func_filename=None):
new_signature = Signature(parameters) # Checks the parameter consistency
def pass_locals():
return dict_func(locals()) # noqa: F821 TODO
code = pass_locals.__code__
mod_co_argcount = len(parameters)
mod_co_nlocals = len(parameters)
mod_co_varnames = tuple(param.name for param in parameters)
mod_co_name = func_name or code.co_name
if func_filename:
mod_co_filename = func_filename
mod_co_firstlineno = 1
else:
mod_co_filename = code.co_filename
mod_co_firstlineno = code.co_firstlineno
if sys.version_info >= (3, 8):
modified_code = code.replace(
co_argcount=mod_co_argcount,
co_nlocals=mod_co_nlocals,
co_varnames=mod_co_varnames,
co_filename=mod_co_filename,
co_name=mod_co_name,
co_firstlineno=mod_co_firstlineno,
)
else:
modified_code = types.CodeType(
mod_co_argcount,
code.co_kwonlyargcount,
mod_co_nlocals,
code.co_stacksize,
code.co_flags,
code.co_code,
code.co_consts,
code.co_names,
mod_co_varnames,
mod_co_filename,
mod_co_name,
mod_co_firstlineno,
code.co_lnotab
)
default_arg_values = tuple(p.default for p in parameters if p.default != Parameter.empty) #!argdefs "starts from the right"/"is right-aligned"
modified_func = types.FunctionType(modified_code, {'dict_func': func, 'locals': locals}, name=func_name, argdefs=default_arg_values)
modified_func.__doc__ = documentation
modified_func.__signature__ = new_signature
return modified_func
def foo(arg):
print(arg)
return "x"
f = create_function_from_parameters(
func=foo,
parameters=[Parameter('x', Parameter.POSITIONAL_OR_KEYWORD)],
documentation="some doc",
func_name="bar",
func_filename="main.py",
)
print(f('xxx'))
等价于
def bar(a):
"""some doc"""
foo({"x":a})
f = bar
参考博客https://www.cnblogs.com/fireblackman/p/16192027.html 参考博客https://www.cnblogs.com/olivetree123/p/5067685.html
相关文章
- Python 命令行之旅:深入 argparse(二)
- Python 命令行之旅 —— 深入 argparse (一)
- Python 命令行之旅 —— 初探 argparse
- Python 操作 excel
- Python 转化成 PB 格式数据
- python调用MySQLdb库,报错 “Library not loaded: libmysqlclient.18.dylib”
- [Python]Conda 介绍及常用命令
- [Python Web]常见的 POST 提交数据的方式
- Linux 安装python3.7.6
- PYTHON用时变马尔可夫区制转换(MARKOV REGIME SWITCHING)自回归模型分析经济时间序列|附代码数据
- Python:基础&爬虫
- Python:虚拟环境
- windows环境下python连接openGauss数据库
- 搭建python开发环境-c++教程 如何搭建Python开发环境?
- 中文编程语言有哪些-为什么 Python 不是未来的编程语言?
- Python基础(十九):函数加强
- [Python Web]配置 nginx 遇到错误排查(初级)
- [Python]再学 socket 之非阻塞 Server
- [Python]peewee 使用经验
- [Python Web]部署完网站需要做的基本后续工作