Python 3: Checking if a function was called on by another function - python

In python 3, is there a way to check if another function executed a particular function? I want the computer to do something if a function was called by the itself and something else if another function called it. Here is an example:
def x():
y()
def y():
"""Psuedocode --->"""
if function y was called by function x:
print ("function y was called by another function")
elif function y was not called by function x:
print ("function y was called not called by another function")
Input ----> x()
Output ---> function y was called by another function
Input ---> y()
Output ---> function y was not called by another function

You can use the Python feature called "Inspect". It returns a list of frame records. The third element in each record is the caller name. Refer docs here: https://docs.python.org/3/library/inspect.html
import inspect
def x():
print inspect.stack()[1][3]
def y():
x()

Related

Can anybody explain about the closure of function in Python?

Python
Can anyone help me to understand this code, I am new to Python, how does this function work?
def makeInc(x):
def inc(y):
return y + x
return inc
incOne = makeInc(1)
incFive = makeInc(5)
print(incOne(5)) # returns 6
print(incFive(5)) # returns 10
Higher-order functions
Functions like makeInc that in turn, return another function are called higher order functions. Usually, functions are known to accept data as input and return data as output. With higher order functions, functions instead of data, either return code as output or accept code as input. This code is wrapped into a function. In Python, functions are first class citizens which means functions, just like data, can be passed around. For instance:
myvariable = print
Notice, how I have assigned print to myvariable and how I have dropped the parentheses after print Functions without parentheses are called function objects. This means myvariable now is just another name for print:
print("Hello World!")
myvariable("Hello World!")
Both of the above statements do the exact same thing. What can be assigned to variables can also be returned from functions:
def myfunction():
return print
myfunction()("Hello World!");
Now let's look at your example:
def makeInc(x):
def inc(y):
return y + x
return inc
makeInc is a function that accepts a parameter called x. It then defines another nested inner function called inc which takes in a parameter called y. The thing about nested functions is that they have access to the variables of the enclosing function as well. Here, inc is the inner function but it has access to x which is a variable of the enclosing outer scope.
The last statement return inc returns the inner function to the caller of makeInc. What makeInc essentially is doing, is creating a custom function based on the parameter it receives.
For instance:
x = makeInc(10)
makeInc will first accept 10 and then return a function that takes in an argument y and it increments y by 10.
Here, x is a function that takes in any argument y and then increments it by 10:
x(42) # Returns 52
nonlocal
However, there is a caveat when using nested functions:
def outer():
x = 10
def inner():
x = 20
inner()
print(x) # prints 10
Here, you would assume that the last print statement will print 20. But no! When you assign x = 20 in the inner function, it creates a new local variable called x which is initialized to 20. The outer x remains untouched. To modify the outer x, use the nonlocal keyword:
def outer():
x = 10
def inner():
nonlocal x = 20
inner()
print(x) # prints 20
If you are directly reading x inside inner() instead of assigning to it, you do not need nonlocal.
What is happening here is that makeInc() returns a function handle pointing to specific implementation of inc(). So, calling makeInc(5) "replaces" the x in inc(y) to 5 and returns the callable handle of that function. This handle is saved in incFive. You can now call the function as defined (inc(y)). Since you set x=5 before, the result will be y+5.

Nested function(Python 3)

a function (funcA) that takes a function (funcB) and returns a function that can be evaluated to produce the same value that funcB would produce (if given the same arguments) plus 1
returned_func(x) = funcB(x) + 1
What could be the possible way of doing this? I am confused with the second part of the question as to how can a function return a value and function at the same time. Any code example would be much appreciated! Thanks!
The concept you're looking for is, essentially, a function decorator. In Python, functions are first-class objects, just like class instances are in other languages. That means that you can pass them around, just like any other object. For example:
def foo(x):
return x + 1
print(foo) # <function foo at 0x0000024202F43EA0>
bar = foo
print(bar) # <function foo at 0x0000024202F43EA0>
Here we created a reference to the function object itself. We can, using the same idea, make a function which returns a function:
def foo(x):
def inner(y):
return x + y
return inner
func = foo(5)
print(func(3)) # 8
func is assigned to the return value of foo, which is itself a function that we can evaluate. You want to return a function A that adds 1 to the result of another function, B. So, pass B to a function make_A:
def make_A(b):
def inner(x):
return b(x) + 1
return inner
def B(x):
return x
A = make_A(B)
print(A(1)) # 2
Python has excellent syntactic sugar for this type of function. See this primer for more information.
def func1(x):
#operations go here:
return(x + 1)
def func2():
#operations go here:
return(x - 1)
if func1(2) == func2(4):
print("Hooray")
Does this help? It is a demonstration of how parameters and return values can interact.
A segment like func(1) implies the return value with the parameter as 1.

Python - passing a function as an argument to another function

I have two files;
The first file, myProgram.py, is a python file with a number of functions
one of the functions contained inside is myFunction
this function would be called with
import myProgram
myProgram.thisFunction()
myProgram.thatFunction()
The second file contains a menu system, with calls to the functions in myProgram.py
I'd like to call a particular function based on an argument passed to a function in file2
def file2_function(function):
myProgram.function
file2_function(thisFunction(x,y,z))
which would essentially create myProgram.thisfunction(x,y,z) and execute it.
I guess I could do this using a bunch of if/elif statements, say:
def file2_function(function):
if function == 1:
myProgram.thisFunction
elif function == 2:
myProgram.thatFunction
Though that could get messy as I'm already using a lot of if/elif/else statements for the menu system.
Is there a better way (or is the if/elif route the way to go?)
The *args in the function file2_function means the arguments to be passed to the function in which it calls:
def func1(a):
print a
def file2_function(function,*args):
function(*args)
file2_function(func1,4)
#4
You can create a dictionary where key is the name of the function, and value is the function itself. Short example:
functions = { 'add' : lambda x,y : x + y, 'mult': lambda x,y : x * y, 'div' : lambda x,y : x / y, 'sub' : lambda x,y : x - y }
functions['add'](1,2) # returns 3
#aga gave you a good hint. When I'm writing cli applications I usually do smth like:
def func1():
pass
def func2():
pass
def func3():
pass
def func_caller(name):
func_dict = {
'func1': func1,
'func2': func2,
'func3': func3
}
try:
func_dict[name]()
except KeyError:
print "no such func"
Alternatively you have getattr. See following snippet:
>>> import sys
>>> getattr(sys,'exc_info')
<built-in function exc_info>
>>> getattr(sys,'exc_info')()
(None, None, None)

How to bring variables into functions - Python

I am having an issue where I want to bring a variable into a function by name.
I have tried this so far:
x = 5
def func(y = x):
return y ** 2
>>>print func()
25
>>>x = 4
>>>print func()
25
However if I try to edit that input variable after I input the code the number the function detects the old input so it would still print 25 as oppose to the new input squared.
Is there a cleaner way to pull a variable into a function that actually works?
Default functions values are calculated during function creation time, so even if you change the value of x it is not going to be changed in the function.
From docs:
Default parameter values are evaluated when the function definition is
executed. This means that the expression is evaluated once, when the
function is defined, and that the same “pre-computed” value is used
for each call.
Read: Using mutable objects as default value can lead to unexpected results.
If you want to access a global value then simply do:
def func():
return x**2
Or better pass it explicitly:
def func(y):
return y**2
Another reason why not to use global variables inside function:
>>> x = 10
>>> def func():
... print x
... x = 5
...
>>> func()
Traceback (most recent call last):
func()
File "<ipython-input-5-ab38e6cadf6b>", line 2, in func
print x
UnboundLocalError: local variable 'x' referenced before assignment
Using classes:
class A:
x = 5
#staticmethod
def func():
return A.x**2
...
>>> A.func()
25
>>> A.x = 10
>>> A.func()
100
Just reference the global variable directly, instead of using it as the default value of an argument.
def func():
return x ** 2
The default value of y is set during function definition, not when running it. So default value for y is set to value of x on def line.
This should work:
def func(y=None):
if y is None:
y = x
return y ** 2
Generally in python Keyword Arguments are always assigned a value and you cant change that assigned value . So in your code
x=5
def func(y = x):
return y ** 2
print func()
x=4
print func()
For the keyword argument y the value of x i.e 5 is assigned and we cant change that value. So even if you change the value of x you will get the same output as 25
To solve this the function might directly access the global variable and return the value like the below code
x=5
def func():
return x ** 2
print func()
x=4
print func()
This is the correct way to do this
x=5
def foo():
global x
return x**2
Or you can simply do it like this
x=5
def foo():
return x**2
In this case the same global variable is referenced if it exists.

Assigning a function to a variable

Let's say I have a function
def x():
print(20)
Now I want to assign the function to a variable called y, so that if I use the y it calls the function x again. if i simply do the assignment y = x(), it returns None.
You simply don't call the function.
>>> def x():
>>> print(20)
>>> y = x
>>> y()
20
The brackets tell Python that you are calling the function, so when you put them there, it calls the function and assigns y the value returned by x (which in this case is None).
When you assign a function to a variable you don't use the () but simply the name of the function.
In your case given def x(): ..., and variable silly_var you would do something like this:
silly_var = x
and then you can call the function either with
x()
or
silly_var()
when you perform y=x() you are actually assigning y to the result of calling the function object x and the function has a return value of None. Function calls in python are performed using (). To assign x to y so you can call y just like you would x you assign the function object x to y like y=x and call the function using y()
The syntax
def x():
print(20)
is basically the same as x = lambda: print(20) (there are some differences under the hood, but for most pratical purposes, the results the same).
The syntax
def y(t):
return t**2
is basically the same as y= lambda t: t**2. When you define a function, you're creating a variable that has the function as its value. In the first example, you're setting x to be the function lambda: print(20). So x now refers to that function. x() is not the function, it's the call of the function. In python, functions are simply a type of variable, and can generally be used like any other variable. For example:
def power_function(power):
return lambda x : x**power
power_function(3)(2)
This returns 8. power_function is a function that returns a function as output. When it's called on 3, it returns a function that cubes the input, so when that function is called on the input 2, it returns 8. You could do cube = power_function(3), and now cube(2) would return 8.
lambda should be useful for this case.
For example,
create function y=x+1
y=lambda x:x+1
call the function
y(1)
then return 2.
I don't know what is the value/usefulness of renaming a function and call it with the new name. But using a string as function name, e.g. obtained from the command line, has some value/usefulness:
import sys
fun = eval(sys.argv[1])
fun()
In the present case, fun = x.
def x():
print(20)
return 10
y = x
y()
print(y)
gives the output
20
<function x at 0x7fc548cd3040>
so it does not actually assign the value returned by x() to the variable y.

Categories