与PHP的compact()和extract()等价的Python

2024-04-29 01:03:39 发布

您现在位置:Python中文网/ 问答频道 /正文

compact()和extract()是PHP中非常方便的函数。compact()获取符号表中的名称列表,并创建仅包含其值的哈希表。提取则相反。e、 g

$foo = 'what';
$bar = 'ever';
$a = compact('foo', 'bar');
$a['foo']
# what
$a['baz'] = 'another'
extract(a)
$baz
# another

在Python中是否有相同的方法?我环顾四周,最近的一次是this thread,它似乎不喜欢。

我知道locals()、globals()和vars(),但如何轻松地选择它们的值的子集呢?

Python是否有更好的东西来避免这种需要?


Tags: 方法函数名称列表fooanotherbarextract
2条回答

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

^{}使得确定变量的定义变得更加困难。当一个变量很难追溯到它被定义的地方时,就很难检查常见的安全问题,比如使用未初始化的变量,或者来自用户输入的未筛选的变量。

^{}并没有那么糟糕,但是如果使用不当,仍然会使查看从变量中设置数组成员的位置变得更加困难。

在许多其他语言中,与extract()等价的是with关键字。Python现在有一个with关键字,尽管它的工作方式有点不同,这使得它不像extract()。但是,在其他语言(如Javascript)中,with关键字also has a poor reputation

我认为最好的建议是用不同的方式思考——不要试图模仿PHP的一个糟糕特性,而要想用简洁易读的代码来做你想做的事情。

它不是很Python,但如果你真的必须:

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

我已经使用了这些实现很多次,而且它们都是有效的,但是技术上不支持修改f_locals

不过,说真的,如果你真的觉得有必要使用这些函数,那么你很可能做错事了。它似乎至少在三个方面与Python's philosophy背道而驰:“显式优于隐式”,“简单优于复杂”,“如果实现很难解释,那是个坏主意”,或者更多(而且,如果你在Python方面有足够的经验,你知道这样的事情还没有完成)。我可以看到它对于调试器或事后分析非常有用,或者对于某种非常通用的框架,它经常需要用动态选择的名称和值创建变量,但这是一个扩展。

如果要使用这些函数,至少应该将extracted变量包含在小范围内。将它们包装在函数中,然后可以将其视为“黑盒”。extract不好的主要原因是,它将变量放在符号表中的方式在检查代码时并不清楚。如果您将这些变量的效果局限于一个非常小的函数,并解释清楚代码和注释的用途,那就不是什么大问题。

相关问题 更多 >