我想创建一个表面上看起来像是另一个类的子类的Python类,但实际上并没有继承它的属性。
例如,如果我的班级名为B
,我希望isinstance(B(), A)
返回True
,以及issubclass(B, A)
,但我不会&#39 ; t希望B
具有为A定义的属性。这可能吗?
注意:我无法控制A
的实施。
为什么我关心:我正在使用的模块检查传递的对象是A
的子类。我想在B
中定义必要的属性,而不继承A
中定义的多余属性(我无法控制其实现),因为我使用__getattr__
传递一些属性调用在一个包装的类上,如果这些属性是由A的继承定义的,则__getattr__
不会被调用。
答案 0 :(得分:3)
在Python3中,覆盖特殊方法__getattribute__
。这使您几乎可以完全控制属性查找。有一些极端情况所以请仔细检查文档(它是语言参考手册的第3.3.2节)。
答案 1 :(得分:3)
使用abstract base classes使一个看似无关的类B
成为A
的子类,而不继承它:
from abc import ABCMeta
class A (metaclass=ABCMeta):
def foo (self):
print('foo')
class B:
def bar (self):
print('bar')
A.register(B)
然后使用,它会给出所需的结果并显示为子类型,而实际上没有任何基类型的成员:
>>> 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'
对于使用普通属性解析找到的成员,不会调用我正在使用
__getattr__
将一些属性调用传递给包装类,如果这些属性是由A
的继承定义的,则__getattr__
将不会被调用。
__getattr__
。您可以改用__getattribute__
。
但是,如果你正在做的是覆盖基类A
的行为,那么我不明白为什么简单地覆盖这些方法不是一个选择:
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()
答案 2 :(得分:2)
您可以实现__getattribute__
来为不在B中的属性引发AttributeErrors:
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)
我很好奇,你为什么要这样做?
答案 3 :(得分:1)
我希望这能满足你(我认为它有点脏黑客):
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))
现在让我们测试一下:
>>> 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
本身继承了属性,所以会发生这种情况:
>>> B.attribute
'Hello'
我希望它不重要,如果你需要使用元类(可能会非常讨厌)。
答案 4 :(得分:0)
只要您在__init__
方法中定义属性并覆盖该方法,B
就无法运行A
的{{1}}代码,并且因此没有定义属性等。删除方法会更难,但似乎超出了问题的范围。