Как реализовать виртуальные методы в Python?
Я знаю виртуальные методы из PHP или Java.
как они могут быть реализованы в Python?
или я должен определить пустой метод в абстрактном классе и переопределить его?
6 ответов:
конечно, и вам даже не нужно определять метод в базовом классе. В Python методы лучше, чем виртуальные - они полностью динамичны, так как ввод в Python утиной типизацией.
class Dog: def say(self): print "hau" class Cat: def say(self): print "meow" pet = Dog() pet.say() # prints "hau" another_pet = Cat() another_pet.say() # prints "meow" my_pets = [pet, another_pet] for a_pet in my_pets: a_pet.say()
Cat
иDog
в Python даже не нужно выводить из общего базового класса, чтобы разрешить это поведение - вы получаете его бесплатно. Тем не менее, некоторые программисты предпочитают определять свои иерархии классов более жестким способом, чтобы лучше документировать его и накладывать некоторые строгость типизации. Это также возможно-см. напримерabc
стандартный модуль.
на самом деле, в версии 2.6 python предоставляет что-то под названием абстрактные базовые классы и вы можете явно установить виртуальные методы следующим образом:
from abc import ABCMeta from abc import abstractmethod ... class C: __metaclass__ = ABCMeta @abstractmethod def my_abstract_method(self, ...):
он работает очень хорошо, если класс не наследуется от классов, которые уже используют метаклассы.
NotImplementedError
это рекомендуемое исключение для создания "чистых виртуальных методов" "абстрактных" базовых классов, которые не реализуют метод.
как говорили другие, это в основном соглашение о документации и не требуется, но таким образом вы получаете более значимое исключение, чем ошибка отсутствующего атрибута.
https://docs.python.org/3.5/library/exceptions.html#NotImplementedError говорит:
это исключение является производным от
RuntimeError
. В пользовательских базовых классах абстрактные методы должны вызывать это исключение, когда они требуют, чтобы производные классы переопределяли метод.например:
class Base(object): def virtualMethod(self): raise NotImplementedError() def usesVirtualMethod(self): return self.virtualMethod() + 1 class Derived(Base): def virtualMethod(self): return 1 print Derived().usesVirtualMethod() Base().usesVirtualMethod()
выдает:
2 Traceback (most recent call last): File "./a.py", line 13, in <module> Base().usesVirtualMethod() File "./a.py", line 6, in usesVirtualMethod return self.virtualMethod() + 1 File "./a.py", line 4, in virtualMethod raise NotImplementedError() NotImplementedError
методы Python всегда виртуальны
как Игнасио сказал еще Каким-то образом наследование классов может быть лучшим подходом к реализации того, что вы хотите.
class Animal: def __init__(self,name,legs): self.name = name self.legs = legs def getLegs(self): return "{0} has {1} legs".format(self.name, self.legs) def says(self): return "I am an unknown animal" class Dog(Animal): # <Dog inherits from Animal here (all methods as well) def says(self): # <Called instead of Animal says method return "I am a dog named {0}".format(self.name) def somethingOnlyADogCanDo(self): return "be loyal" formless = Animal("Animal", 0) rover = Dog("Rover", 4) #<calls initialization method from animal print(formless.says()) # <calls animal say method print(rover.says()) #<calls Dog says method print(rover.getLegs()) #<calls getLegs method from animal class
результаты должны быть:
I am an unknown animal I am a dog named Rover Rover has 4 legs