Python避免子类中的实现方法名称冲突 [英] Python avoiding implementation method name clashes in subclass

查看:173
本文介绍了Python避免子类中的实现方法名称冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在python中创建子类时,如何确保我的子类实现方法不会无意中覆盖超类中的实现方法?我正在努力避免:

When creating a subclass in python, how do I ensure that my subclass implementation methods don't unintentionally override an implementation method in a superclass? I'm trying to avoid:

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)在子类中的所有实现方法上使用__(通常__被描述为超类防止子类化的一种方式;但我认为这将有助于子类避免破坏超类).

I'm thinking the only options are: (1) read the source code of the super class to ensure I'm picking a unique subclass method name (which may break when the superclass is updated); or (2) use __ on all implementation methods in my subclass (usually __ is described as a way for a superclass to prevent subclassing; but I'm thinking it would help a subclass avoid breaking the superclass).

我在这里想念东西吗?

更新 @sobolevn基本上回答了我的问题.需要澄清的是:我在名称处理中心围绕超级类进行的所有讨论都试图隐藏/防止其方法被调用/重写(并且通常会评论这不是python的方式,并且用户应该尊重单个前导_).我担心的一个非常不同的问题是,将我没有编写的类子类化(并且本身没有使用名称修饰),以及为实现方法选择名称,这可能会无意间破坏超类(或其子类)中的代码.父母)(如果该名称已被使用).

Update @sobolevn basically answered my question. To clarify: all of the discussion I've seen on name-mangling centers around superclasses trying to hide/prevent their methods from being called/overridden (and there's usually comment on how this isn't the python way and users should be respectful of a single leading _). I'm concerned about the very different problem of subclassing a class that I didn't write (and which did not, itself, use name mangling), and choosing names for implementation methods, which could inadvertently break code in the superclass (or its parents) if that name was already used.

根据我所读的内容,在我看来(a)编写我自己未编写的类的子类的最佳实践是在所有私有方法前加上__;但是(b)鉴于所有方法都是在python中虚拟的,并且我经常希望我的子类公开一些新的公共/受保护的方法,除了充分了解所有类使用的所有非混合方法名称外,没有什么好选择我是继承人,这种意识可以避免担心(a)的需要.

Based on what I've read, it seems to me that (a) best practice for writing a subclass of class(es) that I didn't write myself would be to prefix __ to all private methods; but (b) given that all methods are virtual in python and I often will want my subclass to expose some new public/protected method, there is no good alternative to being fully aware of all the non-mangled method names used by all the classes I inherit from, and this awareness would obviate the requirement to worry about (a).

推荐答案

PEP8 说:

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

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

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

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

Python使用类名来修饰这些名称:如果Foo类具有一个 名为__a的属性,Foo .__ a不能访问它. (坚持 用户仍然可以通过调用Foo._Foo__a来获得访问权限.)通常, 双引号下划线仅应用于避免名称冲突 带有要设计为子类的类中的属性.

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.

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

What are the differences between them? Look at this example:

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

As you can see it is impossible to call __private method from the outside.

这篇关于Python避免子类中的实现方法名称冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆