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

在Python中,通过名称作为字符串调用类型,python,getattr,Python,Getattr,我知道使用globals()、locals()和getattr通过字符串引用Python中的内容(如中所示),但除非我缺少一些明显的东西,否则我似乎无法将其用于调用类型 e、 g: [12]中的:locals()['int'] --------------------------------------------------------------------------- KeyError回溯(最近一次呼叫最后一次) e:\downloads\u to\u access\in() KeyEr

我知道使用globals()、locals()和getattr通过字符串引用Python中的内容(如中所示),但除非我缺少一些明显的东西,否则我似乎无法将其用于调用类型

e、 g:

[12]中的
:locals()['int']
---------------------------------------------------------------------------
KeyError回溯(最近一次呼叫最后一次)
e:\downloads\u to\u access\in()
KeyError:'int'
在[13]中:globals()['int']
---------------------------------------------------------------------------
KeyError回溯(最近一次呼叫最后一次)
e:\downloads\u to\u access\in()
KeyError:'int'
getattr(???,'int')。。。

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

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

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

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

有局部变量、全局变量,然后是内置变量。
getattr(__builtins__,'int')
也许您正在寻找内置的:

import __builtin__
getattr(__builtin__,'int')

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

thing = 'int'
eval(thing)

请记住,这是非常强大的,您需要了解它可能包含什么,以及它来自何处。例如,如果您接受用户输入,恶意用户可以使用此代码对您的计算机造成无限的损害。

您已经获得了使用内置的解决方案,但另一个值得保存在工具包中的技术是分派表。如果您的CSV被设计为由多种语言编写的多个应用程序使用,它可能如下所示:

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

def parseInput(typename, value):
    return getattr(__builtins__,typename)(value)
在这种情况下,您可能需要这样的内容,其中
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期望的准确值。

评论表明您对使用eval生成数据的想法不满意。在
\uuuu内置函数中查找函数可以查找
eval

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

Integer,15
String,34
Float,1.0
Integer,8
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

类型int被命名为
int
。您不需要通过复杂的查找在
locals()
中找到它。只要说
int
。你想干什么?当您知道对象的名称时,为什么需要使用字符串查找内置对象?因为在我的实际代码中,我从csv文件中读取“int”。正在读取的值可能是任何接受字符串的可调用值(因此全局/本地命名空间中的任何函数或构造函数中可以接受字符串的任何类型)。无需导入:默认情况下已加载。@mavnn:这是正确的。不过,默认情况下加载的是一个逻辑实现细节。(特别是在使用哪个名称下)如评论中所述,这是从我无法完全控制的csv文件中读取值。eval绝对不是我们要走的路!提供CSV文件的人是邪恶的、精神病的、反社会的吗?他们到底有多邪恶?如果不能信任他们提供类型名,您如何信任他们做任何事情?如果你能信任他们提供数据,你就可以信任他们提供类型名称。天哪,你今天心情不好,洛特先生。我有没有冒犯你?不,它们不是上述任何一种,但为什么要让代码变得比它有理由的更脆弱?@mavnn:eval中没有“漏洞”,除非提供数据的人是已知的反社会者。我更喜欢少施魔法,
eval
涉及的魔法最少。“漏洞问题”是一堆胡言乱语,除非在web应用程序中确实存在反社会者。否则,就用最简单的方法。当然,mavnn将不得不做出自己的评估。我只想补充一点,如果您只想查找类型名,那么查找内置名可能会更简单。如果您想使用eval并且对此感到不安,那么使用一个简单的正则表达式来检查字符串是否仅为字母数字将防止恶意攻击。
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
是一个实现细节。请参阅~utnubus-answer。我的情况很不寻常,我拥有非常“可靠”的数据(直接从大型机获取),而包含处理信息的csv文件很容易被大量人修改+不过,我还是想听听有用的建议。在将来的项目中,我会记住这一点。有一种正确的方法可以访问
\uuuuu内置\uuuu
模块,那就是导入它。不建议使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu