在Python中如何保护函数不受基类的影响?
我目前正在使用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
\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.<代码>,但是这里有此约定的确切用法。我们的情况。非常感谢!