【问题标题】:How to use the argument of a function to determine which class to call?如何使用函数的参数来确定调用哪个类?
【发布时间】:2016-12-21 07:43:56
【问题描述】:

假设我们有一堆怪物类,其中包括一个地精和一个小鬼:

class Goblin(object):
    def __init__(self):
        self.Name = "Goblin"
        self.HP = random.randint(15,20)
        self.Damage = random.randint(5,10)

class Imp(object):
        def __init__(self):
            self.Name = "Imp"
            self.HP = random.randint(5,10)
            self.Damage = random.randint(2,5)

我们有一个创建怪物的函数,其中“Type”将是要创建的怪物的类型:

def GenerateCharacter(Type, Number):

    i=0
    while i < (Number):
        TempChar = #what do I put here so it knows to create Goblins if I do GenerateCharacter(Goblin, 10)

        Character_List.append(TempChar)
        i = i + 1

如果函数的 Type 参数是类的名称“Goblin”,我如何使放入 TempChar 的类成为 Goblin?因此,如果我执行 GenerateCharacter(X, 10),它会执行 TempChar = X() ??

如果我执行 GenerateCharacter(Goblin, 10),我希望它生成 10 个 Goblin 类的实例并附加到 Character_List,但如果我执行 GenerateCharacter(Imp, 10),我希望它执行 10 个小鬼。

【问题讨论】:

    标签: python python-3.x oop object


    【解决方案1】:

    假设您将类的名称作为字符串传递,请尝试以下操作:

    def GenerateCharacter(Type, Number):
        i=0
        while i < (Number):
            if Type == "Goblin":
                TempChar = Goblin()
            elif Type == "Imp":
                TempChar = Imp()
            # Etc. for every type of monster you have 
            Character_List.append(TempChar)
            i += 1
    

    通过将 Goblin 和 Imp 类型封装在 Monster 类中可能有更好的方法,这可能会使您的代码更容易维护。有关更多信息和示例,请参见此处:http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Factory.html

    编辑:这里更接近你想要的:

    list_of_monsters = []
    
    class Foo:
        def __init__(self):
            print "foo created"
    
    class Bar:
        def __init__(self):
            print "bar created"
    
    class Fubar:
        def __init__(self, num, word):
            print "Fubar created"
            self.number = num
            self.phrase = word
    
    def create_monster(class_name, *args):
        local_class = class_name(*args)
        list_of_monsters.append(local_class)
    
    create_monster(Foo)
    create_monster(Bar)
    
    # You can even pass in arguments:
    create_monster(Fubar, 1, "Hello")
    
    print list_of_monsters
    

    如果您检查此代码,您将看到 list_of_monsters 将包含 3 个对象,每个类一个。

    【讨论】:

    • 假设我们有数百种怪物:我需要数百个 if 语句。如果没有 if 语句,有没有办法做到这一点?通过直接从参数中获取类型并将其放在“TempChar = Goblin()”语句中“Goblin”的位置?因此,如果我执行 GenerateCharacter(X, 10),它会执行 TempChar = X() ??
    • 好吧,如果您将参数作为字符串传递,则无法这样做,因为您的示例中的 X 将是字符串类型,这是不可调用的。您必须将构造函数本身作为参数传入才能以这种方式调用它。
    • 你能给我举个例子吗?还是不确定
    • 太棒了!非常感谢,这正是我所需要的。这是我缺少的 *args 部分,我仍然不知道它的真正含义。看来我有一些研究要做
    • @pomtree,很有可能从字符串创建对象...看我的回答
    【解决方案2】:

    如果您将其作为字符串传递,您可以使用 globals() 方法返回全局命名空间中所有变量的字典

    def GenerateCharacter(Type, Number):
        Character_List = []
        for i in range(Number):
            name = Type
            TempChar = globals()[name](name)
    
            Character_List.append(TempChar)
    
        return Character_List
    

    还可以在循环外创建 Character_List 并使用 for 循环,因为它更简洁,而且您可以避免自己增加循环的计数器。

    【讨论】:

    • globals() 方法返回错误:Traceback (最近一次调用最后一次): File "", line 1, in GenerateCharacter2(Goblin, 10) File "/ Users/kosay.jabre/Desktop/Monster.py",第 39 行,在 GenerateCharacter2 TempChar = globals()[name](name) KeyError: "main.Goblin'>"跨度>
    • 那是因为你传入了对象,把名字作为字符串传递GenerateCharacter('Goblin', 10)
    猜你喜欢
    • 2021-10-09
    • 1970-01-01
    • 2010-12-19
    • 2015-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    相关资源
    最近更新 更多