Python相当于PHP的compact()和extract()

Tur*_*adg 9 php python dictionary

compact()和extract()是PHP中的函数我发现非常方便.compact()获取符号表中的名称列表,并仅使用其值创建哈希表.提取物恰恰相反.例如,

$foo = 'what';
$bar = 'ever';
$a = compact('foo', 'bar');
$a['foo']
# what
$a['baz'] = 'another'
extract(a)
$baz
# another
Run Code Online (Sandbox Code Playgroud)

有没有办法在Python中做同样的事情?我环顾四周,最接近我的是这个线程,它似乎皱着眉头.

我知道locals(),globals()和vars(),但我怎样才能轻松选择其值的一个子集?

Python有没有更好的东西可以避免这种需要?

Dav*_*d Z 10

它不是非常Pythonic,但如果你真的必须:

import inspect

def compact(*names):
    caller = inspect.stack()[1][0] # caller of compact()
    vars = {}
    for n in names:
        if n in caller.f_locals:
            vars[n] = caller.f_locals[n]
        elif n in caller.f_globals:
            vars[n] = caller.f_globals[n]
    return vars

def extract(vars):
    caller = inspect.stack()[1][0] # caller of extract()
    for n, v in vars.items():
        caller.f_locals[n] = v   # NEVER DO THIS - not guaranteed to work
Run Code Online (Sandbox Code Playgroud)

我已经使用了很多这些实现,并且它们可以工作,但f_locals不支持技术修改.

但是说真的,如果你真的觉得你需要使用这些功能,你可能会采取错误的方式.它至少在三个方面与Python的哲学相悖:"显性优于隐性","简单优于复杂","如果实施难以解释,这是一个坏主意",也许更多(实际上,如果你有足够的Python经验,你就会知道这样的事情并没有完成.我可以看到它对于调试器或事后分析很有用,或者可能对某些非常通用的框架很常见,这些框架经常需要用动态选择的名称和值来创建变量,但这只是一个延伸.

如果要使用这些函数,至少应将extract包含的ed变量保留在小范围内.将它们包装在您可以认为是"黑盒子"的功能中.主要原因extract是糟糕的是它以一种在检查代码时不明确的方式将变量放入符号表中.如果你将这些变量的影响本地化为一个非常小的函数,并解释你正在做什么清楚的代码和注释,这不是一个大问题.


Fer*_*yer 9

我担心Python中没有等价物.在某种程度上,你可以使用(和传递)来模拟它们的效果locals:

>>> def compact(locals, *keys):
...     return dict((k, locals[k]) for k in keys)
...
>>> a = 10
>>> b = 2
>>> compact(locals(), 'a', 'b')
{'a': 10, 'b': 2}

>>> def extract(locals, d):
...     for k, v in d.items():
...         locals[k] = v
...
>>> extract(locals(), {'a': 'foo', 'b': 'bar'}
>>> a
'foo'
>>> b
'bar'
Run Code Online (Sandbox Code Playgroud)

不过,我不认为这些功能"非常方便".动态的全局/局部变量是邪恶的,容易出错 - PHP人员在不鼓励register_globals的时候才知道.根据我的经验,很少有经验丰富的PHP程序员或主要框架使用compact()extract().

在Python中,显式优于隐式:

a = 1
b = 2
# compact
c = dict(a=a, b=b)

# extract
a, b = d['a'], d['b']
Run Code Online (Sandbox Code Playgroud)

  • 不要修改本地人()!http://docs.python.org/library/functions.html#locals (6认同)

tho*_*ter 6

是否值得指出extract()(并且在较小程度上compact())是PHP的最"邪恶"特征之一(以及register_globalseval),应该避免吗?

extract使得确定变量定义的位置变得更加困难.当难以将变量追溯到定义的位置时,更难以检查常见的安全问题,例如使用未初始化的变量或源自用户输入的未过滤变量.

compact 并不是那么糟糕,但如果使用得不好,仍然会比看到数组成员从变量设置的位置更困难.

extract()许多其他语言相同的是with关键字.Python现在有一个with关键字,虽然它的工作方式有点不同,使它不太像extract().但是,在其他语言(如Javascript)中,with关键字的声誉也很差.

我认为最好的建议是以不同的方式思考 - 而不是试图模仿PHP的一个不好的功能,想一想用简洁易读的代码做你想做的事情的其他方法.