关于类:不继承属性的python子类

Python subclass that doesn't inherit attributes

我想创建一个python类,它表面上看起来是另一个类的子类,但实际上并不继承它的属性。

例如,如果我的类名为B,我希望isinstance(B(), A)返回True,以及issubclass(B, A),但我不希望B具有为a定义的属性。这可能吗?

注:我不控制A的实现。

我关心的原因:我使用的模块检查传递的对象是否是A的子类。我想在B中定义必要的属性,而不继承A中定义的多余属性(我不控制它的实现),因为我正在使用__getattr__将一些属性调用传递到包装类,如果这些属性是从a继承定义的,则不会调用__getattr__


使用抽象基类使半不相关的类B成为A的子类,而不继承它:

1
2
3
4
5
6
7
8
9
10
from abc import ABCMeta
class A (metaclass=ABCMeta):
    def foo (self):
        print('foo')

class B:
    def bar (self):
        print('bar')

A.register(B)

然后使用,它将给出所需的结果并显示为子类型,而实际上没有任何基类型的成员:

1
2
3
4
5
6
7
8
9
10
>>> issubclass(B, A)
True
>>> b = B()
>>> isinstance(b, A)
True
>>> b.foo()
Traceback (most recent call last):
  File"<pyshell#16>", line 1, in <module>
    b.foo()
AttributeError: 'B' object has no attribute 'foo'

I'm using __getattr__ to pass some attribute calls onto a wrapped class, and if these attributes are defined by inheritance from A, __getattr__ won't be called.

对于使用普通属性解析找到的成员,不会调用__getattr__。你可以用__getattribute__来代替。

但是,如果您所做的是重写基类A的行为,那么我不明白为什么简单地重写方法不是一个选项:

1
2
3
4
5
6
7
8
9
10
11
class A:
    def doSomething (self);
        print('Do not do this!')

class B:
    def __init__ (self, wrapper):
        self.wrapper = wrapper

    def doSomething (self):
        print('Doing something else instead!')
        self.wrapper.doSomething()


在python3中,重写特殊方法__getattribute__。这使您几乎可以完全控制属性查找。有一些角箱,因此请仔细检查文档(这是语言参考手册的第3.3.2节)。


您可以实现__getattribute__来为不在b中的属性引发attributeErrors:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A(object):
    def __init__(self):
        self.foo = 1

    def bar(self):
        pass

class B(A):
    def __init__(self):
        self.baz = 42

    def __getattribute__(self, attr):
        if attr in ('foo', 'bar'):
            raise AttributeError()
        return super(B, self).__getattribute__(attr)

我很好奇,你为什么要这样做?


我希望这能让你满意(我觉得这有点下流):

1
2
3
4
5
6
7
8
9
10
11
12
13
class A:
    attribute ="Hello"
    pass

class B(A):
    def __getattribute__(self, name):
        if name =="__dict__":
            return super().__getattribute__(name)
        if name in type(self).__dict__:
            return type(self).__dict__[name]
        if name in self.__dict__:
            return self.__dict__[name]
        raise AttributeError("type object '{}' has no attribute '{}'".format(type(self).__name__, name))

现在让我们测试一下:

1
2
3
4
5
6
7
8
9
10
>>> a = A()
>>> a.attribute
'Hello'
>>> b = B()
>>> b.attribute
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
  File"file.py", line 13, in __getattribute__
    raise AttributeError("type object '{}' has no attribute '{}'".format(type(self).__name__, name))
AttributeError: type object 'B' has no attribute 'attribute'

不幸的是,类B本身继承了属性,因此发生了以下情况:

1
2
>>> B.attribute
'Hello'

我希望这不重要,如果你需要使用元类的话(这会变得非常糟糕)。


只要您在__init__方法中定义属性并重写该方法,B将不会运行来自A__init__的代码,因此也不会定义属性等。移除方法会比较困难,但似乎超出了问题的范围。