Как реализовать виртуальные методы в 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
методы Python всегда являются виртуальными.
...при условии, что они не являются частными ! Слишком плохо для парня с++.