将字符串作为实例/对象的名称
我这几天一直在为以下问题苦恼...
我想找到一种方法,可以通过输入来创建一些对象,并且在需要的时候,可以通过 '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 个回答
>>> class Bear():
... pass
...
>>> class Dog():
... pass
...
>>>
>>> types = {'bear': Bear, 'dog': Dog}
>>>
>>> types['dog']()
<__main__.Dog instance at 0x75c10>
当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。
随便创建没有名字的变量真的是个坏主意——我真心希望你能放弃想要直接用 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
的那个模块,也不仅仅是实例化它的那个模块。
这仍然是个糟糕的主意,但这是实现它的最小伤害的方法。
如果你只是想在一个模块的命名空间里引入新的命名变量,那么使用 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
来取出它。