简体   繁体   English

python 中的不可继承方法

[英]Non-inheritable method in python

Suppose I have two classes, one inheriting from the other:假设我有两个类,一个继承自另一个:

class A():
    def __init__(self):
        pass

    def doSomething(self):
        print('It Works !') # Insert actual code here

class B(A):
    pass

How do I make the doSomething method impossible to inherit, so that: ( I want to make the error happen )如何使doSomething方法无法继承,以便:(我想让错误发生)

>>> a = A()
>>> a.doSomething()
'It Works !'
>>> b = B()
>>> b.doSomething()
Traceback (most recent call last):
  File "<pyshell#132>", line 1, in <module>
    b.doSomething()
AttributeError: 'B' object has no attribute 'doSomething'

You should question whether you want to have a non-inheritable part in the first place.您应该首先质疑您是否想要拥有不可继承的部分。 It would be more typical to abstract out the common parts of A and B into a common parent, or use a mixin pattern .更典型的做法是将AB的共同部分抽象为一个共同的父级,或者使用mixin 模式

    class Parent
     def doCommonThing1
     def doCommonThing2
     /          \
    /            \
   /              \
  /                \
class A            class B
 def doSomething    def doOtherThing

If you insist that B must be a subclass of A, then the only way to "uninherit" a method is to override it to do something else.如果您坚持 B 必须是 A 的子类,那么“取消继承”方法的唯一方法就是重写它以执行其他操作。 For example, a property which raises attribute error is for all practical purposes the same as a missing attribute:例如,引发属性错误的属性实际上与缺少属性相同:

>>> class A:
...     def doSomething(self):
...         print("it works")
... 
>>> class B(A):
...     @property
...     def doSomething(self):
...         msg = "{!r} object has no attribute 'doSomething'"
...         raise AttributeError(msg.format(type(self).__name__))
... 
>>> A().doSomething()
it works
>>> hasattr(B(), "doSomething")
False
>>> B().doSomething()
...
AttributeError: 'B' object has no attribute 'doSomething'

To the best of my knowledge, there is no builtin way to do this in Python, because it is not really considered part of the Python philosophy.据我所知,在 Python 中没有内置的方法可以做到这一点,因为它并没有真正被认为是 Python 理念的一部分。 There can define "protected" and "private" methods in Python by prepending a single _ or double __ , but you can still call those, it's just discouraged.在 Python 中可以定义“受保护”和“私有”方法,方法是在前面加上一个_或双__ ,但你仍然可以调用它们,只是不鼓励。

One very hacky way to achieve something similar might be to make the method itself "private" and have __getattr__ redirect to that method, but only if the object is really an A .实现类似事情的一种非常老套的方法可能是使方法本身“私有”并让__getattr__重定向到该方法,但前提是 object 真的是A

class A():
    def __init__(self):
        pass

    def __doSomething(self):
        print('It Works !')
        
    def __getattr__(self, attr):
        if attr == "doSomething":
            if type(self) == A:
                return self.__doSomething
            else:
                raise TypeError("Nope")
        return super(A).__getattr__(self, attr)

But this could still be circumvented by calling the "private" method directly as _A__doSomething or overwriting __getattr__ in B .但这仍然可以通过直接调用“私有”方法作为_A__doSomething或覆盖B中的__getattr__来规避。

Alternatively, possibly safer and probably simpler (but still pretty hacky IMHO), you could also add that check to doSomething itself.或者,可能更安全,可能更简单(但仍然很hacky恕我直言),您也可以将该检查添加到doSomething本身。

    def doSomething(self):
        if type(self) != A:
            raise TypeError("Nope")
        print('It Works !')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM