且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Python:在函数的本地名称空间中包含字典条目

更新时间:2023-11-19 22:52:16

在一般情况下,因为字典可以有不是有效变量名称的键,例如Python 关键字或非字符串。

如果你非常需要这个,你可以保证字典键都是有效的变量名,并且你不需要它在Python 3上工作,可以遍历字典项目并使用 exec 语句。这种方法有一些奇怪的范围结果,这很丑陋,应该强烈劝阻。



可接受的选择是创建一个虚拟对象并将它们设置为属性,例如:

 >>> data = dict(a = 1,b = 2,c = 3,d = 4)
>>> from types import SimpleNamespace
>>> v = SimpleNamespace(** data)
>>> v.a
1
>>> v.d
4

但它只是用于dict访问的语法糖。 阅读Python#19的禅宗。无论你如何看待它,你都需要命名空间!另一个想法是:创建一个可调用的类而不是一个函数(通过继承 collections.Callable ),然后解压字典中的属性。那么至少你的变量将被类命名空间。

This has probably been asked before, but a quick search didn't give me an answer.

Suppose there is a dictionary containing all variables. How can I pass this dictionary on to the local namespace of a function? For example:

data = dict(a=1,b=2,c=3,d=4)
def f(data):
    return data['a'] + data['d']

requires to write data[' '] around each variable you would like to access. How can you add all entries of the dictionary to the local namespace of the function? For objects you can use

self.__dict__.update(data)

Is there something equivalent for functions, so that you get something along the lines of:

data = dict(a=1,b=2,c=3,d=4)
def f(data):
    add_to_local_namespace(data)
    return a + d

It is impossible in the general case, because the dict can have keys which are not valid variable names, e.g. Python keywords or non-strings.

If you desperately need this, and you can guarantee that the dict keys are all valid variable names, and you don't need it to work on Python 3, it's possible to loop over the dict items and use an exec statement. There are some weird scoping consequences of this approach, it's very ugly, and should be strongly discouraged.

An acceptable alternative is to create a dummy object and set them as attributes, for example:

>>> data = dict(a=1,b=2,c=3,d=4)
>>> from types import SimpleNamespace
>>> v = SimpleNamespace(**data)
>>> v.a
1
>>> v.d
4

But it's only really like a syntactic sugar for dict access. Read zen of Python #19. Whichever way you look at it, you will need namespacing!

Another idea: create a callable class instead of a function (by inheriting collections.Callable), and unpack the dict into attributes on the class. Then at least your variables will be namespaced by the class.