0

I have a little problem with a variable update.

I have my variable declared in my first function as such self.TestVar = 0 then if a certain count ==2 self.TestVar = 2

in a second function (in the same class) but called from within another class I want returning self.TestVar. no way.

AttributeError: 'ThndClass' object has no attribute 'TestVar'

I am most certainly not doing the good way, all I want is accessing self.TestVar = 2 from my other class that's it's but I can't find a proper way to do so in Python. It looks like my issue is that I get my self.TestVar = 2 in a "if" statement which make it live in another scope (or I might be wrong).

import sys
from PIL import Image
from PyQt4 import QtCore, QtGui


class MainWindow(QtGui.QWidget):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()

    def initUI(self):

        self.TestVar = 0
        self.TheCount = 2
        if self.TheCount ==2:
            self.TestVar = 2
        ThndClass()




    def Getit(self):
        print("called correctly")
        print(self.TestVar)
        return  self.TestVar



def main():

    app = QtGui.QApplication([])
    mw = MainWindow()
    sys.exit(app.exec_())


class ThndClass(QtGui.QWidget):
    def __init__(self):
        super(ThndClass, self).__init__()
        self.initUI2()

    def initUI2(self):
        print("Class Called")
        print(MainWindow.Getit(self))

if __name__ == '__main__':
    main()

If I remove the 2nd Class call :

import sys
from PIL import Image
from PyQt4 import QtCore, QtGui




class MainWindow(QtGui.QWidget):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()

    def initUI(self):

        self.TestVar = 0
        self.TheCount = 2
        if self.TheCount ==2:
            self.TestVar = 2
        self.Getit()




    def Getit(self):
        print("called correctly")
        print(self.TestVar)
        return  self.TestVar



def main():

    app = QtGui.QApplication([])
    mw = MainWindow()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

This works correctly, but I want to be able to call def Getit() from another class and get my result. Or simply get a way to directly access self.TestVar from my other class.

1
  • Well actually that is the minimal exemple of my actual code. Commented Oct 12, 2014 at 21:02

2 Answers 2

1

When you call

MainWindow.Getit(self)

in ThndClass.initUI2, you are treating MainWindow and ThndClass interchangeably, when they do not have the same attributes. Here is an actual minimal example:

class Parent():

    def __init__(self):
        pass


class Child1(Parent):

    def __init__(self):
        super().__init__()
        self.foo = "foo"

    def method(self): 
        print(type(self))
        print(self.foo)


class Child2(Parent):

    def __init__(self):
        super().__init__()
        self.bar = "bar"


c1 = Child1()
Child1.method(c1) # pass Child1 instance to Child1 instance method
c2 = Child2()
Child1.method(c2) # pass Child2 instance to Child1 instance method

and full output:

<class '__main__.Child1'> # gets a Child1 instance
foo # first call succeeds
<class '__main__.Child2'> # gets a Child2 instance (which doesn't have 'foo')
Traceback (most recent call last):
  File "C:/Python34/so.py", line 25, in <module>
    Child1.method(c2)
  File "C:/Python34/so.py", line 11, in method
    print(self.foo)
AttributeError: 'Child2' object has no attribute 'foo' # second call fails

However, as it is not clear what exactly the code is supposed to be doing, I can't suggest a fix. I don't know why you create but don't assign a ThndClass instance in MainWindow.initUI, for example.


Here is one possible fix; pass a Child1 instance to Child2.__init__, then use it either as an argument to Child2.method:

class Child2(Parent):

    def __init__(self, c1): # provide Child1 instance as parameter
        super().__init__()
        self.bar = "bar"
        self.method(c1) # pass instance to Child2.method

    def method(self, c1):
        c1.method() # call Child1.method with c1 as self parameter

(Note that c1.method() is equivalent to Child1.method(c1).)

or make it an instance attribute:

class Child2(Parent):

    def __init__(self, c1): # provide Child1 instance as parameter
        super().__init__()
        self.bar = "bar"
        self.c1 = c1 # make Child1 instance a Child2 instance attribute
        self.method() # now no argument needed

    def method(self):
        self.c1.method() # call Child1.method with c1 as self parameter

(Note that self.c1.method() is equivalent to Child1.method(self.c1).)

In use (either way):

>>> c1 = Child1()
>>> c2 = Child2(c1)
<class '__main__.Child1'> # Child1.method gets a Child1 instance
foo # and is called successfully
Sign up to request clarification or add additional context in comments.

8 Comments

Sorry I really can't make it simpler... I have add a second part in the comment showing my problem come well from the fact I am calling my function from another class, but that don't make it actually simple :(
Just want to access a function from another class :( It is so simple :(
Accessing the method is fine, but you can't pass one class as self as if it were another and expect everything to work.
Well if I remove the self : TypeError: Getit() missing 1 required positional argument: 'self' I would have think Python would have been smart enought to figure out that when I am calling MainWindow.Getit(self) I am refering to the self of my MainWindow class. So how I am supposed to do ?
You can't do it at all the way your code is currently structured - you don't have access to a MainWindow instance inside ThndClass.initUI2. You could pass one explicitly through ThndClass.__init__ by giving it a mw parameter, then call ThndClass(self) in MainWindow.initUI, but (again) as I don't know what you're trying to achieve I don't know whether that will get you anywhere useful.
|
0

Thank's to your help jonrsharpe here's my working code :)

import sys
from PIL import Image
from PyQt4 import QtCore, QtGui




class MainWindow(QtGui.QWidget):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()

    def initUI(self):

        self.TestVar = 0
        self.TheCount = 2
        if self.TheCount ==2:
            self.TestVar = 2
            Themain = self
            ThndClass(Themain)







    def Getit(self):
        print("called correctly")
        print(self.TestVar)
        return  self.TestVar



def main():

    app = QtGui.QApplication([])
    mw = MainWindow()
    sys.exit(app.exec_())


class ThndClass(QtGui.QWidget):
    def __init__(self, Themain):
        super(ThndClass, self).__init__()
        self.Themain = Themain
        self.initUI2()

    def initUI2(self):
        print("Class Called")
        print(self.Themain.Getit())

if __name__ == '__main__':
    main()

All working good now : ) Thanks you very much !

4 Comments

You can replace Themain = self; ThndClass(Themain) with, simply, ThndClass(self). Also, this should not be an answer (or an edit to the question); you don't need to provide the fixed code here, accepting my answer is sufficient.
Actually it don't really make sense to me with ThndClass(self) only as I already have a "self" int the second class. Things get confuse. On the way I wrote I am explicitly passing MainWindow self into TheMain and then passing TheMain as an argument of the second class; so everything is quite sipmle and clear. I have add my answer as, as you have seen, I have done it in a slighty diferent way to solve my problem. I still don't get exactly how the code should look with only ThndClass(self). But that helped me for sure.
You understand that the name(s) an object is assigned to in one function or method is completely unrelated to the name(s) it is assigned to in any another, right? Whatever name you assign self (there referring to the MainWindow instance) to in MainWindow.initUI (including leaving it as self), that object will still be assigned to the name Themain in ThndClass.__init__, where self (again, even if you pass the MainWindow instance directly by the name self in MainWindow.initUI) will refer to the new ThndClass instance.
Interesting link thanks, I get what you are saying now yes, indeed I can only write ThndClass(self) , self of class 1 will go directly in the second argument of class2, no need for me to give it the same name. thanks !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.