5

我知道使用 globals()、locals() 和 getattr 来通过字符串引用 Python 中的东西(如在这个问题中),但除非我遗漏了一些明显的东西,否则我似乎无法将它与调用类型一起使用。

例如:

In [12]: locals()['int']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)

e:\downloads_to_access\<ipython console> in <module>()

KeyError: 'int'

In [13]: globals()['int']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)

e:\downloads_to_access\<ipython console> in <module>()

KeyError: 'int'

getattr(???, 'int')...

这样做的最佳方法是什么?

4

6 回答 6

12

有局部变量,全局变量,然后是内置函数。也许您正在寻找内置:

import __builtin__
getattr(__builtin__,'int')
于 2009-10-30T15:12:11.453 回答
7

您已经使用内置函数获得了解决方案,但另一个值得放在您的工具包中的技术是调度表。如果您的 CSV 旨在供以多种语言编写的多个应用程序使用,它可能如下所示:

Integer,15
String,34
Float,1.0
Integer,8

在这种情况下,您可能需要这样的东西,其中csv包含上述数据的元组列表:

mapping = {
    'Integer': int,
    'String': str,
    'Float': float,
    'Unicode': unicode
}
results = []
for row in csv:
    datatype = row[0]
    val_string = row[1]
    results.append(mapping[datatype](val_string))
return results

这为您提供了允许任意字符串映射到有用类型的灵活性。您无需处理数据即可为您提供 python 期望的确切值。

于 2009-10-30T15:47:16.283 回答
3
getattr(__builtins__,'int')
于 2009-10-30T15:09:49.557 回答
2

这里的问题是它int__builtins__模块的一部分,而不仅仅是全局命名空间的一部分。int您可以使用以下代码获取内置类型,例如:

int_gen = getattr(globals()["__builtins__"], "int")
i = int_gen(4)
# >>> i = 4

同样,您可以通过将模块名称作为字符串索引传递给 来访问任何其他(导入的)模块globals(),然后使用getattr提取所需的属性。

于 2009-10-30T15:08:07.733 回答
2

评论表明您对使用 eval 生成数据的想法不满意。寻找功能__builtins__可以让您找到eval.

给出的最基本的解决方案如下所示:

import __builtin__

def parseInput(typename, value):
    return getattr(__builtins__,typename)(value)

你会像这样使用它:

>>> parseInput("int", "123")
123

凉爽的。工作得很好。这个怎么样?

>>> parseInput("eval", 'eval(compile("print \'Code injection?\'","","single"))')
Code injection?

这是否符合您的预期?除非您明确希望这样做,否则您需要做一些事情来防止不可信的输入在您的命名空间中出现。我强烈推荐一个简单的白名单,在输入无效的情况下优雅地引发某种异常,如下所示:

import __builtin__

def parseInput(typename, value):
    return {"int":int, "float":float, "str":str}[typename](value)

但是如果你不能忍受,你仍然可以通过验证请求的函数实际上是一个类型来添加一点盔甲:

import __builtin__

def parseInput(typename, value):
    typector = getattr(__builtins__,typename)
    if type(typector) is type:
        return typector(value)
    else:
        return None
于 2009-10-30T23:49:15.000 回答
1

如果您有一个作为事物名称的字符串,并且您想要该事物,您还可以使用:

thing = 'int'
eval(thing)

但是请记住,这是非常强大的,您需要了解可能包含的内容以及它的来源。例如,如果您接受用户输入作为事物,恶意用户可以使用此代码对您的机器造成无限破坏。

于 2009-10-30T15:17:15.970 回答