class A(object):
def print_some(self):
print 'a'
class B(object):
def print_some(self):
print 'b'
class C(A, B):
pass
c = C()
print c.print_some()
'a'
What i expect of the output is 'b'. The reason i want to do this is because i want to override some method, let's say form_valid from CreateView in django, simply by inheriting a class i write containing custom form_valid, or there are better approaches?
class A is first (left) in the class C(A, B) instruction, so you are getting the print_some method from it (A class). Read here.
From your question I expect you can change the inheritance of B and C, can't you? So why don't you build up the inheritance like
A <- B <- C
Or in code:
class A(object):
....
class B(A):
...
class C(B):
...
This should give you the desired output.
Related
I'm trying to define an inner class in a hierarchy of classes and I can't figure out the right way to make sure that the inner class correctly subclasses the parents' corresponding inner classes without throwing an exception in the case where one or more of the immediate parent classes has not themselves subclassed that inner class.
I've also tried many times to write this question in a more approachable way, so I apologise if it's a bit of a headscratcher!
Hopefully this example will clarify things:
(assume for this question that we don't know which, if any, of B or C define subclasses of A.Inner - obviously in this example neither do, but that's not the point.)
Cheers.
class A:
class Inner:
...
class B(A):
...
class C(A):
...
class D(B, C):
class Inner(B.Inner, C.Inner):
...
>>>
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-163-6f592c573c6f> in <module>
6 class C(A):
7 ...
----> 8 class D(B, C):
9 class Inner(B.Inner, C.Inner):
10 ...
<ipython-input-163-6f592c573c6f> in D()
7 ...
8 class D(B, C):
----> 9 class Inner(B.Inner, C.Inner):
10 ...
TypeError: duplicate base class Inner
You can use the fact that if A.inner is a class, and B or C do not explicitly subclass the inner class, then B.inner and C.inner are the same object -> A.inner:
>>> class A:
... class inner: pass
...
>>> class B(A): pass
...
>>> class C(A): pass
...
>>> B.inner is C.inner
True
>>> C.inner is A.inner
True
We're leveraging a dictionary to ensure uniqueness and order (use collections.OrderedDict or some other ordered_set implementation if you are on a version that does not yet guarantee dict order). We can determine which classes we need to subclass on D.inner like so:
inner_classes = {getattr(klass, 'inner'): True for klass in [C, B] # control your MRO here.
if getattr(klass, 'inner') is not A.inner}
# Ensure that we also extend A.inner, in case neither B nor C subclasses A.inner
inner_classes[A.inner] = True
class D(A):
class inner(*inner_classes.keys()): pass
In this way we get consistent MRO, it doesn't matter which class (if any) subclasses A.inner, and D.inner works.
Alright folks, going on from g.d.d.c's partial answer, I think we have a solution here that works cleanly and simply for arbitrary class hierarchies.
I'll do some testing on it for a couple of days and see if it does the job. I'm still not happy with the requirement to specify the bases manually - I feel like some sort of introspection inside the wrapper could handle this automatically. Please do chime in with more suggestions.
Thanks heaps again to g.d.d.c for kicking me in the right direction!
def inner_class(*bases):
def _inner_class(cls):
bs = []
for b in bases:
try: bs.append(getattr(b, cls.__name__))
except AttributeError: pass
bs = sorted(set(bs), key = bs.index)
return type(cls)(
cls.__name__,
(cls, *bs),
{}
)
return _inner_class
class A:
class Inner:
...
class B(A):
class Inner(A.Inner):
...
class C(A):
...
class D(A):
...
class E(B, C, D):
#inner_class(B, C, D)
class Inner:
...
print(E.Inner.mro())
>>> [<class '__main__.Inner'>, <class '__main__.E.Inner'>, <class '__main__.B.Inner'>, <class '__main__.A.Inner'>, <class 'object'>]
I want to access an attribute of the class instance that called a function :
for example:
class A:
def a(self):
return B.q
class B:
q=0
def b(self):
M=A()
return M.a()
c=B()
c.q = 6
print(c.b())
the output will be 0 but I want it to print the q attribute of the instance c of the class B which has the value 6
Pass the instance as a parameter.
class A:
def a(self, b):
return b.q
class B:
q=0
def b(self):
M=A()
return M.a(self)
c=B()
c.q = 6
print(c.b())
This appears to be very bad program design. What are you trying to accomplish with this?
You have a class attribute and an instance attribute -- in that class -- of the same name, q. This makes your code difficult to follow and to maintain.
You have method B.b instantiate an instance of class A. You immediately call A.a, which has been assigned the questionable task of returning an instance attribute from and object of class B.
Clean up your design.
Use init appropriately for each class.
Design your class methods to work appropriately with the characteristics of instances of that class. Your question strongly suggests that your design is not yet clean in your mind, nor in code.
define an init method so that you can work with the instance attributes instead of the class variable
class A:
def a(self):
return B.q
class B:
def __init__(self):
self.q = 0
def b(self):
M=A()
return M.a()
c=B()
c.q = 6
print(c.b())
I am trying to write a plugin environment where I need to do multiple inheritances on an unknown number of classes. Therefore, I have opted to use the type class creation:
class A(object):
def __init__(self,s):
self.a="a"
def testA(self,x):
print(x)
class B(object):
def __init__(self,s):
self.b="b"
def testA(self,x):
print(x)
C = type('C', (A,B), {})
x= C("test")
print x.b
When I run the above code, I get the error:
AttributeError: 'C' object has no attribute 'b'
This is because only the init for class A is being run when the instance for class C is initialized. My question is how can I get the class C to have both the init for class A as well as the init for class B to run when an instance of class C is initialized. I do realize that if I had class C like the following it would work:
class C(A,B):
def __init__(self,s):
A.__init__(self,s)
B.__init__(self,s)
However, given that I need to have a dynamic list of classes inherited this will not work.
It seems you're using python 2 so I'm using this old python 2 super() syntax where you have to specify the class and the instance, although it would work in python 3 as well. In python 3 you could also use the shorter super() form without parameters.
For multiple inheritance to work is important that the grandparent class __init__ signature matches the signature of all siblings for that method. To do that, define a common parent class (MyParent in this example) whose __init__ has the same parameter list as all the childs. It will take care of calling the object's __init__ that doesn't take any parameter, for us.
from __future__ import print_function
class MyParent(object):
def __init__(self, s):
super(MyParent, self).__init__()
class A(MyParent):
def __init__(self, s):
self.a = "a"
super(A, self).__init__(s)
def testA(self, x):
print(x)
class B(MyParent):
def __init__(self, s):
self.b = "b"
super(B, self).__init__(s)
def testA(self,x):
print(x)
C = type('C', (A, B), {})
x = C("test")
print(x.b)
You can define as many children to MyParent as you want, and then all __init__ methods will be called, provided you used super() correctly.
I have three different class's and some variables in it
class A(object):
a = "Hello"
b = "World"
class B(object):
a = "Hello"
b = "World"
class C(object):
a = "Hello"
b = "World"
Where a = "Hello" and b = "World" is common to all class's, how can I declare these variables as a global class and Inherit the properties to these tables.
I Tried in this way, but am not able to get the solution.
class G(object):
a = "Hello"
b = "World"
class A(object, G):
pass
Here I'm trying to inherit the whole property of the class. Please help me to solve this thanks in advance.
class A(object):
a = "Hello"
b = "World"
class B(A):
something
class C(B):
something
c = C()
print(c.a,c.b)
You don't have to re-declare a and b each time or else why would you inherit in the first place. If you declare them you basically are overwriting the parent's variable with the child's. If you do that you can call the parent's one with super().
This is how you do it. Please let know in comments if there is something that you don't understand, or if I am doing anything wrong.
class A(object):
a = "Hello"
b = "World"
class B(A):
pass
class C(B):
pass
c = C()
print(c.a,c.b)
Prints Hello World
Define class A as:
class A(G):
pass
The problem with repeating the base class object is that it creates a base class resolution conflict, since A was inheriting it twice: Once directly, and once indirectly through class G.
I am instantiating a class inside another one:
class A(F):
def __init__(self):
return
b = B()
Class B also inherits class F:
class B(F):
def __init__(self):
return
There are properties of F which have been defined in class A, which I need to access inside class B. (a MySQL connection and a logging handler.)
I would like B to have the properties which have been set to F, when they were instantiated initially in A, so I can use the logging/mysql handlers inside B without re-instantiating them.
How can I go about this? Sorry if the question is unclear.
Put the stuff you want to share in F and both A and B will be able to share it. Eg
class F(object):
def useful(self):
pass
class A(F):
def something(self):
self.useful()
class B(F):
def something_else(self):
self.useful()