Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/299.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_Inheritance - Fatal编程技术网

Python避免子类中实现方法名称冲突

Python避免子类中实现方法名称冲突,python,inheritance,Python,Inheritance,在python中创建子类时,如何确保子类实现方法不会无意中重写超类中的实现方法?我试图避免: class A: def a(self): self._helper_func() def _helper_func(self): # do something specific to A class B(A): def b(self): self._helper_func() def _helper_func(sel

在python中创建子类时,如何确保子类实现方法不会无意中重写超类中的实现方法?我试图避免:

class A:
    def a(self):
        self._helper_func()

    def _helper_func(self):
        # do something specific to A

class B(A):
    def b(self):
        self._helper_func()

    def _helper_func(self):
        # do something; didn't realize this would mess up a()
我认为唯一的选择是:(1)阅读超类的源代码,以确保我选择了唯一的子类方法名称(当超类更新时,该名称可能会中断);或者(2)在我的子类中的所有实现方法上使用(通常被描述为超类防止子类化的一种方式;但我认为这将帮助子类避免破坏超类)

我是不是遗漏了什么

更新 @索波列夫基本上回答了我的问题。澄清一下:我所看到的所有关于名称混乱的讨论都围绕着试图隐藏/防止其方法被调用/重写的超类展开(通常会有评论说这不是python的方式,用户应该尊重一个前导函数)。我关心的是一个完全不同的问题,那就是对一个我没有编写的类进行子类化(而这个类本身也没有使用名称混乱),并为实现方法选择名称,如果已经使用了这个名称,那么可能会无意中破坏超类(或其父类)中的代码

根据我所读到的,在我看来,(a)编写我自己没有编写的类的子类的最佳实践是在所有私有方法前加前缀;但是(b)鉴于python中的所有方法都是虚拟的,并且我经常希望我的子类公开一些新的公共/受保护的方法,除了完全了解我从中继承的所有类所使用的所有未损坏的方法名称之外,没有什么好的替代方法,这种了解将避免需要担心(a)。

说:

仅对非公共方法和实例使用一个前导下划线 变量

为避免名称与子类冲突,请使用两个前导下划线 调用Python的名称混乱规则

Python将这些名称与类名混淆:如果类Foo有 名为_a的属性,它不能被Foo访问。(坚持的 用户仍然可以通过调用Foo._Foo__a.)获得访问权限。通常, 双前导下划线只能用于避免名称冲突 类中的属性设计为子类

它们之间有什么区别?看看这个例子:

class Parent(object):
    """ This parent has all types of methods. """
    def _will_private_run_test(self):
        self.__private()

    def public(self):
        print('public', self.__class__)

    def _protected(self):
        print('protected', self.__class__)

    def __private(self):
        print('private', self.__class__)


class Child(Parent):
    """ This child only knows parent's methods. """
    pass



class ChildWithOverrides(Parent):
    """ This child overrides all. """
    def public(self):
        print('New', 'public', self.__class__)

    def _protected(self):
        print('New', 'protected', self.__class__)

    def __private(self):
        print('New', 'private', self.__class__)

def run_private(obj):
    if hasattr(obj, '__private'):
        print('A mirracle happened!')

    try:
        obj.__private()
    except AttributeError as ae:
        print(ae)



parent = Parent()
parent._will_private_run_test()

child = Child()
teen = ChildWithOverrides()

parent.public()
child.public()
teen.public()

parent._protected()
child._protected()
teen._protected()

run_private(parent)
run_private(child)
run_private(teen)
输出将是:

('private', <class '__main__.Parent'>)
('public', <class '__main__.Parent'>)
('public', <class '__main__.Child'>)
('New', 'public', <class '__main__.ChildWithOverrides'>)
('protected', <class '__main__.Parent'>)
('protected', <class '__main__.Child'>)
('New', 'protected', <class '__main__.ChildWithOverrides'>)
'Parent' object has no attribute '__private'
'Child' object has no attribute '__private'
'ChildWithOverrides' object has no attribute '__private'
('private',)
(‘公共’,)
(‘公共’,)
(‘新’、‘公共’、)
(‘受保护’,)
(‘受保护’,)
(‘新’、‘受保护’、)
“Parent”对象没有属性“\uu private”
“Child”对象没有属性“\uu private”
“ChildWithOverrides”对象没有属性“\uu private”

正如您所看到的,从外部调用_私有方法是不可能的

可能的重复项请为助手func指定一个更具描述性的名称。说它在干什么。谢谢!看到您在子类中使用了_private,证实了名称篡改将是防止我的子类无意中重写超类中的实现方法的一种适当方式。最奇怪的输出将是尝试
teen。_将_private_运行_test()
要查看函数
是否将运行
将调用
父版本的
\u private
青少年版本。从这个答案来看,我假设它将正确调用
父版本。