Basic Python if statements - python

I'm learning Python and I'm trying to understand this line if I call f(-1):
x = 0
def f(x):
if x < 0:
return g(-x)
else:
return g(x)
def g(x):
return 2*x + 3
If I call f(-1) I get 5. But I incorrectly interpret that I would get 1. This is my interpretation process:
Since x=-1 it should return g(-x). There is no def g(-x) though. However if it returns def g(x) then we should get 2*x+3, which is 1?
Don't know where I misunderstand.
Thanks

Think of g as the function and x as input to the function.
Furthermore, x is also just like any other variable name.
This means I could instead rename the x variable in the g function to anything I want.
I could also call g anything I want.
Example:
def f(x):
if x < 0:
return grumpy_function(-x)
else:
return grumpy_function(x)
def grumpy_function(cool_value):
return 2*cool_value + 3
Now try to walk through the logic using these above functions...
f(-1) causes the if statement x<0 to be true.
So we will execute the line return grumpy_function(-x)
We know that x=-1, so this means -x = -(-1) = 1.
Therefore cool_value is actually 1 not -1.
Now go to grumpy_function: 2*1+3 = 5.

when call g(-x), in your case, it equals g(-(-1)), which is g(1)

When you specify def f(x) or def g(x), you're saying that, in the following context, x is going to be the name for the actual parameter of these two methods, regardless of the x=0 defined outside.
That being said, the following lines are equivalent:
f(-1)
g(1) # because if x < 0 is True
2 * 1 + 3
5
From your code, it is not exactly clear to me which of the xes you'd like to refer to the global x=0 and which of them should refer to the function's parameter, like -1 in your example. You should make this distinction yourself and name them differently, for example, x and y. As far as I know, if you name your function parameters the same as your global variables, you lose access to the global variables from within the function body (except for globals tricks).

Related

Are functions and helper functions treated differently in python?

Over here, the main function is g(x) and the helper function is h(). I noticed I can get the output for g(3), simply by binding x=3 and then doing any of the three
print(g(x))
g(x)
z=g(x)
But on the other hand, I noticed h() is outputted only when I type "print(h())". Are my observations correct or did I make a mistake? And also what is the logic behind this weird discrimination?
I like to think of it this way. Usually, if you had a line like "5" or "x=5", python doesn't give an output of 5. But functions have been given a special feature where they are invoked in any of the 3 ways. It's only that this special feature is being 'withdrawn' in the case of helper functions
The code you have written is equivalent to this:
def g(x):
def h():
any_name_you_want = 'abc'
return any_name_you_want
x += 1
print("in g(x)", x)
print(h())
return x
You cannot assign to a non-local variable inside a function. When Python creates the namespace for h, x is local to h because the assignment requires python to add the namespace for x at runtime.
Hence your code is also equivalent to :
def g(x):
def h():
return 'abc'
x += 1
print("in g(x)", x)
print(h())
return x
To get a sense of what is happening, run the following and then read up on UnboundLocalError:
def g(x):
def h():
x = x
return x
x += 1
print("in g(x)", x)
print(h())
return x

Python function argument can't be used as a variable in a child function

Here's the problem I try to solve:
I have a first function, to which I put in arguments. Then, later on, I have a second function, from which I want to call, as a variable, the said argument of the parent function. So it goes like:
def parent_function(argument=x):
if statement:
child_function()
else:
...
return result
def child_function():
x = x + 5
return x
If I run such a code, I get an error in the child function saying name 'x' is not defined.
However, if I fix my code to make x global in the parent function, like this:
def parent_function(argument=x):
global x
if statement:
child_function()
else:
...
return result
def child_function():
x = x + 5
return x
I get the error name 'x' is parameter and global
I need to import both functions in another file and I can't "dismantle" the child function inside the parent function.
Thanks very much for any help !
Don't use global Variables. Every function needs it's own arguments:
def parent_function(x):
if statement:
x = child_function(x)
else:
...
return result
def child_function(x):
x = x + 5
return x
name 'x' is parameter and global means you can't overwrite parameter x for being global also. To fix this, use another variable y, like this:
def parent_function(argument=x):
global y
y = x
if statement:
child_function()
else:
...
return result
def child_function():
y = y + 5
return y
This error happens because you are trying to overwrite a parameter in a function whose scope is local to that function by giving it a global scope. The problem is that variables defined in the context of a function are by definition local variables. To better illustrate this problem ,you can simply try to launch this piece of code:
def parent_function(argument="Hello"):
global argument
return argument
You will see that it will fail to run for the same reason that I have explained. I hope I have been clear in my explanation. Good luck.
The first thing you need to change is this:
def parent_function(argument=x):
If you search for how to make a default argument in a function you will get something like this: https://www.geeksforgeeks.org/default-arguments-in-python/
. This means instead of x you need to have some default value, for example:
def parent_function(argument=5):
This means that if you do not pass the argument called argument to the function value 5 will be passed.
On the other hand, it seems that you want x to be an argument, which means the def line should look like this:
def parent_function(x=5):
Second, global keyword needs to be used in the child_function since x has not been used in parent_function. This leads to this:
def parent_function(x=5):
if statement:
child_function()
else:
...
return result
def child_function():
global x
x = x + 5
return x
To have all this work, there must be at least two more lines one to set x and another to call parent_function, like this:
x = 6
parent_function(4)
But, to be even funnier, x from the arguments in parent_function and x used in child_function are not the same thing, and you can see for yourself in this example which is similar to your code, but fully executable:
def parent_function(x=5):
if True:
print(child_function())
else:
print("else branch")
return True
def child_function():
global x
x = x + 5
return x
x = 6
parent_function(4)
This prints out 11 even you might think it will print out 9!
This is due to fact that keyword global refers to the (as the word says) global variable declared outside of the functions, the variable with value 6. Usually, local and global variables should have different names, so either the argument x in parent_function or global x variable needs to be renamed.
IDK if this helps, but you will learn something from this, for sure!

How to change a variable inside a function scope after defining the function in Python?

I'm looking for a way to change the variables defined inside a function after defining the function.
For example
def GetNthPower(x) :
n = None
return x**n
my_numbers_list = [11,23,45,56,78,98]
# now if I feel like I need the 4th power of some numbers in the list
GetNthPower.n = 4
for x in my_numbers_list :
print GetNthPower(x)
# If I want 7th power then
GetNthPower.n = 7
This obviously will not work, is there any way to do this?
N.B: I know we can achieve this by setting 'n' as an argument of the function, but I want to do it this way for a particular reason.
I want my function to have only one argument (for using the function in multiprocessing.Pool.map()).
You can define static variables inside functions, almost like you did:
def GetNthPower(x) :
return x ** GetNthPower.n
GetNthPower.n = 3
print(GetNthPower(2)) #8
Make sure to initialize correctly your GetNthPower.n before first use though.
If you're worried about initialization, you could go for this version which uses a default value 1:
def GetNthPower(x) :
return x ** (GetNthPower.n if hasattr(GetNthPower, "n") else 1)
I think it would still be better for you to write a function that takes two arguments, or use the predefined ** operator.
Don't use one function; create a function that makes your function, using a closure.
def nth_power_maker(n):
def _(x):
return x ** n
return _
my_numbers_list = [11,23,45,56,78,98]
# now if I feel like I need the 4th power of some numbers in the list
get_4th_power = nth_power_maker(4)
for x in my_numbers_list:
print(get_4th_power(x))
get_7th_power = nth_power_maker(7)
Alternatively, you could use functools.partial to bind a keyword argument to a function
from functools import partial
def get_nth_power(x, n):
return x ** n
get_third = partial(get_nth_power, n=3)
get_third(4)
64
x = 4
# in a loop
for pow in [2, 4, 6, 8]:
f = partial(get_nth_power, n=pow)
f(x)

Local variable referenced before assignment error python

def outside(x=1):
def printHam():
x = x+1
print x
return printHam
myfunc = outside(7)
myfunc()
This doesn't works gives error Local variable referenced before assignment error python
However this works
def outside(x=1):
def printHam():
print x + 1
return printHam
myfunc = outside(7)
myfunc()
Because you are assigning x in the first case, python will assume x is a local variable (which is the default). In the second case you aren't assigning it so it will check the global scope.
If you want this example to work, you have to pass the outer x into the inner function like so:
def outside(x=1):
def printHam(x=x):
x = x+1
print x
return printHam
That being said, this seems like a horribly contrived use case, so there's probably a better solution for your actual use case. But I can't tell you what it is without knowing more about what you're trying to do.

Python why do my nested functions give a Nonetype error?

I'm new to programming.
def start():
x = 4
def addition():
n = 3
def exponential():
z = 2
def multiplication():
l = 2
print(x + n ** z * l)
return multiplication
equals = start()
equals()
why am I getting a "Nonetype" object is not callable error?
You're confusing a bunch of programming concepts:
Don't declare a function whenever you only need a statement
You're confusing function declaration with function call (invocation), and also the nesting is pointless. Declaring nested fn2 inside of fn1 doesn't magically also call fn2 and also transmit its return-value back to fn1. You still have to use an explicit return-statement from each fn.(If you forget that, you're implicitly returning None, which is almost surely not what you want)
For now, just don't ever nest functions at all.
Functions with no arguments are essentially useless, they can't take inputs and compute a result. Figure out what their arguments should be.
Specifically for the code you posted, addition(), multiplication() don't have any return value at all, i.e. None. exponential() returns multiplication, i.e. a function which only returns None. But then, both addition() and start() ignore that anyway, since they don't have a return-statement either, hence they implicitly return None.
Calling start() just gives you None, so you're just assigning equals = None. Not the result of some mathematical expression like you intended.
So:
reduce every unnecessary function to just a statement
declare each of your functions separately (non-nested)
each fn must have args (in this case at least two args, to make any sense)
each fn must have a return statement returning some value
only declaring a function and never calling it means it never gets run.
put an empty line in between function declarations (Then it's obvious if you forgot the return-statement)
Credits goes to #BrenBarn for being first to answer this. But I wanna post the code to make it more clear, and point out to some ways to make it better.
def start():
x = 4
def addition():
n = 3
def exponential():
z = 2
def multiplication():
l = 2
print (x + n ** z * l)
return multiplication()
return exponential()
return addition()
equals = start()
print equals #Output: 22
However, this is not the best way to list different methods. You should learn how to use a class in your python code.
I am going to define a class called "mathOperations". I will define three methods (functions): addition,exponential, multiplication. These functions are reusable.
class mathOperations():
def addition(self,x,y):
return x+y
def exponential(self,x,y):
return x**y
def multiplication(self,x,y):
return x*y
m= mathOperations()
z=2
l=2
x=4
n=3
result= m.addition(x,m.multiplication(m.exponential(n,z),l))
print result #Output:22
You should learn how to make your code reusable, try to google "procedural programming"; "Oriented Object Programming", or check "Learn Python the hard way" book. These are first and most used approach to make your code reusable. Think of it like a generic mathematical function to solve problems.

Categories

Resources