In python, I'm creating an object inside a class:
class A:
def __init__(self):
self.one = 1
self.two = B()
Now I define class B, and I want to access self.one from inside B()
class B()
def __init__(self):
self.three = "hello"
# here I want to change self.one from class A to self.one + 1
# how to do it without doing self.two = B(self.one) on class A
# definition?
something = A()
is there a way to reference the parent object property, or do we have to pass the value when creating the object ?
A is not a parent object, parent object is the object from which you inherit. B has no knowledge about A, you have to modify your classes structure, for example by passing reference to parent in B's constructor (which you say you do not want to do, althouth it is not entirely clear what do you mean by "without doing self.two = B(self.one)", as this would pass copy of self.one, not a reference, but this is the way to do it)
class A:
def __init__(self):
self.one = 1
self.two = B(self)
class B()
def __init__(self, parent):
self.three = "hello"
self.parent = parent
print self.parent.one # or do whatever you want with it
If you really have to do this, you can use introspection, but this is ugly, hacky, bad way of achieving the result
import inspect
class A():
def __init__(self):
self.one = 1
self.two = B()
class B():
def __init__(self):
self.three = "hello"
self.parent = inspect.currentframe().f_back.f_locals['self']
print self.parent.one
Related
In the code below, I have a class (MainClass) that contains two subclasses (Class1 and Class2).
class MainClass():
def __init__(self):
self.teste = 'abcdefg'
class Class1():
def __init__(self):
self.a = 'a'
self.b = 'b'
self.c = 'c'
class Class2(Class1):
def __init__(self):
super().__init__()
self.d = 'a'
self.e = 'b'
self.f = 'c'
Class2 when receiving Class1 as inheritance, automatically inherits the variables of Class1.
Now I would like to do the same and take these other variables to my MainClass.
I managed to do some things by assigning it to a specific variable like self.values (eg: self.values.a), however, I need these variables to be inside the main class for access. (eg: self.a)
Another way that worked was, doing this workaround: `self.dict.update(self.Class2.dict)
However, I am not convinced of the method. I would like to know if there is a better way to "inherit" this subclass in my main class. Is there any way using something like super().__init__() or something like that to accept my subclass?
Thanks!
What about if instead of inheritance you use composition, by this I mean creating an instance of Class2 in you constructor (init) method inside your main class, something like this:
# Define Class1 and Class2 at global scope
class Class1():
def __init__(self):
self.a = 'a'
self.b = 'b'
self.c = 'c'
class Class2(Class1):
def __init__(self):
super().__init__()
self.d = 'a'
self.e = 'b'
self.f = 'c'
class MainClass():
def __init__(self, *args, **kwargs):
self.class_2 = Class2(*args, **kwargs)
def some_function(self):
some_operation = self.class_2.a * self.class_2.b
# Now you can access class2 variables like this (self.class_2.some_variable)
UPDATE
Whay did you nested your classes inside your main class, can't you define them at global scope?
De-indent Class1 and Class2 so that they're no longer inside MainClass. Then MainClass can inherit either of them.
class Class1:
def __init__(self):
self.a = 'a'
self.b = 'b'
self.c = 'c'
class Class2(Class1):
def __init__(self):
super().__init__()
self.d = 'a'
self.e = 'b'
self.f = 'c'
class MainClass(Class2):
def __init__(self):
super().__init__()
self.teste = 'abcdefg'
I want to use the super function to write a string into a list of a specific instance of a parent object. Here's my code so far:
#!/usr/bin/env python
# test.py
class Master(object):
def __init__(self):
pass
class Sub1(Master):
list = []
def __init__(self):
pass
class Sub2(Sub1):
def __init__(self, name):
super(Sub2, self).list.append(name)
m = Master()
m.foo = Sub1()
m.foo.bar = Sub2('something')
m.bla = Sub1()
m.bla.blub = Sub2('else')
print(m.foo.list)
In this case the output is of course
['something', 'else']
However I want it to be just 'something'.
How can I achieve this?
I tried:
class Sub1(Master):
def __init__(self):
self.list = []
Which yields:
AttributeError: 'super' object has no attribute 'list'
Is there an easy solution?
As you have noted, if you define lst as a class attribute in Sub1, it is shared among all instances, which is not what you want. So you have to define lst as an instance attribute in Sub1 but then it has to be managed by an instance of Sub1 and not an instance of Sub2. Here is a modified code that offers what you expect:
class Master(object):
def __init__(self):
super().__init__()
class Sub1(Master):
def __init__(self):
super().__init__()
self.lst = []
def add(self, item):
self.lst.append(item.name)
class Sub2(Sub1):
def __init__(self, name):
super().__init__()
self.name = name
m = Master()
m.foo = Sub1()
m.foo.add(Sub2('something'))
m.bla = Sub1()
m.bla.add(Sub2('else'))
print(m.foo.lst)
print(m.bla.lst)
Here is the ouput:
['something'] <-- m.foo.lst
['else'] <-- m.bla.lst
Rem1: When using super() the whole class hierarchy has to be collaborative (i.e. use super() in the constructor).
Rem2: In Python3, super() is equivalent to super(classname, self)
Rem3: Don't use list as a variable name (it is a builtin type)
Rem4: My code stores only the name attribute in the list to mimic the example your gave, but I guess that in real life you would rather store instances of Sub2 in that list. To do so, simply remove the .name in the addfunction.
EDIT : Thinking a bit more about my answer, I came to another solution that may be closer to your initial attempt. Let me know which one works best for your actual problem...
class Master(object):
def __init__(self):
super().__init__()
class Sub1(Master):
def __init__(self):
super().__init__()
self.lst = []
class Sub2(Sub1):
def __init__(self, parent, name):
super().__init__()
parent.lst.append(name)
m = Master()
m.foo = Sub1()
m.foo.bar = Sub2(m.foo, 'something')
m.bla = Sub1()
m.bla.blub = Sub2(m.bla, 'else')
print(m.foo.lst)
print(m.bla.lst)
Your actual problem seems to be in the way you initialize list.
You need to assign it in __init__(), not within the class body, to avoid it being shared between all instances of the class (see Static class variables in Python).
class Sub1(Master):
def __init__(self):
self.list = []
I have the following problem
class A:
def __init__(self):
self.window = "<I am window class>"
class B(A):
def __init__(self):
super().__init__()
def createObject(self):
print(self.window) # it works here
self.c = C()
def drawRect(self):
print(self.window) # does not work when called from class C
class C(B):
def __init__(self):
self.draw()
def draw(self):
super().drawRect()
app = B()
app.createObject()
I have figured that, when I call the super().drawRect() function in class C
it sends the <__main__.C object at 0x0000023D99FA6748> as self.
How can I make class C, in function draw() send <__main__.B object at 0x0000017A2BA95358> in the super().drawRect()
I am asking because in the non-simplified code when I call the function from the B class itself, it prints the self.window, but when called from the C class it prints None
how can this be fixed?
what am I doing wrong?
There is no B object when you create an instance of C, there is only a C instance that happens to inherit from B.
So the answer to your question:
How can I make class C, in function draw() send <__main__.B object at 0x0000017A2BA95358> in the super().drawRect()
Is: You can't.
You could create a new B object (but that would defy the purpose of inheritance) alongside your C object.
But it seems more reasonable that you should just call super().__init__ in C.__init__:
class C(B):
def __init__(self):
super().__init__()
self.draw()
def draw(self):
super().drawRect()
It would be weird not to do that anyway. Because inheritance sort of implies that you extend rather than override completely.
But given the fact that you do self.c = C() in your B.createObject method and C inherits from B you should probably figure out another way (e.g. composition) instead of inheritance:
class A:
def __init__(self):
self.window = "<I am window class>"
class B(A):
def __init__(self):
super().__init__()
def createObject(self):
print(self.window) # it works here
self.c = C(self)
def drawRect(self):
print(self.window) # does not work when called from class C
class C(object): # don't inherit from B
def __init__(self, obj):
self.obj = obj
self.draw()
def draw(self):
self.obj.drawRect()
app = B()
app.createObject()
However this will create a reference cycle because you store the C instance as attribute of your B instance and the B instance as attribute of your C instance. It's also possible that you simplified the code too much, maybe the real code prevents composition in some way. However given the current code it seems like inheriting from B is a bad idea for your class C given that it overrides Bs behavior completely and doesn't use any of it's attributes (which it can't anyway because you overrode the methods).
you need to call to
super().__init__()
in class C constructor
Charlie
I have been searching an answer to my question but could not hit the related answer.
Basically i am trying to call a variable from a Class A thats actually GUI to another Class B my code goes like this:
class CLASSA(wx.Frame):
def Method(self):
self.Var = anyvalue
import CLASSA
class CLASSB():
def __init__(self):
self.Var = CLASSA().Method.Var
i have tried as above but its not working out. Isn't it possible to carry out as mentioned ?
At the very least, you need to actually call CLASSA.Method first:
class CLASSB():
def __init__(self):
self.Var = CLASSA().Method().Var
in order for the Var attribute of the CLASSA object to be initialized.
You do not give enough detail to know if Method is necessary. You could, for instance, simply initialize Var in CLASSA.__init__.
# With recommended capitalization
class A(wx.Frame):
def __init__(self):
self.var = any value
class B(object):
def __init__(self):
sef.var = A().var
It's also possible that B should be a subclass of A, in which case B simply inherits var from A:
>>> class B(A):
... pass
>>> print B().var
anyvalue
I'm facing a standstill here while trying to figure out how to have member classes access data from their parent when they are part of an external module.
Basically, this works (the B class can access is parent's methods like so: A.say_hi(A) ):
class A:
def __init__(self):
print("Initializing parent object...")
self.child = self.B()
class B:
def __init__(self):
print("Initializing child...")
A.say_hi(A)
def say_hi(self):
print("A class says hi")
However, this can get pretty messy if classes start getting extra large, so I have been placing my additional classes in files and importing them inline. The problem with that is I can no longer get the member class to access its parent's members and functions if I try to use 'import B.py' when class B is defined within.
Is there any way to get the original behavior without leaving the member class inside the same file as the parent?
Actually in your example you couldn't access instance of A in your class B. And the code A.say_hi(A) does work however is wrong. This has been said in comments to your question.
Here is how you do that if you want to be able to access parent instance:
Module b:
class B(object):
def __init__(self, parent):
self.parent = parent
def say_hi(self):
print 'Child says hi to his parent %s' % (
self.parent.__class__.__name__
)
self.parent.say_hi()
Module a:
from b import B
class A(object):
def __init__(self):
self.b = B(self)
def say_hi(self):
print 'Parent says hi!'
If you pass the object (a) to the class (b), you can call it directly.
class a():
def __init__(self):
print"Made A"
def test(self):
print ">>A Test"
class b():
def __init__(self,parent):
print"Made B"
self.parent = parent
def test(self):
print ">>B Test"
self.parent.test()
a = a()
a.test()
b = b(a)
b.test()