Let's say I have a python class:
class A:
baz = 1
def bar(self, x):
return self.baz * x
Now let's say I have a second class, keeps an instance of the first class as an attribute:
class B:
def __init__(self, a, z):
self.a = a
self.z = z
@property
def baz(self):
return z
Notice that B
does not inherit from class A
; it's not even aware of it.
How can I make an instance of B
act like an instance of A
, except for the behavior explicitly given in the definition of B
? For example, if I want
a = A()
b = B(a, 2)
assert b.bar(2) == 4
that is, use A.bar
but passing in b
as self
. To get this behavior, it's not enough to just do something like
class B:
...
def getattr(self, attribute):
return getattr(self.a, attribute)
That will allow any method not defined on self
to be looked up on self.a
. This works for constants and static methods, but for instance methods it's wrong, because b.bar
would resolve to A.bar
with self
bound to ba
.
Basically what I want to do is dynamically insert A
(or more generally, whatever the type of a
in B.__init__
is) into the MRO for that instance. In other words, to make B
inherit from whatever the type of a
is, on a per-instance basis.
Is such a thing possible?
A hackey way: you can do the method binding yourself in __getattr__
, note, all functions are descriptors, so they have a __get__
method!
In [47]: class A:
...: baz = 1
...:
...: def bar(self, x):
...: return self.baz * x
...:
...:
...: class B:
...: def __init__(self, a, z):
...: self.a = a
...: self.z = z
...:
...: @property
...: def baz(self):
...: return self.z
...:
...: def __getattr__(self, attribute):
...: try:
...: attr = getattr(type(self.a), attribute)
...: except AttributeError:
...: return getattr(self.a, attribute)
...:
...: if callable(attr):
...: return attr.__get__(self)
...: return attr
...:
...:
...:
In [48]: a = A()
...: b = B(a, 2)
...: b.bar(2)
...:
Out[48]: 4
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.