在Python中通过名称作为字符串调用类型

时间:2009-10-30 15:02:16

标签: python getattr

我知道使用globals(),locals()和getattr通过字符串来反馈Python中的内容(如this question中所述),但除非我遗漏了明显的东西,否则我似乎无法使用它与呼叫类型。

e.g:

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')...

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

6 个答案:

答案 0 :(得分:12)

有locals,globals,然后是builtins。 也许你正在寻找内置:

import __builtin__
getattr(__builtin__,'int')

答案 1 :(得分: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所期望的确切值。

答案 2 :(得分:3)

getattr(__builtins__,'int')

答案 3 :(得分:2)

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

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

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

答案 4 :(得分: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

答案 5 :(得分:1)

如果你有一个字符串,它是一个东西的名字,你想要的东西,你也可以使用:

thing = 'int'
eval(thing)

请记住,这非常强大,您需要了解可能包含的内容及其来源。例如,如果您接受用户输入,则恶意用户可以使用此代码对您的计算机进行无限制的损坏。