How are the values being determined in this basic Python class? - python-3.x

I am new to Python and to OOP concept. I was doing a EdX course and came across this code. I have modified it a little bit here. But I need to understand what exactly is happening here.
Question-1: Why does print(baba.x) give 7 but not 3?
Question-2: What does print(X) (capital X) do here? In getX and init I am using 'x' and not 'X'. So where does print(X) get its value from? It seems it is getting this value from the X=7 assignment. But isn't that assignment happening outside of the method getX and also outside of the class Weird. So why is getX able to access X=7 value?
I have searched on scope in Python, but was getting too complicated for me.
class Weird(object):
def __init__(lolo, x, y):
lolo.y = y
lolo.x = x
def getX(baba,x):
print (baba.x)
print (x)
print (X)
X = 7
Y = 8
w1 = Weird(X, Y)
print(w1.getX(3))
The output of the above code is:
7
3
7
None

Read What is the purpose of the word 'self', in Python?
class Weird(object):
def __init__(self, x, y):
self.y = y
self.x = x
def getX(self,x):
print (self.x) # this is the x value of this instance
print (x) # this is the x value you provide as parameter
print (X) # this might read the global X
X = 7
Y = 8
w1 = Weird(X, Y) # this sets w1.x to X (7) and w1.y to Y (8)
print(w1.getX(3)) # this provides 3 as local x param and does some printing

Related

how do I make a for loop understand that I want it to run i for all values inside x. x being a defined array

My code right now is as it follows:
from math import *
import matplotlib.pyplot as plt
import numpy as np
"""
TITLE
"""
def f(x,y):
for i in range(len(x)):
y.append(exp(-x[i]) - sin (pi*x[i]/2))
def ddxf(x,y2):
for i in range(len(x)):
y2.append(-exp(-x[i]) - (pi/2)*cos(pi*x[i]/2))
y = []
y2 = []
f(x, y)
x = np.linspace(0, 4, 100)
plt.title('Graph of function x')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.plot(x, y, 'g')
plt.grid(True)
plt.show()
x0 = float(input("Insert the approximate value of the first positive root: "))
intMax = 100
i = 0
epsilon = 1.e-7
while abs(f(x0,y)) > epsilon and i < intMax:
x1 = x0 - (f(x0))/(ddxf(x0))
x0 = x1
i += 1
print (i)
print (x1)
I get this error when running the program. it seems that (len(x)) cannot be used if x isnt a string. which doesn't make sense to me. if the array has a len and isn't infinite, why (len(x)) cant read his length? anyway, please help me. hope I made myself clear
Regarding the error: You are using x before defining it. In your code, you first use f(x, y) and only after that you actually define what x is (namely x = np.linspace(0, 4, 100)). You probably want to swap these two lines to fix the issue.
Regarding the question in the title: len(x) should be fine to get the length of a list. However, in Python you don't need to go through a list like that. You can instead use for element_name in list_name: This will essentially go through list_name element by element and make it available to you with the name element_name.
There is also something called list comprehensions in Python - you might want to take a look at those and see whether you can apply it to your code.

How to enact pass by reference in python as we do in C/C++?

x,y = 30,40
def swap(x,y):
x = x+y
y = x-y
x = x-y
print(x,y) #Here it swaps but as soon as function ends they go back to their previous values
swap(x,y)
print(x,y) #still prints x as 30 and y as 40
In C/C++ we used & operator to pass their addresses to make this change, how can we do the same thing in python considering python follows pass by object reference model?

How to understand this simultaneous assignment evaluation in python 3? [duplicate]

This question already has answers here:
Multiple assignment and evaluation order in Python
(11 answers)
Closed 3 years ago.
I have recently started learning python. I was playing around with simultaneous assignments today and came across some results that were produced by my code that I cannot understand.
x, y = 3, 5
x, y = y, (x+y)
print(y)
The output is 8.
I am not understanding why y = 8 instead of y = 10 despite x = y = 5 being evaluated first. Since y = 8, this tell us that x = 3 when y = x + y is being evaluated ? How is that possible if x = y is first evaluated, since it is evaluated left to right ?
I first debugged the code (which produced the same result), which I cannot understand. I also have tried looking at the python documentation, where it states "simultaneous overlaps within the collection of assigned-to variables occur left-to-right, sometimes resulting in confusion."
The example that it presents follows my logic:
x = [0, 1]
i = 0
i, x[i] = 1, 2
print(x)
It outputs 2.
(Evaluated left to right) Since i is updated to 1. Then, this updated i is used and hence, x[1] = 2 not x[0] = 2.
I really would appreciate some help.
I am not understanding why y = 8 instead of y = 10 despite x = y = 5 being evaluated first
The right side of an assignment is evaluated first.
In your assignment with x = 3 and y = 5
x, y = y, (x+y)
the right side is evaluated to a tuple (5, 8) first and then assigned to the values on the left side. Therefore y is 8.
You could also think of it as
x, y = 3, 5
temp = y, x + y
x, y = temp
To see what really happens internal, you can disassemble your code:
>>> import dis
>>> def f(x, y):
... x, y = y, x + y
...
>>> dis.dis(f)
Outputs
2 0 LOAD_FAST 1 (y)
2 LOAD_FAST 0 (x)
4 LOAD_FAST 1 (y)
6 BINARY_ADD
8 ROT_TWO
10 STORE_FAST 0 (x)
12 STORE_FAST 1 (y)
14 LOAD_CONST 0 (None)
16 RETURN_VALUE
As you can see, the addition is performed before the assignment.
Python goes right-to-left, left-to-right. You can imagine that python pushes its operations to a stack-like data structure.
Looking at the first assignment: x, y = 3, 5
python will first push the right-hand side value onto the stack as a tuple.
run an unpacking-sequence for n values from the stack, and puts the values back onto the stack right-to-left. "push 5 to the stack, then 3". Current stack = [3, 5]
Finished with the right-hand side, python will assign values to the left-hand side left-to-right, while removing top-of-stack. So it will first tak 3 and store it in variable x, then 5 and store it in variable y.
You can inspect the operations python does in byte code using the dis module.
The following assignments:
x, y = 3, 5
x, y = y, (x + y)
Produce the following operations:
You can inspect the bytecode operations here: http://pyspanishdoc.sourceforge.net/lib/bytecodes.html

Accessing global variable in function in python

I have two pieces of code:
def g(y):
print(x)
x = 5
g(x)
and
def h(y):
x = x + 1
x = 5
h(x)
The first piece of code works perfectly fine printing '5' while the second piece returns:
UnboundLocalError: local variable 'x' referenced before assignment
What does this actually mean? Is it trying to say that it tried to evaluate the line x = x + 1 before it evaluates the line x=5? If that is so, why has the first piece of code not generated any error? It similarly had to evaluate the line print(x) before x was assigned a value.
I think I might have an misunderstanding how functions are called. But I do not know what it is that I got wrong.
# first block: read of global variable.
def g(y):
print(x)
x = 5
g(x)
# second block: create new variable `x` (not global) and trying to assign new value to it based on on this new var that is not yet initialized.
def h(y):
x = x + 1
x = 5
h(x)
If you want to use global you need to specify that explicitly with global keyword:
def h(y):
global x
x = x + 1
x = 5
h(x)
Just as Aiven said, or you can modify the code like this:
def h(y):
x = 9
x = x + 1
print(x) #local x
x = 5
h(x)
print(x) #global x

How to handle a varying number of parameters on a function?

I'm trying to construct a code that gives a square's area and a rectangle's area with the same function, but I'm either running into missing positional argument error or something more exotic with whatever I do and I was flabbergasted by the potential solutions out there as I'm only a very basic level of python coder.
The biggest question is what kind of format should area() function be in order for me to be able to have it assume y is None if it's not given.
def area(x, y):
return x * x if y is None else x * y #Calculate area for square and rectangle
def main():
print("Square's area is {:.1f}".format(area(3))) #Square
print("Rectangle's area is {:.1f}".format(area(4, 3))) #Rectangle
main()
Do it like so:
def area(x, y=None):
return x * x if y is None else x * y #Calculate area for square and rectangle
By giving a default value, you may pass 1 less argument and it will be set to the default.

Resources