如何在不使用if的情况下实例化多个继承类之一

时间:2017-10-05 14:18:38

标签: python class oop inheritance

比如说我有一些类,这些类都来自同一个父类,并且具有相同的参数。一个常见的例子;

class Pet():
...

class Cat(Pet):
 __init__(self,name,colour):
Pet.__init__(self,name,colour)
....

class Cactus(Pet):
 __init__(self,name,colour):
Pet.__init__(self,name,colour)
....

然后说我想根据用户输入在程序中稍后点播某种类型的宠物。我最初想到的是;

if(pet_type == 'Cat'):
 animal = Cat(name,colour)
elif(pet_type == 'Cactus'):
 animal = Cactus(name,colour)
etc...

但有没有更好的方法不需要if?例如,如果该计划被开发为包括超过1000只动物,这些动物都来自宠物,那么就不可能实现。

3 个答案:

答案 0 :(得分:1)

创建允许类的字典:

classes = {
    'Cat': Cat,
    'Cactus': Cactus,
}

try:
    cls = classes[pet_type]
except KeyError:
    # handle invalid pet_type here
else:
    animal = cls(name, colour)

根据您对KeyError的回复,您可能希望使用finally子句而不是else子句,或者只使用get方法{ {1}},例如

dict

答案 1 :(得分:1)

您所寻找的是工厂模式。实现这一目标的方法有很多种,从你展示的显式if-cascades到meta-class magic。

一种相当直接的方法是类装饰器:

PET_CLASSES = {}

def pet_class(cls):
    PET_CLASSES[cls.__name__.lower()] = cls


def create_pet(name):
    return PET_CLASSES[name.lower()]()
@pet_class
class Cat:
    pass


@pet_class
class Dog:
    pass


print(create_pet("dog"))

答案 2 :(得分:0)

您可以使用getattr()

的字符串名称来获取该类
 my_class = getattr(module, "class_name")

然后

 my_object = my_class(...)

module = __import__("module_name")

可以访问模块对象