need help-variable creation in Python (continuation) - python

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.

Related

Create dynamic function in python?

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)

Python String and Instance Object confusion

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)

Python - Function - Argument said to be "undefined"

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')

__class_ data member in python, how it is different from static data member in java

i am trying to execute following code to understand Class data member in python, but it is throwing StopIteration error,
class PizzaShop():
pizza_stock = 10
def get_pizza(self):
while not PizzaShop.pizza_stock:
PizzaShop.pizza_stock -= 1
yield "take yours pizza order, total pizzas left {}".format(PizzaShop.pizza_stock)
mypizza_shop = PizzaShop()
pizza_order = mypizza_shop.get_pizza()
print "{}".format(repr(pizza_order.next()))
i am expecting that it should first print some message and then any exception
i am using python 2.7, ubuntu 32bits os
output:
Traceback (most recent call last):
File "/home/scott/pythonfiles/core_python/pizza.py", line 10, in <module>
print "{}".format(repr(pizza_order.next()))
StopIteration
The problem is this line
while not PizzaShop.pizza_stock:
This will stop immediately if pizza_stock is nonzero. Which it always is. You probably intended to write
while PizzaShop.pizza_stock:
Anyway, if you want to find the details on how values, classes, etc. behave in Python, you should check the docs. It's very different from Java.
P.S. The following is unnecessary as str.format has a shorthand for calling repr. Also, you shouldn't call magic methods like .next directly. Use the builtin next() instead.
print "{}".format(repr(pizza_order.next()))
Should be
print "{!r}".format(next(pizza_order))

What is the difference between syntax error and runtime error?

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

Categories

Resources