【问题标题】:Python introspection: return function argument as a string?Python内省:将函数参数作为字符串返回?
【发布时间】:2020-07-17 22:08:22
【问题描述】:

这是我想做的事

x = 1

f(x+3) # returns 'x+3' (a string)

这可能吗?

(Lisp 和 C 可以做到这一点,但 f 必须是宏)

【问题讨论】:

  • 似乎不太可能,因为 x + 3 将在函数调用之前进行评估。该函数只会看到值为4的参数。
  • @101 如果x+3 得到评估,我不介意。我只想从函数内部获取字符串'x+3'
  • 可能有一些老生常谈的方法来做到这一点,但是为什么你想这样做呢?这尖叫X-Y problem。我只是问,因为如果您提供一些背景和动机,您的问题可能会得到更好的回答和更好的接受。比如你控制def f
  • 这在 R 语言中很简单,但在 Python 中,没有好的选择。 (有人可能会建议使用inspect 阅读调用者的源代码,但那里有很多无声的失败案例和嘈杂、混乱的失败案例,不值得一试。)
  • @Barmar 不,你可以用 introscection 破解一些东西,至少在 CPython 中,你可以使用inspect 获取源代码和行号。不过,正如其他人所提到的,它将非常脆弱且非常hacky。

标签: python python-3.x metaprogramming introspection


【解决方案1】:

如果您要添加的值(3)是一个常数,

`def f(x):
    return f"{x}+3"

f(x)

如果不是,可以传两个参数,

def f(x, y):
    return f"{x} + {y}"

f(x, y)


【讨论】:

  • 不,这不能回答问题。 OP 希望如何在源代码中将函数作为字符串调用。这假设它总是f(x + something)
【解决方案2】:

这是可能的,尽管其他人说了什么。我能想到的唯一方法是检查源代码。我不建议在现实中这样做。不过,这是一个有趣的小玩具。

from inspect import currentframe
import linecache
import re

def f(x):

    cf = currentframe()
    calling_line_number = cf.f_back.f_lineno

    calling_line = linecache.getline(__file__, calling_line_number)
    m = re.search(r"^.*?f\((?P<arg>.*?)\).*$", calling_line)
    if m:
        print (m.group("arg"))

x = 1
f(x + 3)

打印x + 3,这正是传递给 f() 的内容。

【讨论】:

  • cmets 所说的脆弱性(除了其他示例)是您定义 v = fv(...) 导致正则表达式无法匹配的情况。可以遍历分配直到出现qualname - 但似乎很难而且仍然很脆弱。但我仍然喜欢你快速而肮脏的解决方案。
猜你喜欢
  • 2018-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-09-13
  • 2012-03-27
  • 1970-01-01
  • 2012-05-25
  • 2017-08-01
  • 2014-12-07
相关资源
最近更新 更多