I was trying to make variables inside a loop. i.e. I pass a pattern of variables, and the pattern of their values and the variables are accordingly created and stored in a text file.
But, I tried something off topic and did this:
a = lambda a: a
for i in ["a", "b"]:
b = eval(i)(a)
print(i)
the output was:
a
b
Can anyone please explain what has happened here?
Edit:
I have analysed its answer.
I will paste it below.
Please verify if it is correct.
Thank you!
Lets first break the problem in parts.
def a(n):
return n
b = eval("a")(a)
print("a")
b = eval("b")(a)
print("b")
We can clearly see that the output is due to the two print statements.
print("a")
print("b")
Thus the rest of the statements play no part in the output.
def a(n):
return n
b = eval("a")(a)
b = eval("b")(a)
These statements can simply be put across like this:
def a(n):
return n
b = a(a)
b = b(a)
The statement
b = a(a)
makes the same effect as
def b(n):
return n
Thus the entire code can be put across like this:
def a(n):
return n
def b(n):
return n
print("a")
print("b")
Thus there is no ambiguity in this question now.
Here's how you can deconstruct your loop to understand for yourself, and please don't do that as pointed out in the comment.
a = lambda a: a
# First iteration
i = "a"
b = eval(i)(a)
print(i) # a
# Second iteration
i = "b"
b = eval(i)(a) # eval("b") is now <function __main__.<lambda>(a)>
print(i) # b
You are printing the variable i (which takes the values "a" and "b" since you loop over ["a", "b"]). If you want to see which values the variable b takes, print b instead:
a = lambda a: a
for i in ["a", "b"]:
b = eval(i)(a)
print(b)
Lets first break the problem in parts.
def a(n):
return n
b = eval("a")(a)
print("a")
b = eval("b")(a)
print("b")
We can clearly see that the output is due to the two print statements.
print("a")
print("b")
Thus the rest of the statements play no part in the output.
def a(n):
return n
b = eval("a")(a)
b = eval("b")(a)
These statements can simply be put across like this:
def a(n):
return n
b = a(a)
b = b(a)
The statement
b = a(a)
makes the same effect as
def b(n):
return n
Thus the entire code can be put across like this:
def a(n):
return n
def b(n):
return n
print("a")
print("b")
Thus there is no ambiguity in this question now.
Related
I know there are similar questions about passing functions into functions, but I'm not clear on the effective solution for my particular problem.
The following function works but the formula is static. It only works on a fixed function, namely (in mathy pseudocode) f(a) = 3^a mod 17 = b where f(11) = 7
def get_a(b):
'''
Get preimage a from A for f(a) = b where b in B
'''
a = 1
while(1):
x = pow(3, a) % 17
if x == b:
return a
if a > 10000:
return -1
a += 1
def main():
b = 7
a = get_a(7)
print(F'The preimage a of b={b} is: {a}')
if __name__ == '__main__':
main()
I want to make a user pass in any given function. To start with, I implemented something just a little more complex but still pretty simple.
def get_a_variable(b, base, mod):
'''
Get preimage a from A for f(a) = b where b in B
'''
a = 1
while(1):
# print(F'a:{a}, b{b}')
x = pow(base, a) % mod
# print(F'x:{x}')
if x == b:
return a
if a > 10000:
return -1
a += 1
def main():
b = 7
a = get_a(7)
print(F'The preimage a of b={b} is: {a}')
a = get_a_variable(7,3,17)
print(F'Again, the preimage a of b={b} is: {a}')
This works but I want to make it even more dynamic.
To try implement this, I created a new function that can be passed as an argument:
def power_mod_function(base, x, mod):
return power(base, x) % mod
I'm not exactly sure how the trial value arg x should be handled or if it should even be in this function.
Then I "forked" the "get_a(b)" function that takes a callback I believe
def get_a_dynamic(b, crypt_func):
'''
Get preimage a from A for f(a) = b where b in B
'''
a = 1
while(1):
x = crypt_func() # Not sure how to manage the arg passing here
if x == b:
return a
if a > 10000:
return -1
a += 1
Then I updated main():
def main():
b = 7
a = get_a(7)
print(F'The preimage a of b={b} is: {a}')
a = get_a_dynamic(b, power_mod_function(3, x, 17)) # Not sure how to pass my middle arg!!
print(F'Again the preimage a of b={b} is: {a}')
I'm getting the following error messages:
python pre_img_finder.py
The preimage a of b=7 is: 11
Traceback (most recent call last):
File "pre_img_finder.py", line 45, in <module>
main()
File "pre_img_finder.py", line 41, in main
a = get_a_dynamic(b, power_mod_function(3, x, 17))
NameError: name 'x' is not defined
I don't know how to set it up right and do the variable passing so that I can pass the static variables once in main and the middle test variable x will always increment and eventually find the results I want.
Perhaps I just need to receive a function that begins with a "type" argument that acts as a kind of switch, and then takes a variable number of arguments depending on the type. For example, we could call the above a base-power-mod function or (bpm), where "power" is the answer we're looking for, i.e. a is the pre-image of b in technical terms. Then just call
main():
a = get_a_dynamic(7, ("bpm", 3,17))
And then implement it that way?
Thanks for your help!
Use *args to pass additional arbitrary number of arguments to the function.
def get_a_dynamic(b, crypt_func, *args):
'''
Get preimage a from A for f(a) = b where b in B
'''
a = 1
while(1):
x = crypt_func(*args)
if x == b:
return a
if a > 10000:
return -1
a += 1
Then call it in your main like this
def main():
b = 7
a = get_a(7)
print(F'The preimage a of b={b} is: {a}')
a = get_a_dynamic(b, power_mod_function, 3, x, 17)
print(F'Again the preimage a of b={b} is: {a}')
The way to generate dynamic functions with partial defined arguments is... functools.partial
from functools import partial
def get_a_variable_with_func(b, func):
'''
Get preimage a from A for f(a) = b where b in B
'''
a = 1
while(1):
x = func(a)
if x == b:
return a
if a > 10000:
return -1
a += 1
b = 7
def power_mod_function(base, mod, x):
return (base ** x) % mod
partial_func = partial(power_mod_function, 3, 17)
a = get_a_variable_with_func(7, partial_func)
print(a)
>>>
11
By the way, this is more pythonic:
from functools import partial
def get_a_variable_with_func(b, func):
'''
Get preimage a from A for f(a) = b where b in B
'''
for a in range(10001):
if func(a) == b:
return a
return -1
def power_mod_function(base, mod, x):
return (base ** x) % mod
a = get_a_variable_with_func(7, partial(power_mod_function, 3, 17))
print(a)
When you do this :
a = get_a_dynamic(b, power_mod_function(3, x, 17))
you don't pass power_mod_function to get_a_dynamic, you pass its result
instead. To pass the function you just have to pass the function name.
Therefore, because the function needs a value internal to get_a_dynamic (the x arg) and also two external arguments (3 and 17), you must pass these two arguments to get_a_dynamic separately for it to be able to call the passed function with the three needed arguments.
For that purpose, the suggestion of AnkurSaxena could be used especially if if the number of args can vary. But you can also declare it like this :
def get_a_dynamic(b, crypt_func, pow, mod):
then use it like this :
a = get_a_dynamic(b, power_mod_function, 3, 17))
You do something like:
def get_a_dynamic(b, function, argtuple):
# …
x = function(*argtuple) # star-operator unpacks a sequence
# … et cetera
… in essence. You can then always check the range of argtuple when passing it around, or be scrupulous about your calling conventions – but that star-operator unpack bit is the crux of what you are looking for, I think.
If you want to pass the name of the function as a string (as per your example) you can do something like:
function = globals()["bpm"] # insert your passed string argument therein
… but that’s kind of sketchy and I don’t recommend it – better in that case to pre-populate a dictionary mapping function string names to the functions themselves.
Is it possible to make a two functions with seperate for-loops but that the second function gets what the first one did? I have a very simple example:
a = [1,2,3,4]
def func():
for i in a:
if i == 1:
continue
def func2():
func()
for i in a:
print(i)
print(func2())
The problem with the second function is that it doesnt "get" what the first function does. How could I fix this? I want the second function to get the first one so that I can continue on with statements.
To pass information from one function to another, the first function needs to return it.
def func(a):
r = []
for i in a:
if i == 1:
continue
r.append(i)
return r
def func2(a):
r = func(a)
for i in r:
print(i)
func2([1, 2, 3, 4])
In this example test_function1 has 4 varibles that need to be used in test_funtion2.I would not like using global variables becouse the actual code i'm writing is more complex and it would break it.
def test_function1():
a = input("Type aaa:")
b = "bbb"
c = "ccc"
d = "ddd"
test_funtion1()
def test_function2():
if a == "aaa"
print(b)
print(c)
print(d)
test_function2()
I have a solution, but I am not sure if it is good or not.Could you tell me if this would work or if there is any other alternative.Thanks!
Sorry for my grammar , english is not my main language.
def test_function1():
a = input("Type aaa:")
b = "bbb"
c = "ccc"
d = "ddd"
return (a, b, c, d)
def test_function2():
if (test_funtion1()[0]) == "aaa"
print(test_funtion1()[1])
print(test_funtion1()[2])
print(test_funtion1()[3])
I think what you're looking for are classes.
a, b,c, d is your state, and an instantiation of such a class forms a state, which is basically the values referenced by these 4. Your first function is the "constructor" (called __init__) and the second function is then able to access these "instance variables".
I edited the solution that best fits me:
def test_function1():
a = input("Type aaa:")
b = "bbb"
c = "ccc"
d = "ddd"
return a, b, c, d
def test_function2():
x = test_function1()
if x[0] == "aaa":
print(x[1])
print(x[2])
print(x[3])
test_funtion2()
Passing arguments to functions and returning values from functions is indeed the first and most obvious way to avoid global state - but wrt/ to your snippet, you should avoid calling test_function1 four times, which is done by keeping the result in a local variable:
def test_function2():
result = test_funtion1()
if result[0] == "aaa"
print(result[1])
print(result[2])
print(result[3])
or in this specific case (when the function returns a tuple or ny sequence of known length) you could use tuple unpacking:
def test_function2():
a, b, c, d = test_funtion1()
if a == "aaa"
print(b)
print(c)
print(d)
Also, if you have a set of functions working on the same set of (related) variables, you may want to have a look at classes and objects.
You can also use this
def test_function1():
a = input("Type aaa:")
b = "bbb"
c = "ccc"
d = "ddd"
t = a, b, c, d
return t
def test_function2():
x = test_function1()
if x[0] == "aaa":
print(x[1])
print(x[2])
print(x[3])
test_function2()
This question already has answers here:
Alternatives for returning multiple values from a Python function [closed]
(14 answers)
Closed 9 months ago.
When I try to call a, b in function add, I get a is not defined even though I am returning the values. How do I make it return both a and b?
def numbers():
a= input ("a:")
a = int(a)
b= input ("b:")
b = int(b)
return a
return b
def add():
numbers()
print (a)
print (b)
add()
A return statement almost always causes a function to immediately terminate, and no other statement in the function will run. So once you return a, you'll never get to return b. You need to return both of them at the same time.
Additionally, returning a value from a function will not automatically put those names into the scope that called the function. You need to manually assign the values to something.
def numbers():
a= input ("a:")
a = int(a)
b= input ("b:")
b = int(b)
return a,b
def add():
a,b = numbers()
print (a)
print (b)
add()
I think so:
def numbers():
a= input ("a:")
a = int(a)
b= input ("b:")
b = int(b)
return a, b
def add(a, b):
print (a)
print (b)
return a, b
def main():
another_a, another_b = numbers()
another_a, another_b = add(another_a, another_b)
main()
def main():
a == 3
b = a + 1
c = b + 1
print(a)
if (a<0):
print(a<0)
print(c)
else:
print('a is not less than 0')
print(a)
I watched the khan academy video #1 on Python programming and tried to duplicate it but it kept on giving the error above.
Thanks for your help
I am a first time python user
You are not assigning to a; you are instead testing for equality with a double ==:
a == 3
Since you didn't assign anything to a yet to compare with 3, that results in a NameError.
Remove one = sign to assign instead:
a = 3
This all assumes that the rest of your code is indented correctly to match the rest of your function:
def main():
a = 3
b = a + 1
c = b + 1
print(a)
if (a<0):
print(a<0)
print(c)
else:
print('a is not less than 0')
print(a)
== is used for comparison tests. You need to use = for variable assignment:
a = 3
Also, as your code currently stands, the stuff outside of main will not be able to access a because it is local to the function. Hence, you need to indent it one level:
def main():
a = 3
b = a + 1
c = b + 1
print(a)
if (a<0):
print(a<0)
print(c)
else:
print('a is not less than 0')
print(a)
main()
I think you want the following code:
def main():
a = 3
b = a + 1
c = b + 1
print(a)
if (a<0):
print(a<0)
print(c)
else:
print('a is not less than 0')
print(a)
main()
You want the if statements to be inside the function that you're making, in this case main(). Otherwise, 'a' will not be defined because it is inside the function main(). Welcome to python, and to stack overflow!