简体   繁体   English

在python中初始化类中的子类

[英]Initialize subclass within class in python

I am initializing a class along with two subclasses in Python using a dictionary. 我正在使用字典在Python中初始化一个类和两个子类。 Would it be possible to check a key in the dictionary within the init and depending the result initialize either one of the two subclasses? 是否可以检查init中字典中的键,并根据结果初始化两个子类中的任何一个? For instance: 例如:

Class Pet():
    def __init__(self,dic):
       self.name=dic['name']
       self.age=dic['age']
       if dic['type']=='dog':
          #Initialize a dog which inherits all pet methods with name and age passed onto it 
       elif dic['type']=='cat':
          #Initialize a dog which inherits all pet methods with name and age passed onto it 


    def pet_methods():      
        # a bunch of pet methods that I would like to be inherited


    Class Dog():
       def __init__(self):
          self.dog_attributes=dic['dog_attributes']
    Class Cat():
       def __init__(self):
          self.cat_attributes=dic['cat_attributes']

What code can be used in the if/else statement? if / else语句中可以使用哪些代码? Or is there a better way to organize the code? 或者有更好的方法来组织代码吗? I am confused as it seems like I want to call a init within another init. 我很困惑,因为我似乎想在另一个init中调用init。

In subclasses, your init method is overriding the init method of the original superclass. 在子类中, init方法会覆盖原始超类的init方法。 This will work fine and is an import concept of OObject Oriented Programming. 这将工作正常,是OObject Oriented Programming的导入概念。 If you want to call an init method from the superclass, do super(self) . 如果你想从超类调用init方法,请执行super(self) If you want to call any other method, do super.method() and include any extra arguments. 如果要调用任何其他方法,请执行super.method()并包含任何其他参数。

While this may be possible by the semantics of python's classes, I would argue that this is a poor design pattern and should be avoided. 虽然这可能是通过python类的语义实现的,但我认为这是一个糟糕的设计模式,应该避免。

In Object Oriented programming, your classes should represent divisions between portions of your data and logic. 在面向对象的编程中,您的类应该表示数据和逻辑部分之间的划分。 What you're doing right now is coupling the logic/data of the Pet superclass and its subclasses. 你现在正在做的是耦合 Pet超类及其子类的逻辑/数据。 Instead, what you should strive for is to decouple your objects as much as possible. 相反,你应该努力的是尽可能地分离你的对象。 This simplifies the interface between classes and helps you to write classes that are as generic as possible and use subclasses to implement specific behavior. 这简化了类之间的接口,并帮助您编写尽可能通用的类,并使用子类来实现特定的行为。

In your case, you should do the initialization of different pet types within the __init__ methods of the specific pets. 在您的情况下,您应该在特定宠物的__init__方法中初始化不同的宠物类型。 If you write your code this way, it is conceptually much easier to add new Pet subclasses - all you need to do is inherit from Pet and initialize the subclass as it should be. 如果以这种方式编写代码,从概念上讲,添加新的Pet子类要容易得多 - 您需要做的就是从Pet继承并初始化它应该是的子类。

The method that you're attempting to implement right now makes it much harder to implement subclasses. 您现在尝试实现的方法使得实现子类变得更加困难。 An implementer would need to understand what variables to set in the subclass to hook into the Pet classes initialization scheme, and then it would need to go into the Pet source and implement new functionality for initializing the new Pet subclass type. 实现者需要了解要在子类中设置哪些变量以挂接到Pet类初始化方案,然后需要进入Pet源并实现新功能以初始化新的Pet子类类型。 This is much harder to do and requires editing multiple classes just to implement a new subclass. 这要做得更加困难,需要编辑多个类才能实现新的子类。

This question also talks about the problems of what you're trying to implement. 这个问题还谈到了你想要实现的问题。

What you've posted isn't what you think. 你发布的不是你的想法。 In your example, "Dog" and "Cat" aren't subclasses of "Pet", they're inner classes . 在您的示例中,“Dog”和“Cat”不是“Pet”的子类 ,它们是内部类 I've posted some code below demonstrating how you should write the sub classes. 我在下面发布了一些代码,演示了如何编写子类。 For instantiation of different subclasses in your situation, it's best to use the Factory Pattern which you can Google up and I've included as an example below. 为了在你的情况下实例化不同的子类,最好使用你可以谷歌的工厂模式 ,我在下面作为一个例子。 I've also set the factory to be able to return the correct subtype by String, but this is an ugly way of doing things so I'd suggest you not use the example. 我还设置工厂能够通过String返回正确的子类型,但这是一种丑陋的做事方式所以我建议你不要使用这个例子。

class Pet:
    def __init__(self):
        pass

    def method1(self):
        print "Method 1 has been called."

    def method2(self):
        print "Method 2 has been called."

    def yelp(self):
        print "I am yelping"


class Dog(Pet):
    def __init__(self):
        Pet.__init__(self)

    def yelp(self):
        print "I am barking"


class Cat(Pet):
    def __init__(self):
        Pet.__init__(self)

    def yelp(self):
        print "I am meowing"


class PetFactory:
    def __init__(self):
        pass

    def acquire_dog(self):
        return Dog()

    def acquire_cat(self):
        return Cat()

    def acquire_pet_by_name(self, pet_type):
        if pet_type == "dog":
            return Dog()
        elif pet_type == "cat":
            return Cat()

This will yield: 这将产生:

>>> pet = Pet()
>>> dog = Dog()
>>> cat = Cat()
>>> dog.yelp()
I am barking
>>> cat.yelp()
I am meowing
>>> pet.yelp()
I am yelping
>>> pet_factory = PetFactory()
>>> pet_factory.acquire_cat().yelp()
I am meowing
>>> pet_factory.acquire_pet_by_name("cat").yelp()
I am meowing
>>> cat.method1()
Method 1 has been called.
>>> dog.method2()
Method 2 has been called.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM