Why does c.print_a() output 'B'?
class A(object):
def __init__(self):
self.some_name = 'A'
def print_a(self):
print self.some_name
class B(object):
def __init__(self):
self.some_name = 'B'
def print_b(self):
print self.some_name
class C(A, B):
def __init__(self):
A.__init__(self)
B.__init__(self)
if __name__ == '__main__':
c = C()
c.print_a()
class A(object):
def __init__(self, some_name='A'):
self.some_name = some_name
def print_a(self):
print self.some_name
class B(object):
def __init__(self, some_name='B'):
self.some_name = some_name
def print_b(self):
print self.some_name
class C(A, B):
def __init__(self):
A.__init__(self, some_name='AAAAA')
B.__init__(self, some_name='BBBBB')
if __name__ == '__main__':
c = C()
c.print_a()
-
Let's try to clarify: you want C to set names for some objects of types A and B and later calling some print_a and print_b function get these names back ?kriss– kriss2011年01月13日 07:50:24 +00:00Commented Jan 13, 2011 at 7:50
-
Yes! why couldn't I format the code well as above?Suge– Suge2011年01月13日 07:54:04 +00:00Commented Jan 13, 2011 at 7:54
-
you must put 4 leading spaces before every line for the formatter to understand it's code. There is also an icon to do that on selected block.kriss– kriss2011年01月13日 08:07:53 +00:00Commented Jan 13, 2011 at 8:07
-
I used the '{}' icon to format the code but failed, what's the problem?Suge– Suge2011年01月13日 08:24:00 +00:00Commented Jan 13, 2011 at 8:24
-
@zkz, do these actually need to be instance attributes or will they be the same for every instance of a given class?aaronasterling– aaronasterling2011年01月13日 08:26:53 +00:00Commented Jan 13, 2011 at 8:26
3 Answers 3
You only have a single object here; the some_name property is shared between methods from all inherited classes. You call A.__init__, which sets it to A, then B.__init__, which changes it to B.
Also note that you're calling base methods incorrectly; use super:
class A(object):
def __init__(self):
self.some_name = 'A'
super(A, self).__init__()
def print_a(self):
print self.some_name
class B(object):
def __init__(self):
self.some_name = 'B'
super(B, self).__init__()
def print_b(self):
print self.some_name
class C(A, B):
def __init__(self):
super(C, self).__init__()
if __name__ == '__main__':
c = C()
c.print_a()
3 Comments
c.__dict__, which is simply a regular Python dictionary.self.__some_name, which will create a semi-"private" attribute to that class; it will actually create attributes named eg. _A__some_name and _B__some_name. This is very rarely used, though, and I don't recommend it.There's only one self, and you're overwriting its some_name in B.__init__. Maybe you're used to C++, where there would be two separate fields, A.some_name and B.some_name. This concept doesn't apply to Python, where attributes are created dynamically on assignment.
2 Comments
Say you want C to set names for some objects of types A and B and later calling some print_a and print_b methods on objects of type C get these names back ?
You can get this type of behavior using C++ inheritance model, but python model is very different. Only one object with one set of fields. If you want the C++ behavior, the simplest way is probably to declare subobjects (and it looks like a common abuse of inheritance over composition).
Looks like you are trying to do something like below:
class Printable(object):
def __init__(self, name):
self.name = name
def myprint(self):
print self.name
class C(object):
def __init__(self):
self.a = Printable('A')
self.b = Printable('B')
def print_a(self):
self.a.myprint()
def print_b(self):
self.a.myprint()
if __name__ == '__main__':
c = C()
c.print_a()