I was writing a small python script to understand a concept and got another confusion. Here's the code -
x = 5
y = 3
class Exp(object):
def __init__(self, x, y):
self.x = x
self.y = y
print("In",x, y, self.x, self.y)
print("Middle",x,y)
print("Out",x,y)
Exp(1,2)
The output is -
Middle 5 3
Out 5 3
In 1 2 1 2
Now, my concept was python interpreter starts reading and executing the code from the first line to last line. It executes the code inside a class only when it is "called", not when it is defined. So, the output should print "Out" first. But here it is printing "Middle" first. This should not happen, as python interpreter when first encounters "Middle" - it is within the definition, and thus should not be executed at that time. It should be executed only after reading the last line of code where the class "Exp" is called.
I searched on Google and StackOverflow for the solution but couldn't find one explaining it for the class.
Kindly help me understand where I'm getting it wrong...
Your doubt is right. I had the same doubt like 6 months back and a friend of mine helped me figure the answer out.
print("Middle",x,y)
The above statement does not belong to any method. It belongs to the class Exp. The __init__() method is executed when an object is created and is internally called by the Python interpreter when an object is instantiated from your end. Since the above statement is not a part of any method, the interpreter executes it before invoking the __init__ method. Since variables x and y are both available in the scope of class Exp, it isn't considered an error and the interpreter executes it.
If you remove the declarations of variables x and y, you will see a NameError like below.
Traceback (most recent call last):
File "trial.py", line 9, in <module>
print("Middle",x,y)
NameError: name 'x' is not defined
And this is because x and y are not even created from the class Exp's perspective.
This odd behaviour happens because your print("Middle",x,y) is not inside a definition of a function, so it gets called before print("Out",x,y).
Your code is equivalent to:
x = 5
y = 3
class Exp(object):
def __init__(self, x, y):
self.x = x
self.y = y
print("In",x, y, self.x, self.y)
print("Middle",x,y)
print("Out",x,y)
Exp(1,2)
Whose output will be:
Middle 5 3
Out 5 3
In 1 2 1 2
One of the possible ways to correct this is to define print("Middle",x,y), say within the constructor.
x = 5
y = 3
class Exp(object):
def __init__(self, x, y):
self.x = x
self.y = y
print("In",x, y, self.x, self.y)
print("Middle",x,y)
print("Out",x,y)
Exp(1,2)
The output you will then get is:
Out 5 3
In 1 2 1 2
Middle 1 2
Class methods are not executed as compiled, they have to be invoked.
With your code above the print(middle) statement is not defined within a class method. Whereas the print(In) statement is defined within the init (also called constructor) method.
When you run the code and the compiler runs through the script, the print(In) statement is not invoked until the init() method is called.
However this print(middle) line is not defined as a method of the Exp class, but is executable as a built-in function, despite the whitespace. Consequently as Python compiles the class Exp the print(middle) statement is invoked. This is the only time the print(middle) statement would be invoked. As it is not in a class method it cannot be accessed later in the program.
If you try the code below, you get the output 'Out' and 'In'. You would only get 'Middle' by calling Exp.test()
x = 5
y = 3
class Exp(object):
def __init__(self, x, y):
self.x = x
self.y = y
print("In",x, y, self.x, self.y)
def test(self):
print("Middle",x,y)
print("Out",x,y)
Exp(1,2)
Related
This question already has answers here:
What's the pythonic way to use getters and setters?
(8 answers)
Closed 2 years ago.
Assume that I have a class which requires pre-treatment of an input variable x. Towards this end, I have implemented a function within this class to set the variable (including the pre-treatment). To fool-proof the algorithm, I would like to know whether there is a way to catch attempts of users trying to set x manually, instead of calling the correct function. As a small dummy example, consider the following:
class dummy():
def __init__(self, x):
# This function initializes the instance
self.x = x
def adjust_x(self):
# This function makes some change to x
self.x += 5
def set_x(self, x):
# This function initializes x correctly
self.x = x
self.adjust_x()
instance = dummy(3)
print('Initialized correctly, the value of x is: ' + str(instance.x))
# We can also set x later on, using the correct function
instance.set_x(3)
print('Calling the function to set x, we get: ' + str(instance.x))
# However, if the user would try to set x directly, the variable does not get
# correctly adjusted:
instance.x = 3
print('Direct setting: ' + str(instance.x) + ' (/= 8, because instance.adjust_x() was not called)')
Is there a way to catch someone using instance.x to set x? I'd like to raise an error or a warning in that situation.
In Python, you can restrict the access of an attribute (that's the equivalent of setting the access modifier of a field to private) by prepending a double underscore to the attribute.
Example
class Object():
def __init__(self, name):
self.__name = name
Trying to access instance.name or instance.__name would raise an AttributeError.
Note
As #mkrieger1 pointed out, the double underscores were not meant to prevent access but I find it that it works. More about private variables in Python can be found here.
I am following a tutorial from: http://sthurlow.com/python/lesson08/
I do not understand the following:
Any function or variable created on the first level of indentation
(that is, lines of code that start one TAB to the right of where we
put class Shape is automatically put into self. To access these
functions and variables elsewhere inside the class, their name must be
preceded with self and a full-stop (e.g. self.variable_name).
Here is part of the example used:
#An example of a class
class Shape:
def __init__(self,x,y):
self.x = x
self.y = y
description = "This shape has not been described yet"
author = "Nobody has claimed to make this shape yet"
def area(self):
return self.x * self.y
def perimeter(self):
return 2 * self.x + 2 * self.y
def describe(self,text):
self.description = text
I understand how self.x affects __ init __ part of the code, but not for functions because they seem to play by different rules (e.g. i cannot access variables from inside functions)... In other words, i'm trying to figure out what self.x is doing in the functions. if I put only x in the function what does it do? If I put x in __ int __ it only 'lives' in __ int and cannot be called when I make an object . If I put self.x in __int it can be called when I make an object. I am wondering about self.x vs x in functions because I cannot figure out code to test it
I understand how self.x affects __ init __ part of the code, but not for functions because they seem to play by different rules (e.g. i cannot access variables from inside functions)...
No, they really don't play by different rules. __init__ is just a function, defined in a class definition, exactly like area.
They both take self as an explicit parameter, and have to use that self if they want to access or set instance attributes like x, or call instance methods like describe.
The only difference is how they're called:
area is something that you call directly. When you write my_shape.area(), that calls the area function passing my_shape as the value of self.
__init__ is something that Python calls automatically. When you write my_shape = Shape(2, 3), Python constructs a new Shape object, and then calls the __init__ function passing that new object as self (and 2 and 3 as x and y).
In other words, i'm trying to figure out what self.x is doing in the functions. if I put only x in the function what does it do?
Plain old x is a local variable if you have one, a global variable if you don't. So, inside __init__, where there's a parameter named x, it's that x (e.g., it's 2 in the Shape(2, 3) example). Inside area, where there is nothing local named x, it would be a global variable. But you probably don't have a global named x either, so it would raise a NameError.
self.x, on the other hand, is the x attribute of whatever self is. As explained above, self is a newly-created Shape instance inside __init__, and whatever Shape instance you called area on inside area.
If I put x in __ int __ it only 'lives' in __ int and cannot be called when I make an object .
Yes, if you define something named x in __init__, it's a local variable, so it only lives within __init__. That's true for any function—not just __init__, not even just methods defined in a class; that's what local variables mean. Once the function ends, those variables are gone, and nobody can ever access them again. (This isn't quite true if closures are involved, but they aren't here, so ignore that.)
I don't know what you mean by "called", because you don't normally call values that aren't functions/methods/classes, and I don't know what you mean by "when I make an object", because when you make an object is exactly when __init__ gets called.
If I put self.x in __int it can be called when I make an object.
Anything you assign to self.x inside __init__ gets stored as part of that self instance. So, it can be accessed again by anyone who has that instance. For example, inside area, you can access it as self.x. Or, from top-level code, you can access it as my_shape.x.
Again, there's nothing special about __init__ here; you could do the same thing in another method—as the describe method does. You could even do it from outside the object.
For example:
>>> my_shape = Shape(2, 3)
>>> my_shape.x
2
>>> my_shape.area()
6
>>> my_shape.x = 4
>>> my_shape.area()
12
Again, I don't know what you mean by "called" or by "when I make an object".
I am wondering about self.x vs x in functions because I cannot figure out code to test it
Try adding this method:
def play_with_x(self):
x = 10
print(x)
print(self.x)
x = 20
print(x)
print(self.x)
self.x = 30
print(x)
print(self.x)
Then try this:
>>> x = 0
>>> my_shape = Shape(2, 3)
>>> my_shape.play_with_x()
You'll see that it can change x and self.x. They're completely independent of each other, but mostly seem to act the same from within one function. But now:
>>> x
0
>>> my_shape.x
30
That x = 20 didn't do anything to the global variable x. But that self.x = 30 did permanently change self, which is the same object as my_shape, so my_shape.x is now 30.
I have the following Python code to represent the velocity of an object.
class Vector(object):
def __init__(self, x, y):
self.x, self.y = x, y
class Physics(object):
def __init__(self, velocity):
self.velocity = velocity
#property
def velocity(self):
return self._velocity
#velocity.setter
def velocity(self, velocity):
self._velocity = velocity
self._hi_res_velocity = Vector(velocity.x * 1000, velocity.y * 1000)
My intent is for velocity.x to set both _velocity.x and _hi_res_velocity.x, but the setter isn't run in this case. I get the following:
>>> myObject = Physics(Vector(10, 20))
>>> myObject.velocity.x = 30
>>> myObject._velocity.x, myObject._hi_res_velocity.x
(30, 10000)
I think the getter for velocity is run and then x is set on that returned value, but is it possible to implement the behavior I want using properties? I feel like I'll have to rewrite my logic to make this work.
When you do this:
myObject.velocity.x = 30
|_______________|
|
|___ this part already resolved the property
The myObject.velocity is already returning a Velocity instance, and this happens first. Then the .x which follows is just a normal attribute access, since the Vector class doesn't define a descriptor for handling x.
I'll suggest a different design, make either the "velocity" or the "hi_res_velocity" a getter-only, i.e. one of them is computed from the other whenever needed. This will resolve your issue, and also has the advantage that you don't have to store the same state twice.
I've been trying to make a soccer game using Python. Most of the problems I've run into I've been able to find a way around. However, I'm getting stuck on the error "global name '---' not defined", referring to a method name. From what I've seen, the problem deals with trying to call a method from a method. Since pasting my code would take too much time explaining what was going on, I wrote a very basic example of the problem:
class example():
def doMath(x,y):
z = x + y
z = square(z)
return z
def square(z):
z = z * z
return z
print doMath(5,4)
This is in no way meant to be a program worth writing, nor is it the smart way of doing that calculation... It just imitates the problem I'm having. This code will not work, because the method "doMath" doesn't know the method "square" exists. I've seen this fixed by making the square method a submethod (I don't know what it's called, it's just indented under the primary method). However, that is not viable in my soccer code since I'd be having multiple methods calling it. I've seen similar questions to this, but the answers still don't fit my code. A global function seems like it would be what I'm looking for, but it typically leads to an error of something not existing. I could just add a bunch of instructions to the main, but that's alot of work and lines of code that I'd prefer not to have to add - it would make it pretty ugly.
So the main question is... how can I get the doMath method to call the square method without having to combine them.
While we're at it... I've been calling these methods rather than functions... am I correct on that?
As others have noted, you need to use self, and you need to call your methods correctly, with an instance, for example:
#!/usr/bin/python
class example():
def doMath(self, x, y):
z = x + y
z = self.square(z)
return z
def square(self, z):
z = z * z
return z
p = example()
print p.doMath(5,4)
outputs:
paul#local:~/src/python$ ./square.py
81
paul#local:~/src/python$
Clearly, in this particular case there's no advantage to these methods being in a class at all, and you could more easily do:
#!/usr/bin/python
def square(z):
return z * z
def doMath(x, y):
return square(x + y)
print doMath(5,4)
While we're at it... I've been calling these methods rather than functions... am I correct on that?
method -> routine that is a member of a class.
function -> routine that returns a result (compare with mathematical function)
procedure -> routine that does not return a result
member -> part of a class or struct (either a member variable or a member function etc)
Procedures are odd in python because even though a procedure does not return anything you can still assign its result to a variable.
The result in this case is None see here: Python procedure return values
If doMath and square are part of a class, they both should have another parameter called self. Methods calls take place on this self parameter. For example:
def doMath(self, x, y):
z = x + y
z = self.square(z)
return z
class example():
def doMath(self,x,y):
z = x + y
z = self.square(z)
return z
def square(self,z):
z = z * z
return z
def p(self):
print self.doMath(5,4)
e=example()
e.p()
def main():
x=2
def cool():
y=4
nonlocal x
print (x)
It is showing an error as --nonlocal x is a invalid syntax--.And if I dont declare it as nonlocal it says undefined x. So, how do i acess a variable which is in some other function ?Now how do i access x variable which is defined at main().
You can't.
You shouldn't. Doing so would just make it hard to read code because code from anywhere could read and modify your variables. By keeping access restricted to the one function it is easier to follow.
You do not. The variables local to a function only exist while that function is running; so once main has returned, its x does not exist. This also ties in to the fact that a separate call to the function gets a separate variable.
What you describe is a bit like reading the value of a static variable in C. The difference with static variables is that they're independent of the call; they still exist, and that makes most functions that use them non-reentrant. Sometimes this is emulated in Python by adding a default argument with a mutable value, with the same downsides.
In CPython, you actually can find out what the local variables of a pure Python function are by inspecting its code object, but their values will only exist in the call itself, normally on a call stack.
def func():
x=2
import dis
print func.__code__.co_varnames
dis.disassemble(func.__code__)
yields:
('x',)
2 0 LOAD_CONST 1 (2)
3 STORE_FAST 0 (x)
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
So x is actually local variable 0.
I would suggest looking up a debugger for details on call stack inspection.
Once you start needing attributes on a function, turn it into a functor:
class MainFactory(object):
def __call__(self):
self.x = 4
main = MainFactory() # Create the function-like object main
main() # call it
print main.x # inspect internal attributes
A functor in python is simply a normal object whose class implements the special __call__ method. It can have an __init__ method as well, in which you may pre-set the values of attributes if you wish. Then you can create different "flavours" of your functor by supplying different arguments when instantiating:
class MainFactory(object):
def __init__(self, parameter=1):
self.parameter = parameter
def __call__(self):
self.x = 4 * self.parameter
Now main = MainFactory(2); main() will have main.x set to 8.
Obviously, you can keep unimportant variables of the function inaccessible by simply using local variables instead of attributes of self:
def __call__(self):
# i and p are not accessible from outside, self.x is
for i in range(10):
p = i ** self.parameter
self.x += p
x = 0
def main():
global x
x = 2 # accesses global x
main()
print x # prints 2