Initialize subclass within class in python

核能气质少年 提交于 2020-07-10 04:53:51

问题


I am initializing a class along with two subclasses in Python using a dictionary. 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? 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? 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.


回答1:


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.

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. 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. 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.

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. 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.




回答2:


In subclasses, your init method is overriding the init method of the original superclass. This will work fine and is an import concept of OObject Oriented Programming. If you want to call an init method from the superclass, do super(self). If you want to call any other method, do super.method() and include any extra arguments.




回答3:


What you've posted isn't what you think. In your example, "Dog" and "Cat" aren't subclasses of "Pet", they're inner classes. 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.

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.


来源:https://stackoverflow.com/questions/31387342/initialize-subclass-within-class-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!