I have a little module that creates a window (program1). I've imported this into another python program of mine (program2).
How do I make program 2 get self.x and x that's in program1?
This is program1.
import Tkinter
class Class(Tkinter.Tk):
def __init__(self, parent):
Tkinter.Tk.__init__(self, parent)
self.parent = parent
self.Main()
def Main(self):
self.button= Tkinter.Button(self,text='hello')
self.button.pack()
self.x = 34
x = 62
def run():
app = Class(None)
app.mainloop()
if __name__ == "__main__":
run()
You can access the variable self.x as a member of an instance of Class:
c = Class(parent)
print(c.x)
You cannot access the local variable - it goes out of scope when the method call ends.
I'm not sure exactly what the purpose of 'self.x' and 'x' are but one thing to note in the 'Main' method of class Class
def Main(self):
self.button= Tkinter.Button(self,text='hello')
self.button.pack()
self.x = 34
x = 62
is that 'x' and 'self.x' are two different variables. The variable 'x' is a local variable for the method 'Main' and 'self.x' is an instance variable. Like Mark says you can access the instance variable 'self.x' as an attribute of an instance of Class, but the method variable 'x' is only accessible from within the 'Main' method. If you would like to have the ability to access the method variable 'x' then you could change the signature of the 'Main' method as follows.
def Main(self,x=62):
self.button= Tkinter.Button(self,text='hello')
self.button.pack()
self.x = 34
return x
This way you can set the value of the method variable 'x' when you call the 'Main' method from an instance of Class
>> c = Class()
>> c.Main(4)
4
or just keep the default
>> c.Main()
62
and as before like Mark said you will have access to the instance variable 'self.x'
>> c.x
34
Related
In a code, there is a class that has a function named 'goal_callback'. In the function, variables are defined using .init prefix and others are defined normally without the prefix.
I know that the self. prefix is used to make the variable a 'class variable' so that it can be accessible to every function in class. So in the code, I have, only one function present, does it make any difference if we define the variables with the self. prefix or not.
What exactly will be the difference between the '_pub_takeoff' variable and the 'takeoff_or_land' variable?
#! /usr/bin/env python
class CustomActionMsgClass(object):
def __init__(self):
self._as = actionlib.SimpleActionServer("action_custom_msg_as", CustomActionMsgAction,
self.goal_callback, False)
def goal_callback(self, goal):
success = True
r = rospy.Rate(1)
self._pub_takeoff = rospy.Publisher('/drone/takeoff', Empty, queue_size=1)
self._takeoff_msg = Empty()
self._land_msg = Empty()
# Get the goal word: UP or DOWN
takeoff_or_land = goal.goal #goal has attribute named 'goal'.
if __name__ == '__main__':
rospy.init_node('action_custom_msg')
CustomActionMsgClass()
rospy.spin()
Here is an example for object-level and class-level variables.
class A(object):
Z = 3 # class variable. Upper-case is good code style for class-level variables
# defined inside the class but outsize of it's methods
def __init__(self):
self.x = 1 # object variable
y = 2 # local variable; it will lost after returning from the function
def some_method(self):
self.w = 4 # object variable too
# Note that it is not recommended to define
# object variables outside of __init__()
In your code _pub_takeoff is variable of the object; takeoff_or_land is local variable.
How does self.x work if x is not a class bound or instance bound variable? In this case, is there any benefit to use it?
My Analysis:
In general if we execute a.a1 = 5, interpreter will give NameEror: name a is not defined. It means we can't define variable using letter ., as it is used to call attribute of an object.
If I write code as
a = 5
a.a1 = 10
It gives AttributeError: int object has no attribute x. It was expected.
Now look at my below code
class Example:
p = 1
def __init__(self):
self.q = 2
def my_function(self):
self.x = 5
return self.x
obj = Example()
print(obj.my_function())
print(dir(obj), obj.__dict__)
As x is neither a class bound variable nor an instance bound variable. So I assume x is not an attribute of self but it executes successfully without any error. So I am wondering, how does it work. Please explain it, also let me know the use because as per explanation we can use it.
Doing self.x = 5 you simply create a new attribute which you can later modify, just like an ordinary variable ; except you access it through the instance.
At that moment you are declaring and instantiating a new field for the object of type Example. When in other function, there would be reference to self.x, no error would be thrown. When no declaration was made - runtime error would be raised, for example:
class Example:
p = 1
def __init__(self):
self.q = 2
def my_function(self):
self.x = 5
return self.x
def other(self):
return self.x
obj = Example()
print(obj.other())
print(obj.my_function())
This results in AttributeError: 'Example' object has no attribute 'x'.
One needs to bear in mind execution order, so that the field is declared and instantiated before referenced.
This is standard way of defining attribute. Here you can find more about classes and attributes: https://docs.python.org/2/tutorial/classes.html
I have a class, call it Test, which has a variable var. It uses this variable in its __init__ mathod, and maybe looks something like this:
class Test(object):
var = 0
def __init__(self):
print(self.var)
In order to change this variable before I initialise the class, this seemed logical
test = Test
test.var = 42
test.__init__(test)
...and behaves like I expected it to. (printing 42)
However, when the code looks like this:
class Test(Canvas):
var = 0
def __init__(self, parent):
Canvas.__init__(self, parent)
self.pack()
print(self.var)
test = Test
test.var = 42
test.__init__(test, frame) #tkinter frame I had made elsewhere
... it throws an error at the canvas.__init__ line, complaining that
TypeError: _options() missing 1 required positional argument: 'cnf'
I doubt this is a problem with the cnf parameters, as the class works fine when called 'normally', as in test = Test(). I have a feeling the parameters are being passed differently.
Can someone shed some light?
Thanks in advance
You seem to have a misunderstanding of how python classes work.
In your code you're doing test = Test, which does nothing but make test point to the class Test. It does not create an instance of Test.
If you want to change the value of a class value, there's no need to do an assignment to a temporary variable first. For example. to create a class that has var set to zero, and you later want to change it to 42, you can do it this way:
class Test(object):
var = 0
...
Test.var = 42
Also, you should never call __init__ directly, except perhaps when calling the function of the superclass with the __init__ of a subclass. Instead, you create an instance of the class which will automatically call the __init__ for you:
test = Test()
This all works the same whether you inherit from a tkinter class or any other class.
When you run the following example, it will print out 42:
import tkinter as tk
class Test(tk.Canvas):
var = 0
def __init__(self, parent):
tk.Canvas.__init__(self, parent)
self.pack()
print(self.var)
Test.var = 42
root = tk.Tk()
test = Test(root)
Note that because this is a class variable, changing it once will change it for all instances.
Hi I have staring programming with c and I conld'nt understand value scope in python.
here is my code
class ScenarioEnvironment():
def __init__(self):
print(self)
class report():
config = ScenarioEnvironment()
def __init__(self):
self.config = ScenarioEnvironment()
what happens passing config and config at init()?
and I wonder the value scope which config will be class valuable?
You need to know the differences between class attribute and instance object attribute.
Maybe these codes will help you:
class TestConfig1(object):
config = 1
def __init__(self):
self.config = 2
class TestConfig2(object):
config = 1
def __init__(self):
self.config2 = 2
if __name__ == "__main__":
print TestConfig1.config
t = TestConfig1()
print t.config
t2 = TestConfig2()
print t2.config
print t2.config2
more you can see the python blog.click here
Since your question seems a bit ambiguous, I'll just comment/fix your code:
class ScenarioEnvironment():
def __init__(self,x):
self.x = x # Assigning instance variable x to constructor parameter x.
print(self) # You're printing the object instance.
class report():
# Static variable shared amongst all classes.
config = ScenarioEnvironment(None) # Assigned to new instance of ScenarioEnvironment.
def __init__(self):
# No argument, must pass one (None).
# self.config is to a new ScenarioEnvironment instance.
self.config = ScenarioEnvironment(None)
Lets try out the classes.
Output:
s = ScenarioEnvironment(None)
r = report()
>>> <__main__.ScenarioEnvironment instance at 0x026F4238>
>>> <__main__.ScenarioEnvironment instance at 0x026F4300>
>>> <__main__.ScenarioEnvironment instance at 0x026F4350>
In Python, if I define a variable:
my_var = (1,2,3)
and try to access it in __init__ function of a class:
class MyClass:
def __init__(self):
print my_var
I can access it and print my_var without stating (global my_var).
If I put my_var right after class MyClass however, I get scope error (no global variable found).
What is the reason for this? How should I do this? Where can I read about this to learn? I did read Python Class page but I did not encounter its explanation.
Thank you
Complementing #mgilson's answer:
Note that Python Class variables are shared among the class instances. And the behaviour might be VERY unexpected and seem weird. In practice it works like this:
class MyClass(object):
my_var = 10
def __init__(self):
print(self.my_var)
m1 = MyClass()
print(m1.my_var)
>>> 10 # this is fine
MyClass.my_var = 20
print(m1.my_var)
>>> 20 # WTF? :) --> shared value
m2 = MyClass()
print(m2.my_var)
>>> 20 # this is expected
m1.my_var = 30
print(MyClass.my_var)
>>> 20 # this is also expected
MyClass.my_var = 40
print(m1.my_var)
>>> 30 # But WHY? Isn't it shared? -->
# The value WAS shared until m1.my_var = 30 has happened.
print(m2.my_var)
>>> 40 # yep m2.my_var's value is still shared :)
When you put it right after class MyClass, it becomes a class attribute and you can get access to it via MyClass.my_var or as self.my_var from within the class (provided you don't create an instance variable with the same name).
Here's a little demo:
my_var = 'global'
class MyClass(object):
my_var = 'class'
def __init__(self):
print my_var #global
print MyClass.my_var #class
print self.my_var #class -- Only since we haven't set this attribute on the instance
self.my_var = 'instance' #set instance attribute.
print self.my_var #instance
print MyClass.my_var #class
If you write:
class MyClass(object):
my_var = (1, 2, 3)
you are defining an attribute of MyClass, not a variable. In your __init__ method, then, it is MyClass.my_var.
Once it's inside the class definition, it's no longer global, it's now in the class object's namespace. You can access it with self.my_var within __init__ though...