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

发布于 2024-08-10 08:54:13 字数 836 浏览 10 评论 0原文

我知道使用 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')...

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

I'm aware of using globals(), locals() and getattr to referance things in Python by string (as in this question) but unless I'm missing something obvious I can't seem to use this with calling types.

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

What's the best way of doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

轻许诺言 2024-08-17 08:54:13

有本地变量、全局变量,然后是内置变量。
也许您正在寻找内置的:

import __builtin__
getattr(__builtin__,'int')

There are locals,globals, and then builtins.
Perhaps you are looking for the builtin:

import __builtin__
getattr(__builtin__,'int')
铜锣湾横着走 2024-08-17 08:54:13

您已经获得了使用内置函数的解决方案,但工具包中另一个值得保留的技术是调度表。如果您的 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 期望的准确值。

You've already gotten a solution using builtins, but another worthwhile technique to hold in your toolbag is a dispatch table. If your CSV is designed to be used by multiple applications written in multiple languages, it might look like this:

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

In such a case you might want something like this, where csv is a list of tuples containing the data above:

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

That gives you the flexibility of allowing arbitrary strings to map to useful types. You don't have to massage your data to give you the exact values python expects.

白日梦 2024-08-17 08:54:13
getattr(__builtins__,'int')
getattr(__builtins__,'int')
小矜持 2024-08-17 08:54:13

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

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

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

The issue here is that int is part of the __builtins__ module, not just part of the global namespace. You can get a built-in type, such as int, using the following bit of code:

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

Similarly, you can access any other (imported) module by passing the module's name as a string index to globals(), and then using getattr to extract the desired attributes.

捎一片雪花 2024-08-17 08:54:13

评论表明您对使用 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

Comments suggest that you are unhappy with the idea of using eval to generate data. looking for a function in __builtins__ allows you to find eval.

the most basic solution given looks like this:

import __builtin__

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

You would use it like so:

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

cool. works pretty ok. how about this one though?

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

does this do what you expect? Unless you explicitly want this, you need to do something to prevent untrustworthy inputs from poking about in your namespace. I'd strongly recommend a simple whitelist, gracefully raising some sort of exception in the case of invalid input, like so:

import __builtin__

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

but if you just can't bear that, you can still add just a bit of armor by verifying that the requested function is actually a type:

import __builtin__

def parseInput(typename, value):
    typector = getattr(__builtins__,typename)
    if type(typector) is type:
        return typector(value)
    else:
        return None
跨年 2024-08-17 08:54:13

如果你有一个字符串,它是一个事物的名称,并且你想要这个事物,你也可以使用:

thing = 'int'
eval(thing)

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

If you have a string that is the name of a thing, and you want the thing, you can also use:

thing = 'int'
eval(thing)

Keep in mind though, that this is very powerful, and you need to understand what thing might contain, and where it came from. For example, if you accept user input as thing, a malicious user could do unlimited damage to your machine with this code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文