2017-02-22 99 views
0

В. Как следует передавать константы аргументы базовому классу Python?Python передает постоянные аргументы базовому классу

Используя типичный пример, у меня есть классы Cat и Dog (оба получены из Animal). Вызов x.sound должен вернуть соответствующее слово ("meow", "woof").

Моя проблема заключается в том, что все экземпляры класса делают тот же самый звук, и, следовательно, в то время как я могу передать sound в Animal:

class Animal: 
    def __init__(sound): 
     self.sound = sound 

class Dog: 
    def __init__(): 
     super().__init__("woof") 

Это кажется расточительным, так как мы храним "woof" в каждом случае и у меня есть миллион собак и миллиард кошек. Я мог бы использовать вместо него метод затем:

class Animal: 
    @staticmethod 
    def sound(): 
     raise NotImplementedError("Abstract") 

class Dog: 
    @staticmethod 
    def sound(): 
     return "woof" 

Но сейчас, так как мои животные все очень тихо, это легко пропустить, когда кто-то приходит и пишет Bird класс, не читая мою кропотливо письменную документацию, и только обнаруживает они забыли метод один раз в голубой луне, когда метод фактически вызвал.

Идеально мне хотелось бы что-то вроде шаблонов C++, где сам класс Animal принимает параметр - его нельзя пропустить без возникновения непосредственной ошибки и не занимать больше места на один экземпляр.

template<sound> 
class Animal() 
    . . . 

Есть ли способ выполнить то, что мне нужно в Python?

+0

Я думаю, что все экземпляры собаки должны получать один и тот же фактический строковый объект из-за интернирования строк. –

+0

Я не очень уверен, но вам может понадобиться '__slots__' для этого – vks

+0

@PaulRooney по-прежнему получает указатель на каждый объект. Кроме того, указатель на интернированную строку будет 8 байтов в 64-битной системе, длина которой больше, чем сама строка «woof». –

ответ

0

Вы можете попробовать использовать шаблон заводского дизайна. Что-то вроде этого:

class AnimalFactory(object): 
    animals={} 

    @staticmethod 
    def registerAnimal(animalName, animalClass): 
     if not hasattr(animalClass, "sound"): 
      raise Exception("All animals need to make a sound") 
     AnimalFactory.animals[animalName]=animalClass 

    @staticmethod 
    def createNewAnimal(animalName): 
     return AnimalFactory.animals[animalName]() 

class Dog: 
    sound="woof" 

AnimalFactory.registerAnimal("dog", Dog) 

dog1=AnimalFactory.createNewAnimal("dog") 
print dog1.sound 

class Cat: 
    pass 

AnimalFactory.registerAnimal("cat", Cat) 

Приведенный выше код производит следующий вывод

woof 
Traceback (most recent call last): 
    File "animals.py", line 25, in <module> 
    AnimalFactory.registerAnimal("cat", Cat) 
    File "animals.py", line 7, in registerAnimal 
    raise Exception("All animals need to make a sound") 

Конечно, пользователь может забыть зарегистрировать класс, но до тех пор, как другие пользователи используют AnimalFactory создать новое животное , это должно работать нормально.