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()
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()
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.
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()
Related
Consider such code snippet:
class C:
def __init__(self):
print(id(self))
class D(C):
def __init__(self):
super(D, self).__init__()
print(id(super(D, self)))
if __name__ == '__main__':
d = D()
which produces for me:
140267543158096
140267543678800
Why this happens?
I expected that result should be the same because super(D, self) and self in C is the same object.
I have a class and a sub-class, I'd like to pass the whole of the self of the class to the sub-class. I can pass self over to the new class explicitly easily enough, e.g.
class foo:
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 'foo'
def foo_method(self):
print('a foo method')
class bar(foo):
def __init__(self, foo_object):
self.a = foo_object.a
self.b = foo_object.b
self.c = foo_object.c
def bar_method(self):
print('a bar method')
foo_object = foo(a = 'a', b = 'b')
bar_object = bar(foo_object)
bar_object.a
Is there a more succinct way to pass these over? Something like:
class bar(foo):
def __init__(self, foo_object):
self = self.foo_object
Update:
Thanks https://stackoverflow.com/users/10104112/bastien-antoine, the following solution worked:
class bar(foo):
def __init__(self, foo_object):
self.__dict__ = foo_object.__dict__.copy()
def bar_method(self):
print('a bar method with ' + str(self.c))
Have you tried the copy builtins library?
Otherwise I think you can easily implement your own .copy() method that would copy the values from the old object __dict__ to the new one. Something like this:
class MyObject:
a = None
def set_default_values(self):
self.a = 1
def copy(self, old):
if type(self) == type(old):
self.__dict__ = old.__dict__.copy()
else:
raise TypeError('Wrong type')
if __name__ == "__main__":
obj_1 = MyObject()
print(obj_1.a)
obj_1.set_default_values()
print(obj_1.a)
obj_2 = MyObject()
print(obj_2.a)
obj_2.copy(obj_1)
print(obj_2.a)
Note that I've added a type checking to be sure that you copy attributes that would exist otherwise, but I think simply self.__dict__ = old.__dict__.copy() would work fine, thought you might end up with attributes you might not suppose to have in the new object.
Hope this helps!
I think that you can do that with
class bar(foo):
def __init__(self):
super(bar, self).__init__()
with this code, you ran the init function for the subclass
Consider the code below:
class A(object):
attr = None
def __init__(self):
assert A.attr is not None
class B(object):
def __init__(self, attr):
A.attr = attr
class C(A):
def __init__(self):
super().__init__()
class D(A):
def __init__(self):
super().__init__()
nested_classes = {cls.__name__: cls for cls in {C, D}}
Above doesn't seem to work as I intend because:
>>> first_class = B("first")
>>> first_sub_class = first_class.C()
>>> first_sub_class.attr
'first'
>>> second_class = B("second")
>>> second_sub_class = second_class.C()
>>> second_sub_class.attr
'second'
>>> first_sub_class.attr
'second'
Is there a way to have first_sub_class.attr be first while having second_sub_class.attr be second? Possibly by having a metaclass whose scope is within B?
A few points:
I don't want to pass attr around, I want to set it while B is being initialized.
I don't want to circumnavigate the point above by using partial, since it breaks the rest of the code relying on __name__ or __qualname__ or alike.
I want to keep faithful to the current structure as much as possible.
To solve this problem just add the line self.attr = self.attr inside the __init__ function of A. Since you don't want to change the attributes of A, you will have to make the following changes:
class A(object):
attr = None
def __init__(self):
assert self.attr is not None # Don't refer to A, but to self to get the correct value
self.attr = self.attr
class B(object):
def __init__(self, attr):
self.attr = attr # Don't edit A, just save the value in own instance
def __getattribute__(self, item): # completely added, does some magic to ensure class.attr is set correctly
if item in B.nested_classes:
c = B.nested_classes[item]
c.attr = self.attr
return c
return super().__getattribute__(item)
class C(A):
def __init__(self):
super().__init__()
class D(A):
def __init__(self):
super().__init__()
nested_classes = {cls.__name__: cls for cls in {C, D}}
first_class = B("first")
first_sub_class = first_class.C()
print(first_sub_class.attr)
second_class = B("second")
second_sub_class = second_class.C()
print(second_sub_class.attr)
print(first_sub_class.attr)
You're insanely overcomplicating this:
class A:
def __init__(self, attr):
self.attr = attr
class C(A):
pass
class D(A):
pass
class B:
def __init__(self, attr):
self.attr = attr
def C(self):
return C(self.attr)
def D(self):
return D(self.attr)
Behaves exactly as desired:
>>> first_class = B("first")
>>> first_sub_class = first_class.C()
>>> first_sub_class.attr
'first'
>>> second_class = B("second")
>>> second_sub_class = second_class.C()
>>> second_sub_class.attr
'second'
>>> first_sub_class.attr
'first'
Given a parent class 'A'
class A(object):
def __init__(self,a,b):
self.a = a
self.b = b
def methodA():
# do something
What is the difference between making a subclass 'B' among the below options
Option 1
class B(A):
def methodB():
# do something
Option 2
class B(A):
def __init__(self,a,b):
A.__init__(self, a, b)
def methodB():
# do something
class A(object):
def __init__(self,a,b):
self.a = a
self.b = b
class B(A):
def __init__(self,a,b):
A.__init__(self, a, b)
def methodB():
pass
class C(A):
def methodB():
pass
b = B(1,2)
c = C(1,2)
print b.a == c.a # True
print b.b == c.b # True
In both class instantiation, init under class A will be ran only once.
so no, there is nothing significantly different.
class B is not clean IMO and poses no real purpose at all. It will be ran anyways.
If you wish to do something different in class B init, then yes, you can use this code.
class B(A):
def __init__(self,a,b):
A.__init__(self, a+1, b+1)
def methodB():
pass
I was wandering if you have any suggestions on how I should perform the following task in python:
Suppose I have the following classes:
class A(object):
self._classes = []
def magic(self):
c.foo() for c in self._classes
class B(object):
def foo():'''some cool stuff here'''
class C(B):
def foo():'''very cool stuff'''
class D(B):
def foo():'''very cool stuff'''
What I want to do is when class A is instantiated all classes of type B - (C and D) will be insantiated in self._classes, meaning _classes is [C(),D()].
The general motivation for this, is that I want the user to easily add classes without the need to know about class that uses them. Any help will be appricated.
Voila (thanks to this answer for all_subclasses()):
# recursively get all subclasses of a given class
def all_subclasses(cls):
return cls.__subclasses__() + [g for s in cls.__subclasses__()
for g in all_subclasses(s)]
class B(object):
def foo(self): print '''some cool stuff here in B'''
class C(B):
def foo(self): print '''very cool stuff in C'''
class D(B):
def foo(self): print '''very cool stuff in D'''
class E(D):
def foo(self): print '''very cool stuff in E'''
class A(object):
def __init__(self):
self._classes = [cls() for cls in all_subclasses(B)]
def magic(self):
for c in self._classes: c.foo()
# usage:
A().magic()
Output:
very cool stuff in C
very cool stuff in D
very cool stuff in E
If you know the module in question for example modulex, you can use dir(modulex) to list all the names in the module and then for each name x you can use modulex.__dict__.get(x) to get the actual object.
Then just check if it is of type of B.
In python you can store objects like other methods in list , so first note that you need to define other class then store them in a list , also you need to using self as your foo functions argument! if you haven't subclasses you can use this :
class B(object):
def foo(self):
print 'B'
class C(B):
def foo(self):
print 'C'
class D(B):
def foo(self):
print 'D'
class A(object):
def __init__(self):
self._classes = [B(),C(),D()]
def magic(self):
for c in self._classes:
c.foo()
A().magic()
resoult:
B
C
D