使字符串成为实例/对象的名称

时间:2009-09-25 20:45:18

标签: python string variables object

我已经在以下几天挣扎了......

我正在尝试找到一种方法来实例化一些我可以通过raw_input调用命名的对象,然后,当我需要时,通过'print VARIABLE NAME'命令查看其属性并结合使用 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)

这个想法是'物种'变量(for循环的第一行)例如物种=熊变成了对象'熊'(循环的最后一行),它与 str 结合在一起()方法和'print Bear'命令会给我bear属性。

就像我说的那样,我已经挣扎了一段时间但是尽管看了类似主题的其他帖子仍然无法找到方法。有人说使用词典,其他人说使用setattr(),但我看不出这在我的例子中是如何工作的。

5 个答案:

答案 0 :(得分: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将很乐意存储值,但是' d必须使用getattr来检索它。

答案 1 :(得分: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__模块,您可以确保可以从任何模块“打印thespeciesname” - 不仅仅是定义Zoo的模块,也不仅仅是实例化它的模块。

这仍然是一个糟糕的想法,但这是实施它的最恐怖的方式。

答案 2 :(得分:0)

答案 3 :(得分:0)

class Zoo(object):
    def __init__(self, name):
        self.name = name
        self.animals = []

    def __str__(self):
        return ("The %s Zoo houses:\n" % self.name) + "\n".join(str(an) for an in self.animals)

class Animal( object ):
    species = None
    def __init__(self, legs, stomach):
        self.legs = legs
        self.stomach = stomach

    def __str__(self):
        return "A %s with %d legs and %d stomachs" % ( self.species, self.legs, self.stomach )


class Bear( Animal ):
    species = "Bear"

class Karp( Animal ):
    species = "Karp"


## this is the point ... you can look up Classes by their names here
## if you wonder show to automate the generation of this dict ... don't.
## ( or learn a lot Python, then add a metaclass to Animal ;-p )
species = dict( bear = Bear,
                karp = Karp )

zoo = Zoo( "Strange" )
while len(zoo.animals) < 9:
    name = raw_input("Enter species name: ").lower()
    if name in species:
        legs = input("How many legs does this species have? ")
        stomachs = input("...and how many stomachs? ")
        zoo.animals.append( species[name]( legs, stomachs ) )
    else:
        print "I have no idea what a", name, "is."
        print "Try again" 

print zoo

答案 4 :(得分:0)

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