感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的:
① 2000多本Python电子书(主流和经典的书籍应该都有了)
② Python标准库资料(最全中文版)
③ 项目源码(四五十个有趣且经典的练手项目及源码)
④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)
⑤ Python学习路线图(告别不入流的学习)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
import ast, astor, inspect
# 测试函数
def test\_func(a,b):
d = a + 2
f = b + 5
o = d + f
return o
# 代码转换pass
class dump\_trans(ast.NodeTransformer):
def visit\_Assign(self, node):
dump_code = "print({})".format(node.targets[0].id)
dump_node = ast.parse(dump_code).body[0]
return node, dump_node
# 获取原函数ast
tast = ast.parse(inspect.getsource(test_func)).body[0]
# 进行代码插入
dt = dump_trans()
ntast = dt.visit(tast)
# ast 转换成 源代码 str
new_code = astor.to_source(ntast)
print(new_code)
'''
def test\_func(a,b):
d = a + 2
print(d)
f = b + 5
print(f)
o = d + f
print(o)
return o
'''
# 执行新代码 编译 生成 新函数对象
local={}
exec(new_code, {}, local)
print(local)
new_f = local["test\_func"]
# 执行新函数
new_f(6, 9.0)
# 会有打印信息
装饰器内实现代码插桩 类内函数更新
import ast, astor, inspect
# 获取函数源代码
def get\_func\_code(func):
lines = inspect.getsource(func).split('\n')
col_lead = len(lines[0]) - len(lines[0].lstrip(" "))
lines = [c[col_lead:] for c in lines]
code_str = "\n".join(lines)
return code_str
# dump runtime 函数
def dump(name, var):
print(name + " : ", var)
class inject\_dump(ast.NodeTransformer):
def \_\_init\_\_(self, global_val):
self.global_val = global_val
self.trans_func = {}
def visit\_Assign(self, node):
node.value = self.visit(node.value)
dump_code = "dump(\'{}\', {})".format(node.targets[0].id, node.targets[0].id)
dump_node = ast.parse(dump_code).body[0]
return node, dump_node
def visit\_Call(self, node):
if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name) and\
node.func.value.id == "self" and "self" in self.global_val:
sub_func = getattr(self.global_val["self"], node.func.attr)
ij_dump = inject_dump(self.global_val)
fast = ast.parse(get_func_code(sub_func)).body[0]
nfast = ij_dump.visit(fast)
new_code = astor.to_source(nfast)
print(new_code)
local = {}
exec(new_code, self.global_val, local)
new_func = local[sub_func.__name__]
# 更新类内的子函数 已经是非对象方法
setattr(self.global_val["self"], sub_func.__name__, new_func)
# 加 self参数
return ast.Call(node.func, [ast.Name("self", node.func.ctx)] + node.args, node.keywords)
def transf(func):
def \_deco(\*args, \*\*kwargs):
funn_args = inspect.signature(func)
global_val={"dump":dump,}
if "self" in funn_args.parameters:
print(args[0])
global_val["self"] = args[0]
print(getattr(args[0],"s"))
t = inject_dump(global_val)
fast = ast.parse(get_func_code(func)).body[0]
fast.decorator_list = [] # de decorate
nfast = t.visit(fast)
print(getattr(args[0],"s"))
#print(ast.dump(nfast))
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618317507)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**