Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python中实现虚拟方法?_Python_Virtual Functions - Fatal编程技术网

如何在Python中实现虚拟方法?

如何在Python中实现虚拟方法?,python,virtual-functions,Python,Virtual Functions,我知道PHP或Java中的虚拟方法 如何在Python中实现它们 或者我必须在抽象类中定义一个空方法并重写它?Python方法总是虚拟的。当然,您甚至不必在基类中定义方法。在Python中,方法优于虚拟方法——它们是完全动态的,因为Python中的类型是duck类型 Python中的Cat和Dog甚至不必从公共基类派生来允许这种行为-您可以免费获得它。也就是说,一些程序员更喜欢以一种更严格的方式定义他们的类层次结构,以便更好地对其进行文档记录,并对类型施加一些严格的限制。这也是可能的-请参见示例

我知道PHP或Java中的虚拟方法

如何在Python中实现它们


或者我必须在抽象类中定义一个空方法并重写它?

Python方法总是虚拟的。

当然,您甚至不必在基类中定义方法。在Python中,方法优于虚拟方法——它们是完全动态的,因为Python中的类型是duck类型


Python中的
Cat
Dog
甚至不必从公共基类派生来允许这种行为-您可以免费获得它。也就是说,一些程序员更喜欢以一种更严格的方式定义他们的类层次结构,以便更好地对其进行文档记录,并对类型施加一些严格的限制。这也是可能的-请参见示例。

实际上,在2.6版中,python提供了一种称为抽象基类的东西,您可以显式地设置如下虚拟方法:

from abc import ABCMeta
from abc import abstractmethod
...
class C:
    __metaclass__ = ABCMeta
    @abstractmethod
    def my_abstract_method(self, ...):
如果类不从已经使用元类的类继承,那么它工作得非常好

资料来源:


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

raisenotimplementederror()

对于不实现方法的“抽象”基类的“纯虚拟方法”,这是推荐的例外

说:

此异常源于
RuntimeError
。在用户定义的基类中,抽象方法在要求派生类重写该方法时应引发此异常

正如其他人所说,这主要是一种文档约定,不是必需的,但这样您可以得到一个比缺少属性错误更有意义的异常

例如:

给出:

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
2
回溯(最近一次呼叫最后一次):
文件“/a.py”,第13行,在
Base().usesVirtualMethod()
文件“/a.py”,第6行,使用虚拟方法
返回self.virtualMethod()+1
文件“/a.py”,第4行,采用虚拟方法
引发未实现的错误()
未实现错误

相关:

类似于C++中的一种虚拟方法(通过引用或指向基类的指针调用派生类的方法)在Python中没有意义,因为Python没有键入。(但我不知道虚拟方法在Java和PHP中是如何工作的。)

但是,如果说“虚拟”是指调用继承层次结构中最底层的实现,那么正如一些答案所指出的那样,在Python中总是会得到这样的结果

嗯,几乎总是

正如dplamp所指出的,并非Python中的所有方法都是这样的。邓德方法不适用。我认为这是一个不太为人所知的特征

考虑这个人为的例子

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
现在

但是,请考虑这一项

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
现在

我们所做的唯一更改是使
prop_a()
成为dunder方法


第一个行为的问题可能是,在不影响
prop\u b()
的行为的情况下,无法更改派生类中
prop\u A()
的行为。Raymond Hettinger的《非常好的谈话》给出了一个不方便使用的用例示例。

+1为例。顺便问一下,狗用什么语言说“hau”?@JeremyP:嗯,说得好:-)我猜在语言中,“h”的发音类似于西班牙语中“hippy”或“Javier”的第一个字母。@Eli:对不起,但我对这个问题的答案很感兴趣。在英语中他们说“woof”,其实他们不说,但这是我们用来比喻猫的“喵”和牛的“moo”的词。“哈”是西班牙语吗?@JeremyP我肯定波兰狗会这么说;)@JeremyP是的,我确认狗用西班牙语说“Jau”,用英语写时是“Hau”:)这个指令有python 3的等价物吗?除了dunder方法。这个答案对实现接口类没有帮助,而接口类是使用虚拟方法的主要原因之一。
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
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
>>> B().prop_b()
20
>>> A().prob_b()
10
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
>>> B().prop_b()
10
>>> A().prob_b()
10