Python:返回一个dict的函数,其键是输入参数的名称

时间:2012-03-06 15:09:12

标签: python dictionary

是否可以编写一个函数f来获取混合数据的任意元组:

T = 1.0
N = 20
L = 10
args = (T,N,L)

f(*args) # or maybe f(T,N,L)?

并返回输出:

{'T':1.0, 'N':20, 'L':10}

related question使用local,但是一旦传递给函数,我似乎丢失了名字。有办法防止这种情况吗?我猜测变量是按值传递的,因此它们被认为是新对象。

跟进: Python: Using a dummy class to pass variable names?

6 个答案:

答案 0 :(得分:3)

不,一般情况下*args无法做到这一点。您必须使用关键字参数:

>>> def f(**kwargs):
...  return kwargs
... 
>>> f(T=1.0, N=20, L=10)
{'T': 1.0, 'L': 10, 'N': 20}

原因是*args没有为个别参数引入名称;它只为它们的整个列表引入名称args。该函数没有深入了解参数在其之外的名称(如果有的话)。

当参数数量固定时,您可以使用locals执行此操作:

>>> def g(T, N, L):
...  return locals()
... 
>>> g(T=1.0, N=20, L=10)
{'L': 10, 'T': 1.0, 'N': 20}

(或明确地使用return {'T': T, 'N': N, 'L': L}。)

答案 1 :(得分:2)

在Python中,变量只是附加到值的标签。因此,在调用函数时,无法从另一个范围知道您使用的标签。

答案 2 :(得分:2)

不幸的是,您的猜测是错误的,事实上整个问题都表明了对Python名称如何运作的误解。

Python对象总体上不知道他们的名字。如果您认为可以轻松指定a=b,现在ab都指向完全相同的对象,那么这是完全可以理解的。 Python的“变量”只是指向对象的名称,它们不以任何实际方式包含这些对象。将参数传递给函数时,您传递的是基础对象,而不是名称。接收函数只是将它们绑定到函数签名中指定的名称 - 或者,在您的情况下,只需将它们保存在args中,而不给它们任何名称。

因此,当您询问如何获取对象在不同范围内的名称时,您无法询问对象本身。可能有一种方法可以做到这一点,但它涉及检查调用框架,我非常怀疑你想要。

答案 3 :(得分:1)

使用globals()的解决方案。这仅在在模块范围内是唯一的时才有效,因此它很脆弱 - 如果有重复项,它将选择指向该值的第一个名称,随意。是的,无论如何你最好不要这样做,而是重新思考问题。

def f(*names):
    r = {}
    for n in names:
        r[[ name for name in globals() if globals()[name] is n ][0]] = n
    return r

T = 1.0
N = 20
L = 10

print f(T,N,L)
{'T': 1.0, 'L': 10, 'N': 20}

答案 4 :(得分:0)

是的,据我所知,args是一个列表。要保留标签名称,您需要将dict传递给** kwargs,并使用local显式或以编程方式设置名称。

您可以执行以下操作:

def filter_locals(caller_locals, *args):
    filtered = {}
    for key in args:
        filtered[key] = caller_locals[key]
    return filtered

然后:

X = 1
Y = 2
func(filter_locals(locals(), 'X', 'Y')

func将任意长度列表处理为kwargs。

答案 5 :(得分:0)

有必要将作为单独的参数传递:

keys = ('T', 'N', 'L')
values = (1.0, 20, 10)
d = dict(zip(keys, values))

在您的代码中,行args = (T,N,L)的计算结果为args = (1.0, 20, 10),变量T,N,L的“名称”将替换为其值。