I'm currently taking a Python course, and got to the chapter in our book that talks about functions. (Please note, this is my first time learning any programming.)
One of the exercises I'm working on at the moment asks for me to turn a bunch of conditional statements into a function (i.e. generalization).
To make this brief, my problem is this:
After I define a function, let's say like so...
def count_letter(letter,string):
count = 0
for letter in string:
count += 1
print(count)
(That is the work, as far as I can recall, for what I typed up for the problem.)
I run the program, then call the function in the shell as usual...
(Example directly below)
>>> count_letter(a,bananana)
And I get the following output...
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
count_letter(a,bananana)
NameError: name 'a' is not defined
My teacher and everyone in our class can't figure out why we're getting such an error. We would understand if it was some other type of an error, but having the shell tell us an argument is 'undefined' (i.e. a variable, as we understand the error) is something we haven't been able to figure out.
We've been staring at the code for a week and still can't figure it out.
Any help would be very appreciated.
Afterthought: I'm trying to count the number of "a"s within "bananana" in the example. Thought I should clear the ambiguity there.
As written, a and bananana are the names of variables which should be defined in a similar way you defined the variable count. For example:
>>> character_to_search = 'l'
>>> text = 'Hello World'
>>> count_letter(character_to_search, text)
would be a correct syntax, because both character_to_search and text are undefined.
Another possibility is that instead of using actual variables, your intention was to pass strings directly to the function. In this case, your syntax is slightly incorrect. It should be (note the single quotes):
count_letter('a', 'bananana')
Related
I got NameError for calling test_gobject, but the funny thing is I never called this function name. I called test_gobjectpy()
Can you explain it to me why Python decide to call the wrong function name (see error output)
Maybe it has some problems because I have a string with the same name as function?!
file name test_dyn_fun.py
second_path = ['test_gobject.py', 'st1.py', 'test_show_desktop.py', 'download_img.py', 'test_dump.py']
print("second_path", second_path)
print()
for i in second_path:
#func = create_dyn_func(i)
tmp = i.replace(".", "") #rm dot for function name
print("tmp =", tmp)
exec(f"def {tmp}(): print({i})")
print()
print(dir(test_gobjectpy))
print()
print(locals())
test_gobjectpy()
Error output:
Traceback (most recent call last):
File "/home/manta/Coding/test_dyn_fun.py", line 13, in <module>
test_gobjectpy()
File "<string>", line 1, in test_gobjectpy
NameError: name 'test_gobject' is not defined
In your loop you create functions, the first one created is effectively created like this:
i = 'test_gobject.py'
tmp = 'test_gobjectpy'
exec(f"def {tmp}(): print({i})")
So, it's as if you ran:
exec("def test_gobjectpy(): print(test_gobject.py)")
For Python to print test_gobject.py, it tries to access an object called test_gobject and its attribute .py.
That's what is causing the error. The fact that test_gobject.py looks like a filename to you doesn't matter, it's just names of variables to Python, the way you wrote it.
What would you expect to happen if you called this function?
def test_gobjectpy():
print(test_gobject.py)
More in general, as a beginning programmer, it's generally best to stay away from stuff like exec() and eval(). It's very common for new Python programmers to think they need this, or that it somehow solves a problem they have, but it's generally the worst solution to the problem and rarely actually a good solution at all. (not never, just rarely)
Been looking around and can't find an answer.
So I call either raw_input() or input() to fill out a simple variable. But instead of running the function, I get
UnboundLocalError: local variable 'input' referenced before assignment
My code doesn't have 'input()' anywhere before that first call, and never makes a variable sharing the name. Same happens for 'raw_input()'. I'm confused here, as calls to the functions work fine in other code, and also on the console, but for some reason throw errors on this. No previous calls. Funny enough, it worked on my first run of the code, but now doesn't. What am I looking for?
Edit: Someone asked for the code. Not much to show.
end = False
lightsoff = []
lightson = []
bias = []
i = 0
while not end:
print "Set #" + str(i + 1) +", LED off: ",
offFile = input()
EDIT: To correct here, a variable named 'input' is referred to much later in the code (it's long). I wrote a couple of references backwards. I didn't know Python made a list (or something) of what's going to be a local variable before running, thus throwing up problems like this.
I suspect your code looks a bit like:
>>> def x():
... input = input()
... print(input)
...
>>> x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in x
UnboundLocalError: local variable 'input' referenced before assignment
>>>
The problem is that you've created a variable called 'input', and then trying to get something from it before it exists.
>>> def y():
... val = input()
... print(val)
...
>>> y()
Would work a bit better. In python (and most dynamic languages) functions are kind of values too - so you can use the name of a function just like you would any other variable.
So a good idea is to not name a variable the same as a function.
Does that help?
Inside a class, in the __repr__ constructor, python is confused about what is a string and what isn't. This is for a school project, don't worry, I won't actually be handling social security numbers here.
The code below does not work:
def __repr__(self):
return (
'\nName:\t'+self.getName()+':\t\t\tNurse\n'+
'\tPhone:\t\t\t\t\t\t('+str(self.getPhoneNumber())[0:3]+') '+
str(self.getPhoneNumber())[3:6]+'-'+str(self.getPhoneNumber())[6:10]+'\n'+
'\tOverseeing Doctor:\t\t\t'+self.getDoctor()+'\n'
'\tDescription:\t\t\t\t'+self.getDesc()+'\n'+
'\tBirthday:\t\t\t\t\t'+self.getBDay()+'\n'+
'\tSocial Security Number:\t\t***-**-'+str(round(self.getSocial()))[5:9]+'\n'+#error is in this line
str(self._cases[i] for i in range(len(self._cases)))
)
However, in a different class, I have nearly identical code that does work:
def __repr__(self):
return (
'\nName:\t'+self.getName()+':\t\t\tDoctor\n'+
'\tPhone:\t\t\t\t\t\t('+str(self.getPhoneNumber())[0:3]+') '+
str(self.getPhoneNumber())[3:6]+'-'+str(self.getPhoneNumber())[6:10]+'\n'+
'\tDepartment:\t\t\t\t\t'+self.getDepartment()+'\n'
'\tDescription:\t\t\t\t'+self.getDesc()+'\n'+
'\tBirthday:\t\t\t\t\t'+self.getBDay()+'\n'+
'\tSocial Security Number:\t\t***-**-'+str(self.getSocial())[5:9]+'\n'+
str(self._cases)+'\n'
)
Please tell me what is different between the two, and how to fix the initial code.
You claim there is an error in this part:
str(round(self.getSocial()))[5:9]
but did not tell us anything about your actual error; errors come with tracebacks and exception messages, but without those details we cannot tell you anything about what might go wrong there. Perhaps self.getSocial() returns a string, and round() only takes floating point numbers:
>>> round('123')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: a float is required
You'll need to give us that error message as well as your inputs (the return value of self.getSocial()) and the expected output so we can help you solve that part; perhaps you misunderstood what round() does.
Next, you are trying to convert a generator expression to a string:
str(self._cases[i] for i in range(len(self._cases))
Everything between the parentheses is a lazy evaluating loop, but str() won't evaluate it for you.
If you wanted to produce a string of all cases, joined together with, say, tabs, use str.join() instead:
'\t'.join([str(self._cases[i]) for i in range(len(self._cases)])
You really should look into using str.format() templating; it'll make for much improved and readable code. Your 'working' example would translate to:
def __repr__(self):
phone = str(self.getPhoneNumber())
social = str(self.getSocial())
return (
'\n'
'Name:\t{name}:\t\t\tDoctor\n'
'\tPhone:\t\t\t\t\t\t({phone1}) {phone2}-{phone3}\n'
'\tDepartment:\t\t\t\t\t{dept}\n'
'\tDescription:\t\t\t\t{desc}\n'
'\tBirthday:\t\t\t\t\t{bday}\n'
'\tSocial Security Number:\t\t***-**-{social}\n'
'{cases}\n').format(
name=self.getName(),
phone1=phone[:3], phone2=phone[3:6], phone3=phone[6:10],
dept=self.getDepartment(), desc=self.getDesc(),
bday=self.getBDay(), social=social[5:9],
cases=self._cases)
For example:
def tofloat(i):
return flt(i)
def addnums(numlist):
total = 0
for i in numlist:
total += tofloat(i)
return total
nums = [1 ,2 ,3]
addnums(nums)
The flt is supposed to be float, but I'm confused whether it is a syntax error or a runtime error.
Actually, it is a runtime error, because Python will try to resolve the flt name during runtime (because it's a dynamic language), and it won't find it. When this happens, Python yields and exception saying that it couldn't find the symbol you were using flt and all this happens at runtime.
Syntax errors happen when the interpreter find something not compelling with Python's syntax. For example: The Python's grammar doesn't recognize the input syntax as a valid Python program. This may happen when:
You forgot to add : at the end of an if, def, class, etc expression
You forgot to close some parenthesis or brackets, etc.
A lot of places else when you don't adhere to python's grammar :)
In your example, there is nothing wrong with the grammar. For the interpreter, flt(i) is a very valid call to a flt method which had to be check at runtime within the scopes if it really exists. So the interpreter won't complaint and the syntax of your problem is good.
Actually, this can be seen as a disadvantage over compiled languages like C#, C++, etc. This kind of errors can be detected sooner at compile time, and the compiler screams loud when it find it so you can notice it.
With dynamic languages, you won't notice this until the actual method is called. Your program is simple, so you may find it quick. But, what about the missing o in float was inside some legacy framework within a subclass of a subclass of a class, as a property, inside some other module, etc. That would be harsh :)
UPDATE: The execution model in Python's docs are a great read if you're into how does Python internals works. This will clarify your doubt further and will give you a lot of knowledge :)
Hope this helps!
SyntaxError is raised by parser when it founds that your syntax is not correct, like missing colons, parenthesis, invalid statements etc. It'll not allow you to execute your code until you don't fix that the issue.
Your code will throw only error at runtime, i.e when the function tofloat(i) is called for the first time, so it is a runtime error. Specifically NameError.
Also a runtime error won't stop your program's execution until that buggy part is not executed. So, your code can actually run fine if you don't call tofloat ever.
The code below executes properly up to third line but then stops as NameError is raised.(a runtime error)
print 1
print 2
print 3
print foo
output:
1
2
3
Traceback (most recent call last):
File "so.py", line 4, in <module>
print foo
NameError: name 'foo' is not defined
This code won't execute as we made a SyntaxError, even though the first 3 lines are perfectly okay:
print 1
print 2
print 2
print (foo
Output:
$ python so.py
File "so.py", line 5
^
SyntaxError: invalid syntax
Note that there's also a RunTimeError in python, which is raised when an error is detected that doesn't fall in any of the other categories
You have a NameError, Your code should read:
def tofloat(i):
return float(i)
There is no flt method in Python, that is why it is not working for you.
Incidentally, you really don't need to wrap that float casting into a function, and your whole code can be written as:
def addnums(numlist):
return sum(map(float, numlist))
Using it:
>>> addnums(range(4))
6.0
That was helpful kgiannakakis.
I'm facing a problem as below:
a = ['zbc','2.3']
for i in range(0,5):
exec('E%d=%s' %(i,a[i]))
This results in:
Traceback (most recent call last):
File "", line 2, in
exec('E%d=%s' %(i,a[i]))
File "", line 1, in
NameError: name 'zbc' is not defined
It looks like the code you're generating expands to:
E0=zbc
E1=2.3
At the next iteration through the loop, you'll get an IndexError exception because a is only two elements long.
So given the above, you are trying to assign the value of zbc to E0. If zbc doesn't exist (which it seems that it doesn't), then you will get the NameError you mention.
It's hard to determine what you're actually trying to do with this code, so I'm not sure what to recommend. You could assign strings instead:
exec('E%d="%s"' %(i,a[i]))
This would expand to:
E0="zbc"
E1="2.3"
You would still get the IndexError because your array a is not 5 elements long. That should be an easy fix for you.
Okay. this code is very weird.
As a one liner like this, it's not syntactically correct, but I suspect you're missing line breaks for some reason. But then it becomes
a = ['zbc','2.3']
for i in range(0,5):
exec('E%d=%s' %(i,a[i]))
But that will result in an index error on the reference to a[i] as shown:
>>> a
['zbc', '2.3']
>>> for i in range(0,5):
... print a[i]
...
zbc
2.3
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: list index out of range
If you avoided that issue, you'd get
exec("E2.3=1")
on the second pass through the lopp, and that's a syntax error too.
It seems you are trying to use the solution marked in this question.
If your goal is access values in a loop, you should just use a list. This weird concept of variable names with numbers in them is not one that should be used in any language. Try this.
vals = ['foo', 'bar', 'blah', 67, -0.4, 'your mom']
for i in range(len(vals)):
print(vals[i])
That is the correct way to have a list of values indexed by an integer, not putting it in the variable name.
Just keep in mind that 'exec' executes whatever string you pass in to it as if you typed it in your .py file or the interpreter.
When debugging exec() related code, it's helpful to log whatever you're about to 'exec' when you run into trouble, if you did that you'd easily have noticed that E0 wasn't being assigned to the string "zbc" but to the non-existent object zbc.
Aside from that, this code sample is really weird. There are some legitimate uses for parsing strings into instance variables, or objects in other namespaces, most notably when you're coding a highly dynamic class that needs to do sensible stuff with messy input, or needs to setup a bunch of instance variables from a dict or string. But without context, the code in your question looks like you're avoiding, or don't understand how, to use list() and dict() objects..
I'd recommend telling a bit more about what you're trying to achieve next time you ask a question around something as peculiar as this. That would give people a good opportunity to suggest a better solution, or –if you're approaching a particular problem in a completely sensible way– prevent a bunch of answers telling you that you're doing something completely wrong.