gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 22:43:37 25 4
gpt4 key购买 nike

在 python 中创建子类时,如何确保我的子类实现方法不会无意中覆盖父类(super class)中的实现方法?我试图避免:

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) 阅读父类(super class)的源代码以确保我选择了一个唯一的子类方法名称(当父类(super class)更新时可能会中断);或 (2) 在我的子类中的所有实现方法上使用 __(通常 __ 被描述为父类(super class)防止子类化的一种方式;但我认为它会帮助子类避免破坏父类(super class))。

我是不是漏掉了什么?

更新@sobolevn 基本上回答了我的问题。澄清一下:我看到的所有关于名称修改的讨论都围绕着父类(super class)试图隐藏/防止它们的方法被调用/覆盖(并且通常评论这不是 python 方式,用户应该尊重单个前导 _)。我担心将一个我没有编写的类子类化(并且它本身没有使用名称修改)和为实现方法选择名称的非常​​不同的问题,这可能会无意中破坏父类(super class)(或其子类)中的代码 parent )如果该名称已被使用。

根据我所读到的内容,在我看来,(a) 编写我自己未编写的类的子类的最佳实践是在所有私有(private)方法前加上 __ 前缀;但是 (b) 考虑到所有方法在 python 中都是虚拟的,我经常希望我的子类公开一些新的公共(public)/ protected 方法,除了完全了解所有类使用的所有未损坏的方法名称之外,没有其他好的选择我继承自,这种意识将避免担心 (a) 的要求。

最佳答案

PEP8说:

Use one leading underscore only for non-public methods and instance variables.

To avoid name clashes with subclasses, use two leading underscores to invoke Python's name mangling rules.

Python mangles these names with the class name: if class Foo has an attribute named __a, it cannot be accessed by Foo.__a. (An insistent user could still gain access by calling Foo._Foo__a.) Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed.

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

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 方法。

关于Python避免子类中的实现方法名称冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30543615/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com