Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python获取函数调用外部的变量名_Python_Python 3.x - Fatal编程技术网

Python获取函数调用外部的变量名

Python获取函数调用外部的变量名,python,python-3.x,Python,Python 3.x,让我们有下面的代码 def f(a, b, c): import inspect stack = inspect.stack() # How to know the original variable names i.e 'arg1, 'arg2' & 'arg3' arg1 = arg2 = arg3 = None f(arg1, arg2, arg3) 现在我想知道用于调用f() 如中所示,我们可以使用inspect模块获取帧。但是在这种情况下,它没有帮

让我们有下面的代码

def f(a, b, c):
    import inspect
    stack = inspect.stack()
    # How to know the original variable names i.e 'arg1, 'arg2' & 'arg3'

arg1 = arg2 = arg3 = None

f(arg1, arg2, arg3)
现在我想知道用于调用
f()

如中所示,我们可以使用
inspect
模块获取帧。但是在这种情况下,它没有帮助,因为我必须解析
“f(arg1,arg2,arg3)\n”
,这将是一个混乱的过程


有其他选择吗?

这似乎是您正在尝试的一种粗略的语法解决方法。改为传递一个
dict
或一个
kwargs

使用
dict
,字典使用键值对:

def f(d):
    print(d)
    print(d.keys())

f({'arg1': None, 'arg2': None, 'arg3': None})

# Output
# {'arg1': None, 'arg2': None, 'arg3': None}
# dict_keys(['arg1', 'arg2', 'arg3'])
使用
**kwargs
,它接受数量可变的关键字参数:

def f(**kwargs):
    d = dict(kwargs)  # cast into a dictionary
    print(d)
    print(d.keys())

    # or use it directly
    for arg in kwargs:
        print(arg, '=', kwargs[arg])

f(arg1 = None, arg2 = None, arg3 = None)

# Output
# {'arg1': None, 'arg2': None, 'arg3': None}
# dict_keys(['arg1', 'arg2', 'arg3'])
# arg1 = None
# arg2 = None
# arg3 = None

然后,您可以使用字典的键查找参数名称。

这似乎是您正在尝试的粗略语法解决方法。改为传递一个
dict
或一个
kwargs

使用
dict
,字典使用键值对:

def f(d):
    print(d)
    print(d.keys())

f({'arg1': None, 'arg2': None, 'arg3': None})

# Output
# {'arg1': None, 'arg2': None, 'arg3': None}
# dict_keys(['arg1', 'arg2', 'arg3'])
使用
**kwargs
,它接受数量可变的关键字参数:

def f(**kwargs):
    d = dict(kwargs)  # cast into a dictionary
    print(d)
    print(d.keys())

    # or use it directly
    for arg in kwargs:
        print(arg, '=', kwargs[arg])

f(arg1 = None, arg2 = None, arg3 = None)

# Output
# {'arg1': None, 'arg2': None, 'arg3': None}
# dict_keys(['arg1', 'arg2', 'arg3'])
# arg1 = None
# arg2 = None
# arg3 = None
然后可以使用字典的键查找参数名。

这可能不可取,但至少在某种程度上可以通过解析调用方的字节码来实现。具体地说,您需要使用例如
frame=inspect.stack()[-2][0]
获取调用方的堆栈帧,查看
frame.f_code.co_code
中的原始字节码,查看
frame.f_lasti
中执行的最后一条指令的索引-这将是导致调用函数的
CALL_函数
操作码。(只要您还没有返回-之后,
f_lasti
将随着调用方框架中执行的进行而更新)

现在,解析字节码一点也不难,至少在你开始重构控制流之前(如果你能假设被调用的函数不使用三元运算符,
),但这本身并不难,如果你以前没有做过类似的事情(比如,玩弄事物的内部结构,或者其他一些“低级”的东西),那可能是一座需要攀登的高山,这取决于人;这可能不是一个快速的练习

那么,并发症呢?首先,字节码是CPython的一个实现细节,所以这在诸如Jython之类的替代解释器中不起作用。此外,字节码可以从CPython版本更改到下一个版本,因此大多数CPython版本将需要稍微不同的解析代码

早些时候,我也说过“在某种程度上”——这是什么意思?嗯,我已经提到处理条件可能很难。此外,如果值未存储在变量中,则无法获取变量名!例如,您的函数可能被调用为
f(1,2,3)
f(mylist[0],mydict['asd'],myfunc())
f(*make_args(),**make_kwargs())
——在前两种情况下,您可能只需要确定与每个参数对应的表达式而不是变量名。。。但最后一个案子呢?任何一个表达式都可能对应多个参数,并且您不知道哪个参数来自哪个表达式!一般来说,你也不知道这一点——因为值来自函数调用,你不能在不再次调用函数的情况下查看它们——没有任何东西可以保证函数不会有副作用,或者它们会再次返回相同的值。或者,就像前面的条件句一样,您可以假设调用者没有执行任何操作

简言之,这是可能的——在某种程度上——甚至可能并不特别困难——至少如果你知道自己在做什么的话——但这肯定不会是简单、快速、普遍或可取的


编辑:如果出于某种原因——毕竟——你仍然觉得出于某种原因(或者如果你只是好奇它会是什么样子),那么这里有一个非常有限的概念证明可以让你开始。(仅适用于CPython3.4,仅适用于位置参数,仅适用于局部变量。此外,对于可能不建议这样做,但至少在某种程度上可以通过解析调用方的字节码来实现。具体来说,您可能希望使用例如
frame=inspect.stack()[-2][0]获取调用方的堆栈帧。)
,查看
frame.f\u code.co\u code
中的原始字节码和
frame.f\u lasti
中执行的最后一条指令的索引-这将是导致调用函数的
调用函数
操作码。(只要您还没有返回-之后,
f_lasti
将随着调用方框架中执行的进行而更新)

现在,解析字节码一点也不难,至少在你开始重构控制流之前是这样(如果你能假设被调用的函数不使用三元运算符,
,在函数调用的参数中就可以避免)-但是,虽然这本身并不难,但如果你以前没有做过类似的事情(例如,玩弄事物的内部结构,或其他稍微“低级”的东西),那可能是一座很难攀登的高山,具体取决于人;这可能不是一项快速的运动

那么,复杂度呢?首先,字节码是CPython的一个实现细节,所以这在诸如Jython之类的替代解释器中不起作用。此外,字节码可以从CPython版本更改到下一个版本,因此大多数CPython版本将需要稍微不同的解析代码

早些时候,我也说过“在某种程度上”——这是什么意思?我已经提到处理条件可能很难。此外,如果没有存储值,就无法获取变量名