将字符串作为实例/对象的名称

0 投票
4 回答
2440 浏览
提问于 2025-04-15 14:36

我这几天一直在为以下问题苦恼...

我想找到一种方法,可以通过输入来创建一些对象,并且在需要的时候,可以通过 'print 变量名' 命令结合 str() 方法来查看它们的属性。

举个例子,假设我想创建一个有10只动物的动物园...

    class Zoo(object): 
        def __init__(self, species, legs, stomachs):
            self.species = species
            self.legs = legs
            self.stomachs = stomachs


for i in range(9): 
    species = raw_input("Enter species name: ")
    legs = input("How many legs does this species have? ")
    stomachs = input("...and how many stomachs? ")
    species = Zoo(species, legs, stomachs)

我的想法是,'species' 变量(循环的第一行),比如 species = Bear,最终会变成对象 'Bear'(循环的最后一行)。然后结合 str() 方法和 'print Bear' 命令,就能显示出熊的属性。

正如我所说,我为这个问题挣扎了很久,尽管看了很多类似的帖子,还是没能找到解决办法。有些人说用字典,有些人说用 setattr(),但我看不出这些方法在我的例子中怎么用。

4 个回答

0
>>> class Bear():
...     pass
... 
>>> class Dog():
...     pass
... 
>>> 
>>> types = {'bear': Bear, 'dog': Dog}
>>> 
>>> types['dog']()
<__main__.Dog instance at 0x75c10>

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

1

随便创建没有名字的变量真的是个坏主意——我真心希望你能放弃想要直接用 print FOOBAR 打印一个在代码中根本不存在的 FOOBAR 变量的想法,就像我会劝一个想自杀的人放弃这种疯狂的念头,给生活一个机会一样。你可以使用字典,或者写一个函数,传入 'FOOBAR' 作为参数,然后去查找它等等。

但是如果我的朋友执意要结束自己的生命,我可能会转而建议他们如何以最小的伤害来实现这个目标。在这里的对应情况就是……:

class Zoo(object): 
    def __init__(self, species, legs, stomachs):
        self.species = species
        self.legs = legs
        self.stomachs = stomachs
        import __builtin__
        setattr(__builtin__, species, self)

通过明确使用 __builtin__ 模块,你可以确保从任何模块中“打印物种名称”——不仅仅是定义 Zoo 的那个模块,也不仅仅是实例化它的那个模块。

这仍然是个糟糕的主意,但这是实现它的最小伤害的方法。

6

如果你只是想在一个模块的命名空间里引入新的命名变量,那么使用 setattr 可能是最简单的方法:

import sys

class Species:
    def __init__(self, name, legs, stomachs):
        self.name = name
        self.legs = legs
        self.stomachs = stomachs

def create_species():
    name = raw_input('Enter species name: ')
    legs = input('How many legs? ')
    stomachs = input('How many stomachs? ')
    species = Species(name, legs, stomachs)
    setattr(sys.modules[Species.__module__], name, species)

if __name__ == '__main__':
    for i in range(5):
        create_species()

如果你把这段代码保存到一个叫 zoo.py 的文件里,然后从另一个模块导入它,你可以这样使用:

import zoo
zoo.create_species() # => enter "Bear" as species name when prompted
animal = zoo.Bear # <= this object will be an instance of the Species class

不过,通常来说,使用字典来管理一组命名值是一种更“Pythonic”的方式。动态绑定新变量有很多问题,比如大多数人会希望模块变量在程序运行之间保持相对稳定。此外,Python 对变量命名的规则比动物名字的可能组合要严格得多——例如,变量名不能包含空格。因此,虽然 setattr 可以很高兴地存储这个值,但你需要用 getattr 来取出它。

撰写回答