I have defined two functions(fun1 and fun2), which return some values and I call one of these functions in fun3. I can do if condition inside for loop but is there a way that the function can be chosen before. As shown here. Or is there any other approach?
def fun1(a1,b1)
def fun2(a1,b1)
def fun3(a1,b1,some_para):
if some_para:
sel_func = fun1()
else:
sel_func = fun2()
for Loop:
sel_func(a1,b1)
Functions are objects. Just assign the function instead of calling it. Using your example:
def fun3(a1, b1, some_para):
sel_func = fun1 if some_para else fun2
for Loop:
sel_func(a1, b1)
def fun1(a1,b1)
def fun2(a1,b1)
def fun3(a1,b1,some_para = None):
sel_func = fun1 if some_para else fun2
for Loop:
sel_func(a1,b1)
use some_para =None in function declaration, when you call this function you always need to pass the argument to it and only fun1 will run every time if you don't pass any value an attribute error will occur. if none uses and no value passed fun2 will execute else fun1 will.
You can pass the function as a parameter outside so it is easier to read:
def fun3(a1, b1, sel_func):
for Loop:
sel_func(a1, b1)
# call fun3 with whatever funtion you need in each momment
fun3(a, b, fun1)
fun3(a, b, fun2)
Related
When I call func1 from func2, I get an error. Why is this occurring and how to access the returned dictionary d in func1 from func2?
func1()
NameError: name 'func1' is not defined
class ABC():
def func1(self, a):
d = {}
###do something with a
###return ending dictionary d
return d
def func2(self):
###Retrieve returned dictionary d from func1 and use
func1()
d['key'] = value
func1 and func2 are instance methods of ABC objects. You need to call them from the instance of such object.
In your case, one such instance is self, first parameter of both functions.
Thus, self.func1() will work.
Use self.func1() to call the function inside your class.
I want to use one of the attributes returned by a function in a python script (x) into a python script (y)
The communication between both scripts works well; I can get functions and attributes, but doesn't allow me to attributes returned by a function.
Here is how I worked:
x.py
def func():
b = 10
a = 15
return [a,b]
c = 20
y.py
from x import func
import x
print (x.c)
print (func.b)
I get the "c" value and the following error AttributeError: 'function' object has no attribute 'b'
I have tried also to print x.b, and I've got AttributeError: module 'WorkingLSTM' has no attribute 'b'
Thanks in advance
The way to call func is by using func(), which would give you [a,b].
example:
funcResult = func()
a = funcResult[0]
b = funcResult[1]
funcResults is the return value from func(), that is the list [a,b].
That's not allowed, you have to call the function to get the value from the functions returned list.
a, b = func()
print(b)
# or just...
print(func()[1])
PS: It's "not allowed" because it doesn't make sense in any way; when there is no function call, there is not variable b at all. You might take a look at classes, they can hold static variables.
you cannot access local variables of a function.
these variables exist only during the the time where func is executed and are destroyed afterwards.
You can of course call the function and look at the result, but the result is just a list with two values
rslt = func()
print("A = ", rslt[0])
print("B = ", rslt[1])
The variable was declared inside a function making it a local variable and as such it can"t be accessed outside the function.
The variable is declared outside of the function making it a global variable and is not in anyway tied to your function.
The concept of attributes relates to Classes and you are dealing with a function so you might have to treat it as a class object.
If you are concerned bout accessing the local variables, you might as well do this:
y.py
from x import *
d = func() # func returns a list which is now
# identified/referenced by variable d
# displays the elements in the list using index position
print(d[0])
print(d[1])
If you want to use attributes, you may create a callable class instead of function:
class Func:
def __init__(self):
self.b = 10
self.a = 15
def __call__():
return [self.a, self.b]
func = Func()
Python has the concept of the scope. Local variables have no effect outside the function.
If you want to use it, use class and self or make getter function(but it's not Pythonic).
x.py
class X:
def __init__(self):
self.b = 10
self.a = 15
self.c = 20
def func(self):
return [self.a, self.b]
y.py
from x import X
x = X()
print(x.c)
print(x.func()[1])
I'm learning about inner and outer functions, for example:
def outer_function(msg):
def inner_function():
print(msg)
return inner_function
hi_func = outer_function("hi")
hi_func()
I'm just curious if there is any way to use the inner function inside of the outer function, without returning the inner function, or does it have to be returned to be used?
any way to use the inner function inside of the outer function, without returning the inner function
Sure. You can just call the inner function.
One reason you might want to do this is to encapsulate part of the logic in a function that doesn't need to be used anywhere else. So you would just create it within the function:
def foo(n):
def generate_rand_num(x):
import random
# ... add more logic here to come up with this random num
return random.randint(0, x)
a = generate_rand_num(n)
b = generate_rand_num(n)
c = generate_rand_num(n)
return (a+b+c) < n
print foo(123)
Sorry for the title, I hope it reflects correctly my problem :
In the following code, I was expecting the result to be result 0 1 2 but instead I have 2 2 2. The code inside my_function seems to be interpreted with the last instance of obj. What is wrong ?
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
a_list = []
for index in range(3):
obj = Example(index)
def my_function(x):
#some stuff with x like obj.another_function(x)
return obj.get()
a_list.append(my_function)
for c in a_list:
print(c())
When you define this
def my_function():
return obj.get()
Python will understand that my_function should run the get() method of an object called obj and return the value. It won't know the value of obj and what the get() method does until you attempt to call it.
So, you are actually defining three different functions that will eventually do the same thing. And, in the end, running the same code thrice.
But why is the return 2 2 2?
Because after the last iteration, the value of obj is Example(2)* because you redefine its value at every iteration, and the last one remains.
*
because of this line obj = Example(index)
Understanding a few things about how python works will help you understand what's happening here. Here obj is a closure, closures are evaluated at call time, not when the function is defined so if I do this:
x = "hello"
def printX():
print x
x = "goodbye"
printX() # goodbye
I get "goodbye" because printX is referencing a global variable in my module, which changes after I create printX.
What you want to do is create a function with a closure that references a specific object. The functional way to do this is to create a function that returns another function:
x = "hello"
def makePrintX(a):
def printX():
# We print a, the object passed to `makePrintX`
print a
return printX
# x is evaluated here when it is still "hello"
myPrintX = makePrintX(x)
x = "goodbye"
myPrintX() # "hello"
If you're having trouble understanding the above example I would recommend reading up on python's scoping rules. For your example, you could do something like this:
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
def makeObjFunction(obj):
def objFunction(x):
return obj.get()
return objFunction
a_list = []
for index in range(3):
obj = Example(index)
my_function = makeObjFunction(obj)
a_list.append(my_function)
for c in a_list:
print(c("some value"))
You are appending three my_functions to the a_list which are all closures over the same Example object. Try:
def my_function():
return obj
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
You can see they have the same id so calling get() on each should give the same answer.
If you just append the obj.get function (and drop the my_function) it'll work fine.
a_list.append(obj.get)
....
0
1
2
Edit: You've updated your question so to let you do more stuff in my_function(). It's still basically a scoping problem.
def my_func_factory(p_obj):
def my_function(x):
#some stuff with x like obj.another_function(x)
return p_obj.get()
return my_function
for index in range(3):
obj = Example(index)
a_list.append(my_func_factory(obj))
Since my_function can't see obj being reassigned, each instance doesn't pick up the change.
I think append() during the for just append the function address in a_list[]. After for iteration, the a_list is really given the number. Then it discovers the address of my_function, and they get the number in my_function, this is, 2. That's why you get [2,2,2].
Or maybe, in my_function, function give the method of "obj". But for iteration change the "obj" memory address each time, so the symbol "obj" always aim to the newest object Example. Due to my_function always get "obj", you get the same number from the last object.
There's something I don't understand here when it comes to returning variables. For the sake of simplicity, I wrote a really basic thing to sum up the problem I'm having:
def apples():
dingo = 2
return dingo
def bananas(dingo):
print(dingo)
def main():
apples()
bananas(dingo)
main()
So I create 'dingo' in the 'apples' function. I return it. I use it as a parameter in 'bananas'. I call them both in main, so why do I get the error that 'dingo' is undefined? Also, something I'm unable to do is put dingo = apples() inside the bananas function. I can't unpack it within the bananas function because I want to call them both in main individually. Is there any way to get around this without unpacking?
You get that error because you didn't assign the return value of apples() to anything, especially not a variable named dingo in the scope of main(). This would work:
def apples():
dingo = 2
return dingo
def bananas(dingo):
print(dingo)
def main():
result = apples()
bananas(result)
main()
Notice how I named the variable result - it doesn't have to be named the same as the argument of the bananas() function - it just has to be passed in with the name you assigned it to.
def bananas(dingo) basically means: Create a function called bananas that takes exactly one argument. Inside bananas(), refer to that argument as dingo.
So whatever that argument is called in the scope where you call bananas() is irrelevant.
Same for apples: You create a variable dingo, assign it the value 2 and return it - what's actually returned is just the value (2), it's up to you to assign that result to variable that may or may not be called the same.
what you've returned should be assigned to some variable, otherwise the return value gonna be lost.
I'm curious didn't you get NameError: global name 'dingo' is not defined with your sample code?
In [38]: def apples():
...: dingo = 2
...: return dingo
...:
...: def bananas(dingo):
...: print(dingo)
...:
...: def main():
...: dingo=apples()
...: bananas(dingo)
...:
...: main()
2
def apples():
dingo = 2
return dingo
def bananas(dingo):
print(dingo)
def main():
apples()
bananas(dingo)
main()
The variable dingo is a local variable for the function definition apples() and its scope(lifetime) ends as soon as the function call is done with.That means the variable name dingo doesn't hold any meaning as soon as the function is over.
apples() will return dingono doubt but the function bananas() knows nothing about dingo and neither does main() since dingo is a local variable and confined to apples()
For example:
def ret_val():
var=5
return var
main()
x=ret_val
print x
Output:
5
the return statement only returns the value in the variable and not the variable by name.
so you should replace code by the following:
def apples():
dingo = 2
return dingo
def bananas(dingo):
print(dingo)
def main():
x=apples()#here x will store the value of dingo i.e 2
bananas(x)#the value of x will be passed
main()
Whenever you return something the return statement terminates the function irrespective of the place where it is in the code of the function(i.e. the last statement or in the middle)
def check(x):
if (x % 2==0):
return "even"
return "odd"
Once the control goes to return statement then the function ends and the other return statement is not executed.Hence the return is like a break statement for functions which also gives back a value to the calling function.
Just to clarify, there is nothing special about variables names between scopes:
The code given in the accepted answer is the same as this:
def apples():
dingo = 2
return dingo
def bananas(another_name):
print(another_name)
def main():
result = apples()
bananas(result)
main()
What you call the parameter to bananas is irrelevant.
In your main function definition change the code to look like the following
def main():
bananas(apples())
This way you avoid any temporary assignment of the return values