Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/329.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/8/python-3.x/16.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_Python 3.x_Overriding_Subclassing - Fatal编程技术网

在Python中如何保护函数不受基类的影响?

在Python中如何保护函数不受基类的影响?,python,python-3.x,overriding,subclassing,Python,Python 3.x,Overriding,Subclassing,我目前正在使用python中的模板方法模式 我想知道是否有任何方法可以保护基类中的一些函数,这样子类就不能覆盖了?如下所示,子类中的\u primitive\u操作\u 3覆盖了基类中的相同函数 import abc class AbstractClass(metaclass=abc.ABCMeta): """ Define abstract primitive operations that concrete subclasses define to implemen

我目前正在使用python中的模板方法模式

我想知道是否有任何方法可以保护基类中的一些函数,这样子类就不能覆盖了?如下所示,子类中的
\u primitive\u操作\u 3
覆盖了基类中的相同函数

import abc

class AbstractClass(metaclass=abc.ABCMeta):
    """
    Define abstract primitive operations that concrete subclasses define
    to implement steps of an algorithm.
    Implement a template method defining the skeleton of an algorithm.
    The template method calls primitive operations as well as operations
    defined in AbstractClass or those of other objects.
    """
    def template_method(self):
        self._primitive_operation_1()
        self._primitive_operation_2()
        self._primitive_operation_3()

    # Functions must be specified by subclass (i.e., subclass variant)
    @abc.abstractmethod
    def _primitive_operation_1(self):
        pass

    # Functions must be specified by subclass (i.e., subclass variant)
    @abc.abstractmethod
    def _primitive_operation_2(self):
        pass

    # Functions inherited and not modified by subclass (i.e., subclass invariant)
    def _primitive_operation_3(self):
        print ('Execute operation #3 from main class')

class ConcreteClass(AbstractClass):
    """
    Implement the primitive operations to carry out
    subclass-specificsteps of the algorithm.
    """
    def _primitive_operation_1(self):
        pass

    def _primitive_operation_2(self):
        pass

    # You can still overwrite it if you want
    def _primitive_operation_3(self):
        print ('Execute operation #3 from subclass')

def main():
    concrete_class = ConcreteClass()
    concrete_class.template_method()

if __name__ == "__main__":
    main()

如果无法防止基类中的方法被覆盖,我如何设置一些东西来自动发出警报/警告,表明基类中的某个特定方法已被覆盖?

您无法阻止子类使用相同的名称,不。但是,您可以保护名称不受意外阴影的影响,通过给名称加上双下划线前缀:

def __primitive_operation_3(self):
    print('Execute operation #3 from main class')
Python编译器将替换类的方法中对该名称的所有引用,以添加类名作为前缀。在这里,这是
抽象类
,因此实际名称变成
\u AbstractClass\uuu primitive\u operation\u3
,但由于编译器重写了所有引用,因此您可以透明地在代码中继续使用
\uu primitive\u operation\u3

子类上的任何
\u基元\u操作\u 3
名称都将使用不同的前缀重命名,这仅仅是因为它们是在具有不同名称的类上定义的

此功能明确针对希望允许子类在其定义中使用广泛名称的基类

请参阅词法分析参考文档中的:

类的私有名称。当在类定义的上下文中使用此类别中的名称时,会重新编写以使用损坏的形式,以帮助避免基类和派生类的“私有”属性之间的名称冲突

以及文档的表达式:

私有名称混乱:当类定义中以文本形式出现的标识符以两个或多个下划线字符开头,而不是以两个或多个下划线结尾时,它被视为该类的私有名称。在为私有名称生成代码之前,会将其转换为更长的形式。转换将在名称前面插入类名,删除前导下划线并插入一个下划线。例如,出现在名为
Ham
的类中的标识符
\uuu spam
将转换为
\uham\uu spam
。此转换独立于使用标识符的语法上下文。如果转换后的名称非常长(超过255个字符),则可能会发生实现定义的截断。如果类名只包含下划线,则不进行任何转换

子类仍然可以重写名称,但必须显式包含相同的前缀


请注意,您不能使用此机制来避免在子类中重写特殊方法(使用前导和尾随的
\uuuuuu
双下划线,例如
\uuuuu init\uuuuu
\uu len\uuuu
)。如果基类的子类不能重写特定的方法而不注意调用基类实现,那么清晰的项目文档是至关重要的。您最多可以通过检查缺少的副作用来检测子类是否重写了方法(这就是标准库的功能,或者您可以检查
self.methodname.\uu func\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuulasses(将是抽象方法),而其他方法将保持不变,我希望保持不变方法的保护,以便子类不会意外更改它。@jonrsharpe:不总是这样。许多框架基类实现需要某些东西才能在未被重写的情况下工作。Python甚至有专门的机制来避免此问题……感谢您解释的双下划线与我从M Anaya的Python干净代码中读到的内容相匹配。它并没有真正将其私有化,并且可能会有问题。我想知道是否没有真正的方法防止它被覆盖,是否有方法使它意识到并警告基类中的特定方法已被覆盖(请参见上面的编辑)?谢谢。@KubiK888:你不能。你最多可以检查没有发生的副作用。这就是方法。@KubiK888:你也可以检查
self.methodname.\uu func\uuuuuuuuuuuu是ClassObj.methodname
是真的,如果不是真的,那么你有一个被重写的方法。@KubiK888:不,
\uuuuu name
约定使一个名称类私有。这是n与C++、Java或C语言中的许多开发人员理解私有概念相同的概念。Python中的Curror代码警告,如果您希望根据不同的隐私模型工作,则不应该使用<代码> .java No.<代码>,但是这里有此约定的确切用法。我们的情况。非常感谢!