Как переопределить метод с помощью условного - PullRequest
0 голосов
/ 18 декабря 2018

Я покажу вам свой сценарий, а затем объясню, что я хочу сделать

class Animal(object):
    def __init__(self,name=None):
        self.name=name
        if name=="dog":
            object=Dog()
        if name=="cat":
            object=Cat()
    def execute(self):
        print("I am animal")

class Dog:
    def __init__(self):
        pass
    def execute(self):
        print("I am a dog")

class Cat:
    def __init__(self):
        pass
    def execute(self):
        print("I am a cat")


if __name__ =="__main__":
    instanceAnimal=Animal("cat") # I would like to get "I am a cat" but I got "I am animal"
    instanceAnimal.execute()

Я знаю, что это не очень хороший способ, но у меня есть сценарий использования, и я хочу создать экземплярAnimal и, учитывая имя во входных данных, этот класс будет вызывать соответствующий execute.

Надеюсь, мой пример понятен

Ответы [ 3 ]

0 голосов
/ 18 декабря 2018

Вот как вы можете достичь того, что вы хотите:

class Animal(object):
    def __init__(self, name=None):
        if name == 'cat':
            self._object = Cat()
        elif name == 'dog':
            self._object = Dog()
        else:
            self._object = None

    def execute(self):
        if self._object is not None:
            self._object.execute()
        else:
            print("I am animal")
0 голосов
/ 18 декабря 2018

Чистое решение с использованием метакласса и наследования:

class AnimalType(type):
    _classes = {}

    def __init__(cls, name, attribs, bases):
        super(AnimalType, cls).__init__(name, attribs, bases)
        cls._classes[name.lower()] = cls


class Animal(object):
    __metaclass__ = AnimalType

    def __new__(cls, name=None):
        newcls = type(cls)._classes.get(name, Animal)
        return object.__new__(newcls, name)

    def __init__(self, name=None):
        self.name = name

    def execute(self):
        print("I am animal")


class Dog(Animal):
    def execute(self):
        print("I am a dog")


class Cat(Animal):
    def execute(self):
        print("I am a cat")

И если вы НЕ хотите вообще наследования, просто используйте фабричную функцию:

class Animal(object):
    def execute(self):
        print("I am animal")

class Dog:
    def execute(self):
        print("I am a dog")

class Cat:
    def execute(self):
        print("I am a cat")


_clsmap = {
   "animal": Animal,
   "dog": Dog,
   "cat": Cat
   }

def make_animal(name):
    return _clsmap.get(name, Animal)()
0 голосов
/ 18 декабря 2018

Хотя наследование является лучшим решением здесь, OP специально запрашивает другое решение

object = Dog() или object = Cat() не делает ничего полезного.Он присваивает экземпляр Dog или Cat локальной переменной object, и это все.Он ни к чему не привязывает.

Вы должны будете сохранить ссылку на него в Animal и привязать Animal.execute к соответствующему execute методу.

Также вы можетеиспользуйте словарь, чтобы сделать инициализацию более краткой:

class Dog:
    def execute(self):
        print("I am a dog")

class Cat:
    def execute(self):
        print("I am a cat")

class Animal(object):
    names_to_classes = {'dog': Dog, 'cat': Cat}

    def __init__(self, name=None):
        self.name = name
        try:
            self.object = self.names_to_classes[name]()
        except KeyError:
            raise TypeError('name must be either "dog" or "cat"')

    def execute(self):
        self.object.execute()


instanceAnimal = Animal("cat")
instanceAnimal.execute()
instanceAnimal = Animal("dog")
instanceAnimal.execute()
instanceAnimal = Animal("penguin")
instanceAnimal.execute()

output

I am a cat
I am a dog
TypeError: name must be either "dog" or "cat"

Недостатком этого подхода является то, что Dog.__init__ и Cat.__init__ должны приниматьте же аргументы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...