Conozco métodos virtuales de PHP o Java.
¿Cómo se pueden implementar en Python?
¿O tengo que definir un método vacío en una clase abstracta y anularlo?
python
virtual-functions
Meloun
fuente
fuente
raise NotImplementedError()
Esta es la excepción recomendada para generar "métodos virtuales puros" de clases base "abstractas" que no implementan un método.
https://docs.python.org/3.5/library/exceptions.html#NotImplementedError dice:
Como dijeron otros, esto es principalmente una convención de documentación y no es obligatorio, pero de esta manera obtiene una excepción más significativa que un error de atributo faltante.
P.ej:
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()
da:
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
Relacionado: ¿Es posible hacer clases abstractas en Python?
fuente
Los métodos de Python son siempre virtuales.
fuente
En realidad, en la versión 2.6, Python proporciona algo llamado clases base abstractas y puede establecer métodos virtuales explícitamente como este:
from abc import ABCMeta from abc import abstractmethod ... class C: __metaclass__ = ABCMeta @abstractmethod def my_abstract_method(self, ...):
Funciona muy bien, siempre que la clase no herede de clases que ya usan metaclases.
fuente: http://docs.python.org/2/library/abc.html
fuente
como dijo Ignacio todavía De alguna manera, la herencia de clases puede ser un mejor enfoque para implementar lo que desea.
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
Los resultados deben ser:
I am an unknown animal I am a dog named Rover Rover has 4 legs
fuente
Algo como un método virtual en C ++ (llamar a la implementación del método de una clase derivada a través de una referencia o puntero a la clase base) no tiene sentido en Python, ya que Python no tiene escritura. (Sin embargo, no sé cómo funcionan los métodos virtuales en Java y PHP).
Pero si por "virtual" te refieres a llamar a la implementación más baja en la jerarquía de herencia, entonces eso es lo que siempre obtienes en Python, como señalan varias respuestas.
Bueno, casi siempre ...
Como señaló dplamp, no todos los métodos en Python se comportan así. El método Dunder no lo hace. Y creo que esa es una característica no tan conocida.
Considere este ejemplo artificial
class A: def prop_a(self): return 1 def prop_b(self): return 10 * self.prop_a() class B(A): def prop_a(self): return 2
Ahora
>>> B().prop_b() 20 >>> A().prob_b() 10
Sin embargo, considere este
class A: def __prop_a(self): return 1 def prop_b(self): return 10 * self.__prop_a() class B(A): def __prop_a(self): return 2
Ahora
>>> B().prop_b() 10 >>> A().prob_b() 10
Lo único que hemos cambiado fue hacer
prop_a()
un método más dunder.Un problema con el primer comportamiento puede ser que no se puede cambiar el comportamiento de
prop_a()
en la clase derivada sin afectar el comportamiento deprop_b()
. Esta bonita charla de Raymond Hettinger ofrece un ejemplo de un caso de uso en el que esto es inconveniente.fuente