【问题标题】:Aliased name of a Function in PythonPython中函数的别名
【发布时间】:2012-07-19 04:30:59
【问题描述】:

我想找到被调用的函数的名称......即调用函数的变量的名称。使用基本配方,即__name__func_name,或检查基本堆栈对我不起作用。例如

def somefunc():
    print "My name is: %s" % inspect.stack()[1][3]

a = somefunc
a()
# would output: out: "My name is: somefunc"
# whereas I want it to output: "My name is: a"

我的直觉说我可以做到,但我想不通。有没有蟒蛇大师?

【问题讨论】:

  • 我怀疑这是可能的。您想这样做有什么特别的原因吗?
  • 通常当人们问如何做这样的事情时,他们正在做一些非常糟糕的事情。你能澄清一下这将起到什么作用吗?
  • 您可以更改 a 部分的 name,但我不明白您为什么要这样做。另外,请查看装饰器文档。
  • func_name 在您创建函数时定义。 a.func_namesomefunc
  • 不可能。一个函数只有一个规范名称,即用于构造它的名称(在def 语句中指定并存储在其func_name__name__ 属性中)。您可以有任意数量的其他标识符指向它,但无法从函数内部分辨出哪个用于调用它。

标签: python introspection


【解决方案1】:

这可能是不可能做到 100% 正确的,但您可以尝试以下方法:

import inspect
import parser

# this flatten function is by mike c fletcher
def flatten(l, ltypes=(list, tuple)):
    ltype = type(l)
    l = list(l)
    i = 0
    while i < len(l):
        while isinstance(l[i], ltypes):
            if not l[i]:
                l.pop(i)
                i -= 1
                break
            else:
                l[i:i + 1] = l[i]
        i += 1
    return ltype(l)

# function we're interested in
def a():
    current_func = eval(inspect.stack()[0][3])
    last_frame = inspect.stack()[1]
    calling_code = last_frame[4][0]
    syntax_tree = parser.expr(calling_code)
    syntax_tree_tuple = parser.st2tuple(syntax_tree)
    flat_syntax_tree_tuple = flatten(syntax_tree_tuple)
    list_of_strings = filter(lambda s: type(s)==str,flat_syntax_tree_tuple)
    list_of_valid_strings = []
    for string in list_of_strings:
        try:
            st = parser.expr(string)
            list_of_valid_strings.append(string)
        except:
            pass
    list_of_candidates = filter(lambda s: eval(s)==current_func, list_of_valid_strings)
    print list_of_candidates

# other function
def c():
    pass

a()
b=a
a(),b(),c()
a(),c()
c(),b()

这将打印:

['a']
['a', 'b']
['a', 'b']
['a']
['b']

它非常丑陋和复杂,但可能会满足您的需求。它通过查找调用此函数的行中使用的所有变量并将它们与当前函数进行比较来工作。

【讨论】:

  • 我喜欢这个,这是我试图写的内容的精髓……正如你所说,它很复杂。而且我无法真正分配返回值,因此我可以将它用于 a() 函数,因为解析器给出了语法错误。
  • 为了使用返回值,我将 list_of_candidates 设为全局。尽管更简单的解决方案将是下一个挑战,但您的答案适用于我想做的事情!谢谢!
【解决方案2】:

这里的问题是间接性。您可能会做一些复杂的事情,例如检查堆栈,获取调用该函数的模块的代码,从堆栈中解析行号以找到用于在本地上下文中调用该函数的标签,然后使用它,但是不一定会给你你想要的东西。考虑:

def func(x):
    print get_label_function_called_with()

def func_wrapper(func_in_func_wrapper):
    return func_in_func_wrapper

func_label = func
func_from_func_wrapper = func_wrapper(func_label)
func_from_func_wrapper()

应该打印funcfunc_in_func_wrapperfunc_label 还是func_from_func_wrapper?乍一看,这似乎是一个显而易见的答案,但考虑到你永远不知道你正在调用的代码内部发生了什么样的间接,你真的无法确定。

【讨论】:

  • 这是一个复杂的情况,就我而言,我不关心包装器,但其他人可能会。
  • 重点是为什么没有简单甚至真正可行的方法来做到这一点。
  • 可能不快/不可行,但我的问题是关于它是否可能......我相信有一种方法比 python 中选择的答案更强大,因为 python 是真正动态的.
猜你喜欢
  • 2018-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
  • 2012-02-12
  • 2018-08-19
  • 1970-01-01
相关资源
最近更新 更多