首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将函数中的特定字符串替换为另一个字符串的装饰器

将函数中的特定字符串替换为另一个字符串的装饰器
EN

Stack Overflow用户
提问于 2019-10-23 12:10:06
回答 3查看 302关注 0票数 1

有可能这样做吗?

代码语言:javascript
运行
复制
def my_func():
    my_list = ['abc', 'def', 'ghi']
    my_str = 'abc'

如果我将A传递给装饰器,并将函数中的'abc‘替换为'xxx’,则传递B -> yyy

@装饰器(‘abc’)

代码语言:javascript
运行
复制
def my_func():
    my_list = ['xxx', 'def', 'ghi']
    my_str = 'xxx'

我不知道这是不是可能。

我该怎么做呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-10-23 12:31:01

您可以使用一个装饰器,该装饰器使用ast.NodeTransformer来修改带有目标值的任何字符串节点,并在函数的AST中使用给定的替换:

代码语言:javascript
运行
复制
import ast
import inspect
from textwrap import dedent

class Replace(ast.NodeTransformer):
    def __init__(self, target, replacement):
        self.target = target
        self.replacement = replacement

    def visit_Str(self, node):
        if node.s == self.target:
            node.s = self.replacement
        return node

    # remove 'replace' from the function's decorator list to avoid re-decorating during exec
    def visit_FunctionDef(self, node):
        node.decorator_list = [
            decorator for decorator in node.decorator_list
            if not isinstance(decorator, ast.Call) or decorator.func.id != 'replace'
        ]
        self.generic_visit(node)
        return node

def replace(target, repl):
    def decorator(func):
        tree = Replace(target, repl).visit(ast.parse(dedent(inspect.getsource(func))))
        ast.fix_missing_locations(tree)
        scope = {}
        exec(compile(tree, inspect.getfile(func), "exec"), func.__globals__, scope)
        return scope[func.__name__]
    return decorator

因此:

代码语言:javascript
运行
复制
@replace('abc', 'xxx')
def my_func():
    my_list = ['abc', 'def', 'ghi']
    my_str = 'abc'
    print(my_list, my_str)

my_func()

输出:

代码语言:javascript
运行
复制
['xxx', 'def', 'ghi'] xxx

演示:https://repl.it/@blhsing/ValuableLimeVideogames

票数 2
EN

Stack Overflow用户

发布于 2019-10-23 12:29:07

可以用装饰器替换函数的代码对象,从而替换其中的常量,但这不太可能是您真正想要的解决方案。

这几乎在任何规模下都是不可维护的,因为你会有很大的部分看起来像这样:

代码语言:javascript
运行
复制
# Note, this is python 3.x specific
CodeType(
    argcount,             #   integer
    kwonlyargcount,       #   integer
    nlocals,              #   integer
    stacksize,            #   integer
    flags,                #   integer
    codestring,           #   bytes
    consts,               #   tuple
    names,                #   tuple
    varnames,             #   tuple
    filename,             #   string
    name,                 #   string
    firstlineno,          #   integer
    lnotab,               #   bytes
    freevars,             #   tuple
    cellvars,             #   tuple
)

其中您需要从原始代码对象复制,并根据您的意图对其进行修改。

对于这类问题,更好的解决方案是允许将字符串作为参数传递给函数。如果您需要函数稍后在没有字符串的情况下可调用,则可以使用partial (参见functools.partial)

票数 1
EN

Stack Overflow用户

发布于 2019-10-23 12:18:05

装饰器不能改变你函数内部的逻辑。你既可以对参数进行操作,也可以对返回的内容进行操作。在你的例子中,你可以使用post修饰器

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58515362

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档