admin管理员组文章数量:1401241
I'm trying to use two classes, A
and B
, as mixing classes of AB
. They both have __init_subclass__
methods. The problem is that both __init__sublass__
methods have the same argument msg
. Therefore I've used an adaptor class B_
to rename B
's argument msg_b
. But I'm having trouble!
The nearest I have got is:
class A:
def __init_subclass__(cls, msg, **kwargs):
print(f'{cls=} A: {msg}')
super().__init_subclass__(**kwargs)
class B:
def __init_subclass__(cls, msg, **kwargs):
print(f'{cls=} B: {msg}')
super().__init_subclass__(**kwargs)
# Adaptor class `B_` needed because both `A` and `B` have an argument `msg`.
class B_:
# Rename `msg` to `msg_b`.
def __init_subclass__(cls, msg_b, **kwargs):
# `B.__init_subclass__(msg_b, **kwargs)` sets the subclass as `B` not `cls`, but otherwise works.
B.__init_subclass__.__func__(cls, msg=msg_b, **kwargs)
# Still need a `B`.
def __init__(self, *args, **kwargs):
self.b = B(*args, **kwargs)
# Forward all the attributes to `self.b`.
def __getattr__(self, item):
return getattr(self.b, item)
class AB(A, B_, msg='Hello.', msg_b='Also, hello.' ):
...
print(f'{AB()=}, {isinstance(AB(), A)=}, {isinstance(AB(), B_)=}, {isinstance(AB(), B)=}')
Which does call both __init_sublass__
s with the correct class argument, it prints:
cls=<class '__main__.AB'> A: Hello.
cls=<class '__main__.AB'> B: Also, hello.
But then you get the error:
Traceback (most recent call last):
File <definition of AB>, in <module>
class AB(A, B_, msg='Hello.', msg_b='Also, hello.' ):
File <A's>, in __init_subclass__
super().__init_subclass__(**kwargs)
File <B_'s>, in __init_subclass__
B.__init_subclass__.__func__(cls, msg=msg_b, **kwargs)
File <B's>, in __init_subclass__
super().__init_subclass__(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type
Presumably because B
is not a super type of AB
(B_
is). I’m not clear why super wants subtypes matching though!
Any ideas on how to fix this?
I'm trying to use two classes, A
and B
, as mixing classes of AB
. They both have __init_subclass__
methods. The problem is that both __init__sublass__
methods have the same argument msg
. Therefore I've used an adaptor class B_
to rename B
's argument msg_b
. But I'm having trouble!
The nearest I have got is:
class A:
def __init_subclass__(cls, msg, **kwargs):
print(f'{cls=} A: {msg}')
super().__init_subclass__(**kwargs)
class B:
def __init_subclass__(cls, msg, **kwargs):
print(f'{cls=} B: {msg}')
super().__init_subclass__(**kwargs)
# Adaptor class `B_` needed because both `A` and `B` have an argument `msg`.
class B_:
# Rename `msg` to `msg_b`.
def __init_subclass__(cls, msg_b, **kwargs):
# `B.__init_subclass__(msg_b, **kwargs)` sets the subclass as `B` not `cls`, but otherwise works.
B.__init_subclass__.__func__(cls, msg=msg_b, **kwargs)
# Still need a `B`.
def __init__(self, *args, **kwargs):
self.b = B(*args, **kwargs)
# Forward all the attributes to `self.b`.
def __getattr__(self, item):
return getattr(self.b, item)
class AB(A, B_, msg='Hello.', msg_b='Also, hello.' ):
...
print(f'{AB()=}, {isinstance(AB(), A)=}, {isinstance(AB(), B_)=}, {isinstance(AB(), B)=}')
Which does call both __init_sublass__
s with the correct class argument, it prints:
cls=<class '__main__.AB'> A: Hello.
cls=<class '__main__.AB'> B: Also, hello.
But then you get the error:
Traceback (most recent call last):
File <definition of AB>, in <module>
class AB(A, B_, msg='Hello.', msg_b='Also, hello.' ):
File <A's>, in __init_subclass__
super().__init_subclass__(**kwargs)
File <B_'s>, in __init_subclass__
B.__init_subclass__.__func__(cls, msg=msg_b, **kwargs)
File <B's>, in __init_subclass__
super().__init_subclass__(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type
Presumably because B
is not a super type of AB
(B_
is). I’m not clear why super wants subtypes matching though!
Any ideas on how to fix this?
Share Improve this question asked Mar 24 at 4:52 Howard LovattHoward Lovatt 1,0301 gold badge9 silver badges15 bronze badges 8 | Show 3 more comments1 Answer
Reset to default 1Presumably you don't have the authorization to modify A
or B
, or you would've renamed the msg
parameter in one of their __init_subclass__
s already.
One workaround then is to use an intermediary base class between A
and B
with an __init_subclass__
method that renames the argument msg_b
to msg
before passing the baton to B.__init_subclass__
:
class ABGlue:
def __init_subclass__(cls, msg_b, **kwargs):
super().__init_subclass__(msg=msg_b, **kwargs)
class AB(A, ABGlue, B, msg='Hello.', msg_b='Also, hello.' ):
...
print(f'{AB()=}')
print(f'{isinstance(AB(), A)=}')
print(f'{isinstance(AB(), B)=}')
This outputs something like:
cls=<class '__main__.AB'> A: Hello.
cls=<class '__main__.AB'> B: Also, hello.
AB()=<__main__.AB object at 0x14a498119460>
isinstance(AB(), A)=True
isinstance(AB(), B)=True
Demo: https://ideone/soXBWW
本文标签: pythonProblem if two inherited initsubclasss have the same argument nameStack Overflow
版权声明:本文标题:python - Problem if two inherited __init_subclass__s have the same argument name - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744260620a2597698.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
super()
finds the next class in the MRO but in your caseB
is not in the MRO, hence the error. You may patch the MRO but I'm not sure that's the correct thing to do. – Weijun Zhou Commented Mar 24 at 5:32super()
is a function to call the next method in a MRO. It does not mean the parent class. As long as your class is not part of the MRO it cannot possibly work. The MRO containsA, B_, object
. NoB
is there. – Weijun Zhou Commented Mar 24 at 6:30A
andB
are directly inherited fromobject
. More precisely,super()
returns a proxy object that helps to navigate the MRO and invokes the methods in turn. – Weijun Zhou Commented Mar 24 at 6:39