Py学习  »  Python

在python中实现的虚拟函数没有任何初始化

Vinay Varahabhotla • 3 年前 • 1272 次点击  

考虑下面的代码:

class parent_print():
    
    def print_word(self):
        self.print_hello()
        
class child_print(parent_print):
    
    def print_hello(self):
        print('Hello')
        
        
basic_print = child_print()
basic_print.print_word()

这里我假设 打印你好 是父类中的虚拟函数。父对象(parent_print)的所有子对象都将实现一个名为 打印你好 .这样所有的孩子都可以调用一个函数 打印单词 并根据子对象的方法实现对print_hello函数进行适当的绑定。

但是在C++语言中,我们需要特别指出,函数在父类中是虚拟的。 事实上的 关键字,并使用函数析构函数符号~。

但是,在python中,如果不在python父类中提到函数,这怎么可能呢 打印你好 是一个虚拟的功能。

我假设python使用的概念是虚拟函数,如果我错了,请纠正我并解释这个概念。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/128454
 
1272 次点击  
文章 [ 1 ]  |  最新文章 3 年前
Samwise
Reply   •   1 楼
Samwise    3 年前

与其将其视为“虚拟函数”,不如将其视为“duck类型”的一个示例。在这个表达中:

self.print_hello()

我们只需访问 print_hello 属性 self (不管是什么),然后叫它。如果没有这样的属性,则 AttributeError 在运行时引发。如果属性不可调用,则 TypeError 她长大了。这就是全部。没有对这类问题做出任何假设 自己 --我们只是让它“像鸭子一样呱呱叫”,看看它能不能。

duck类型的危险在于,如果你实例化一个 parent_print 打电话 print_word 在这方面,它将失败:

abstract_print = parent_print()
abstract_print.print_word()
# raises AttributeError: 'parent_print' object has no attribute 'print_hello'

Python确实支持静态类型声明和抽象类的概念,这可以帮助您避免错误。例如,如果我们运行静态类型检查器( mypy )在您的代码中,我们将得到一个错误:

test.py:4: error: "parent_print" has no attribute "print_hello"

这是完全正确的——从静态类型的角度来看,调用 打印你好 因为我们还没有确定这一切 家长打印 实例具有这样的属性。

为了解决这个问题,我们可以宣布 打印你好 作为一种抽象方法(为了培养良好习惯,我还将清理名称以匹配标准Python约定):

from abc import ABC, abstractmethod

class ParentPrint(ABC):
    
    @abstractmethod
    def print_hello(self) -> None: ...

    def print_word(self) -> None:
        self.print_hello()
        
class ChildPrint(ParentPrint):
    
    def print_hello(self) -> None:
        print('Hello')
        
        
basic_print = ChildPrint()
basic_print.print_word()

现在代码类型检查没有问题。

这个 @abstractmethod decorator还指出该类是抽象的(“纯虚拟的”),无法实例化。如果我们试图创造一个 ParentPrint 任何 它的子类没有提供抽象方法的实现,我们得到一个错误, 二者都 静态地从 麦皮 在运行时以 打字错误 在您尝试实例化对象时(甚至在您尝试调用抽象方法之前),会立即引发该问题:

abstract_print = ParentPrint()
# raises error: Cannot instantiate abstract class "ParentPrint" with abstract attribute "print_hello"