Python - Name is not defined in a function variable? - python

I seem to be somehow screwing up the most basic thing. I have:
def function(a, b, c):
return 'hi'
print(function(a,b,c)) results in a NameError for every variable.
What is the cause of this?

The names of the arguments of a function are local variables, they are not available as global names. a, b and c exist only inside of the function, and receive the values you pass to the function.
You need to create new variables or use literal values when calling the function:
print(function(1, 2, 3))
would work because 1, 2 and 3 are actual values to pass into the function.

Related

Using a lambda function in python

Is there a way to convert a function to a lambda function (automatically) in python? Something like:
def func(arg):
print("Hi", arg)
==>
lambda arg: compile(func) # <== something like this
Functions in Python are first-class citizens of the language. This means that a function can be manipulated as if it was a data value. Thus, a function can be passed to another function as an argument, or returned from a function as a result. This is referred to as higher-order programming.
Now, both the def and the lambda keywords define such function values. The main difference is that def assigns a name to such a function, whereas lambdas are anonymous functions. Another difference is that lambdas are limited to one line of code (although there are languages where this is not the case).
For example, here are two equivalent functions, one defined with def, the other with lambda:
def say_hello(name):
print('Hi ', name)
lambda name: print('Hi ', name)
Another way to interpret the def keyword is as follows:
say_hello = lambda name: print('Hi ', name)
Although such code is highly discouraged.
In essence, both of these two functions are (nearly) equivalent data values, but in the snippet above, the one defined with def could later be called, since it has a name and we can therefore later access it. The one defined by lambda cannot, since it does not have a name, and is thus immediately lost if not assigned to a variable or passed to another function, say f, as an argument, where it is then given a name in f's local scope as per the f's parameters.
However, lambdas are useful in cases where we do not want to clutter up our scope with new, short functions that are only passed to another function as an argument:
map(lambda x: x * 2, [1, 2, 3])
# >>> [2, 4, 6]
If you already have a function defined with def that does the multiplication shown above, as would be the case in your example, e.g.:
def double(x):
return x * 2
Then you can simply refer to this function by name in the call to map:
map(double, [1, 2, 3])
# >>> [2, 4, 6]
In short: There is no need to "compile a function to a lambda", a lambda is just a special case of a function which is not given a name. Refer to your function by name instead.
P.S.: Don't use map and filter, use list comprehensions instead, as they are considered more pythonic.
You can make yours easily:
def auto_lam(f):
return lambda *args, **kwargs: f(*args, **kwargs)
Then to use it:
mylam = auto_lam(func)
In this form, you can see that this is quite useless because you are simply calling the same function, but wrapping functions is something that is very common in python because it allows us to modify the behaviour of the function. These are called decorator functions.
For example:
def logging_func(f):
def do_work(*args, **kwargs):
print ("You called me")
res = f(*args, **kwargs)
print ("Finished")
return res
return do_work
Now you can wrap your existing function with this one like so:
#logging_func
def func(arg):
print("Hi", arg)
Now every time you call func, it will log something before and after. I argue this is a better use of function wrappers than one that simply gives you back the same function.

Python: Return possibly not returning value

Hello Stack Overflow Community,
I am trying to write a program that checks Fermat's Last Theorem. The issue I am running into is that an error appears saying "NameError: name 'a' is not defined. However, I define 'a' in my first function and return its value at the end of the function.
I am trying to use the inputed values from the first function in the second function so the user can define the parameters.
Am I misunderstanding how to leverage "Return"? All help is greatly appreciate and will keep me sane.
def input_fermat():
a=input('Enter the first variable \'a\': \n')
b=input('Enter the second variable \'b\': \n')
c=input('Enter the third variable \'c\': \n')
n=input('Enter the exponential variable \'n\': \n')
return a, b, c, n
def check_fermat(a,b,c,n):
calc_1=a**n
calc_2=b**n
calc_3=c**n
if n>2 and int(calc_1) + int(calc_2) == calc_3:
print('Holy smokes, Fermat was wrong!')
else:
print('No that doesn\'t work.')
input_fermat()
check_fermat(a,b,c,n)
The variables a, b, c, n defined in input_fermat only exists within the function, that's why you return them, but when you call the function you aren't saving them anywhere. You should replace:
input_fermat()
By:
a, b, c, n = input_fermat()
Or you can directly pass the return value of input_fermat to check_fermat like this:
check_fermat(*input_fermat())
You are not storing the values that the function input_fermat returns. Try:
a, b, c, n = input_fermat()
check_fermat(a,b,c,n)
This is happening because those variables are defined locally and are not available in check_fermat's namespace.
Refer to the LEGB-rule.
What you can do is define all of those variables using the global keyword in the function definition, although this isn't usually the best approach. You'll also want to cast all of your inputs to ints since input() will return a string.
Returned values don't just automatically show up in your namespace, you have to assign them to something.
a, b, c, n = input_fermat()
Variables a,b,c and n, which you receive as input in input_fermat(), are only available within the body of that function; once you return, you're out of input_fermat()'s scope and the values in a,b,c and n are handed off to whatever variables you called input_fermat() to assign .
A function's scope means the only variables available in any given function are
those that are declared in the body of the function
those passed to the function as arguments in parentheses.
variables declared globally
In check_fermat(),this means you could re-use variables a,b,c and for something other than the input, if you wanted (because a new function means a new scope).
But, in the code shown below, we decide that a,b,c and n in check_fermat() are going to be the same thing as a,b,c and d in input_fermat() with the declaration a,b,c,n = input_fermat(). This is a decision we chose to make; it's arbitrary.
Here's an edited version of your function that accomplishes what I think you were going for:
#Global variables would be declared up here, before all other function declarations.
#Global variables would be available to all the functions that follow.
def input_fermat(): #if there were arguments in these parentheses they'd be included in input_fermat scope
# input_fermat() scope begins
a=int(input('Enter the first variable \'a\': \n'))
b=int(input('Enter the second variable \'b\': \n'))
c=int(input('Enter the third variable \'c\': \n'))
n=int(input('Enter the exponential variable \'n\': \n'))
return a, b, c, n
#input_fermat() scope ends
def check_fermat(): #if there were arguments in these parentheses they'd be included in check_fermat scope
#check_fermat() scope begins
#just as you returned 4 variables at once in input_fermat(), 4 variables can be assigned at once here
a,b,c,n = input_fermat() #need to assign because a, b, c, n from input_fermat() no longer in scope
calc_1=a**n
calc_2=b**n
calc_3=c**n
if n>2 and int(calc_1) + int(calc_2) == calc_3:
print('Holy smokes, Fermat was wrong!')
else:
print('No that doesn\'t')
#python implicitly does a `return None` here
#check_fermat() scope ends
check_fermat()
Note that because of the scopes of these functions, I could have declared the variables in check_fermat() as follows and it would all still work (try running this code for yourself to see)
def input_fermat():
a=int(input('Enter the first variable \'a\': \n'))
b=int(input('Enter the second variable \'b\': \n'))
c=int(input('Enter the third variable \'c\': \n'))
n=int(input('Enter the exponential variable \'n\': \n'))
return a, b, c, n
def check_fermat():
any,variable,names,go = input_fermat()
calc_1=any**go
calc_2=variable**go
calc_3=name**go
if n>2 and int(calc_1) + int(calc_2) == calc_3:
print('Holy smokes, Fermat was wrong!')
else:
print('No that doesn\'t')
check_fermat()
The Process of execution (for both code snippets) goes like this:
check_fermat() on the last line is executed because it's the only function called (not just defined) in our .py file.
Python looks for the definition of check_fermat() to execute it
3.Python finds input_fermat() is called inside check_fermat and goes looking for input_fermat()s definition.
Python finds the definition, executes the function and asks for input.
Input is returned back to check_fermat() and is used to compute Fermat's Last Theorem.
The rest of check_fermat() is carried out (output is printed to terminal). Then, check_fermat() returns None, ending the function call with no variables to return.

Python min override

In Python 3, I made a custom class C for a specific data structure that can be used as an iterable.
But the class ensures that for any data structure c of C, c[0] will be the minimum value of all values in c.
Is there a way that a call to min(c) simply returns c[0] without uselessly exploring all the structure ? (or as usual a ValueError if c is empty)
Is there a way that a call to min(c) simply returns c[0]?
Yes, there is 2 way :
The first one is modifying the source code of python and change the built in function structure, which is not wise and rational at all.
The second way is create your own min function in relative namespace.
Actually based on python name-resolution scheme which called the LEGB manner, When you use an unqualified name inside a scope, Python searches up to four scopes, the local (L) scope, then the local scopes of any enclosing (E) scopes (if it exist) , then the global (G) scope, and then the built-in (B) scope.Thus due to this rule the built in scope will be searches at end and you can simply create a new one on top level of this scope.
But Note that in that case you couldn't use the preceding min function, and if it happens to use it you can delete the costume function using del statement.
But another pythonic way to go with this task is that creating a min function inside your class and use it as an attribute :
>>> class C(object):
... def __init__(self):
... self.index = 0
... self.iterable = range(10)
... def __iter__(self):
... return self
... def min(self):
... try:
... return self.iterable[self.index]
... except IndxError:
... raise Exception('The index is out of range')
>>> c=C()
>>>
>>> c.min()
0
>>> c.iterable=[5,1,4,8]
>>> c.min()
5
Note that in this case you can specify a default index for min function to returns the relative item.

Passing Variables Simplified

I am working on a project, but I need to pass variables between functions and I do not know how. I am not very good at python at all. I just started learning it like a month ago. Anyhow I just want to know the simplest way to pass a variable between functions.
Can I just do this?
def a():
variable1 = 0
answer = raw_input()
if answer == "a":
print "Correct"
b()
def b():
#Variable1 should now be here also right?
a()
Add a parameter to your function b.
def b(argument1):
print 'This is function b(), argument1=', argument1
def a():
# call func b, passing it 42 as an argument
b(42)
Python Functions
In Python you can use global variables, but this is not the recommended way of doing things. Global variables should generally be avoided.
def b()
print 'This is function b(), globalVar1=', globalVar1
def a()
global globalVar1
globalVar1 = 88
b()
Using global variables in a function other than the one that created them
The easiest way to pass a variable between functions is to define the necessary function to accept an argument. Check out functions -part in the official tutorial
In your case you want to pass variable1 to b. Define b as such:
def b(var):
print var
# Whatever else you want to do..
def a():
variable1 = 0
answer = raw_input()
if answer == "a":
print "Correct"
b(variable1)
Your original code does not work because variables inside functions are local to those functions. Using function arguments is the correct way of doing what you want.

Do you change variables AFTER you run a function in python?

So I wrote this function from a book I am reading, and this is how it starts:
def cheese_and_crackers(cheese_count, boxes_of_crackers):
print "You have %d cheeses!" % cheese_count
print "You have %d boxes of crackers!" % boxes_of_crackers
print "Man that's enough for a party!"
print "Get a blanket.\n"
ok, makes sense. and then, this is when this function is run where I got a little confused and wanted to confirm something:
print "OR, we can use variables from our script:"
amount_of_cheese = 10
amount_of_crackers = 50
cheese_and_crackers(amount_of_cheese, amount_of_crackers)
the thing that confused me here is that the amount_of_cheese and amount_of_crackers is changing the variables (verbage? not sure if i am saying the right lingo) from cheese_count and boxes_of_crackers repectively from the first inital variable labels in the function.
so my question is, when you are using a different variable from the one that is used in the initial function you wrote, why would you change the name of the AFTER you wrote out the new variable names? how would the program know what the new variables are if it is shown after it?
i thought python reads programs top to bottom, or does it do it bottom to top?
does that make sense? i'm not sure how to explain it. thank you for any help. :)
(python 2.7)
I think you are just a bit confused on the naming rules for parameter passing.
Consider:
def foo(a, b):
print a
print b
and you can call foo as follows:
x = 1
y = 2
foo(x, y)
and you'll see:
1
2
The variable names of the arguments (a, b) in the function signature (1st line of function definition) do not have to agree with the actual variable names used when you invoke the function.
Think of it as this, when you call:
foo(x, y)
It's saying: "invoke the function foo; pass x in as a, pass y in as b". Furthermore, the arguments here are passed in as copies, so if you were to modify them inside the function, it won't change the values outside of the function, from where it was invoked. Consider the following:
def bar(a, b):
a = a + 1
b = b + 2
print a
x = 0
y = 0
bar(x, y)
print x
print y
and you'll see:
1
2
0
0
The script runs from top to bottom. The function executes when you call it, not when you define it.
I'd suggest trying to understand concepts like variables and function argument passing first.
def change(variable):
print variable
var1 = 1
change(var1)
In the above example, var1 is a variable in the main thread of execution.
When you call a function like change(), the scope changes. Variables you declared outside that function cease to exist so long as you're still in the function's scope. However, if you pass it an argument, such as var1, then you can use that value inside your function, by the name you give it in the function declaration: in this case, variable. But it is entirely separate from var! The value is the same, but it is a different variable!
Your question relates to function parameter transfer.
There are two types of parameter transfer into a function:
By value ------- value changed in function domain but not global domain
By reference ------- value changed in global domain
In python, non-atomic types are transferred by reference; atomic types (like string, integer) is transferred by value.
For example,
Case 1:
x = 20
def foo(x):
x+=10
foo()
print x // 20, rather than 30
Case 2:
d = {}
def foo(x): x['key']=20
foo(d)
print d // {'key': 20}

Categories

Resources