Can someone explain what happened in the second run ? Why did I get a stream of 9's when the code should have given an error?
>>> for __ in range(10): #first run
... print(__)
...
0
1
2
3
4
5
6
7
8
9
This was the second run
>>> for __ in range(10): #second run
... print(_)
...
9
9
9
9
9
9
9
9
9
9
>>> exit()
After this, when I ran the code for the third time, the same code executed as expected and gave the below error. I realize that this question has no practical use. But, I would really like to know why it happened?
NameError: name '_' is not defined
The _ variable is set in the Python interpreter, always holding the last non-None result of any expression statement that has been run.
From the Reserved Classifiers and Identifiers reference:
The special identifier _ is used in the interactive interpreter to store the result of the last evaluation; it is stored in the builtins module.
and from sys.displayhook():
If value is not None, this function prints repr(value) to sys.stdout, and saves value in builtins._. [...] sys.displayhook is called on the result of evaluating an expression entered in an interactive Python session.
Here, that result was 9, from an expression you must have run before the code you shared.
The NameError indicates you restarted the Python interpreter and did not yet run an expression statement yet that produced a non-None value:
>>> _
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_' is not defined
>>> 3 * 3
9
>>> _
9
Related
This question already has answers here:
How Python's closure works
(2 answers)
Can you explain closures (as they relate to Python)?
(13 answers)
Can anybody explain about the closure of function in Python?
(2 answers)
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 1 year ago.
I am learning Python and while I was doing exercises with decorators, I found a case that I don't understand. The code bellow, inspired by the tutorial I use, is working:
>>> def maxExeTime(absMax,printMax=False):
... def decorFun(toDo):
... storeInfo = {"exeMax":0}
... def modified(*p,**pp):
... startTime = time.time()
... returnValue = toDo(*p,**pp)
... exeTime = time.time() - startTime
... if exeTime > storeInfo["exeMax"]:
... storeInfo["exeMax"] = exeTime
... if printMax:
... print("max execution time = {}".format(storeInfo["exeMax"]))
... if exeTime > absMax:
... raise Exception("Max exe time reached: {}".format(exeTime))
... return returnValue
... return modified
... return decorFun
...
>>> #maxExeTime(15,printMax=True)
... def mul(x,y):
... input("Press Enter...")
... return x*y
...
>>>
>>> mul(3,4)
Press Enter...
max execution time = 1.1439800262451172
12
>>> mul(3,5)
Press Enter...
max execution time = 2.1652064323425293
15
>>> mul(3,7)
Press Enter...
max execution time = 2.1652064323425293
21
>>> mul(3,10)
Press Enter...
max execution time = 21.074586629867554
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 13, in modified
Exception: Max exe time reached: 21.074586629867554
>>>
But I don't understand why the dictionary storeInfo is persistent and can be re-used from one call to the other. If I try to store the information directly in a variable (ie exeMax=0) and adapt the code accordingly, I get the behavior that I was expecting with an exception at run time: UnboundLocalError: local variable 'exeMax' referenced before assignment when I try to compare the current execution time with the actual max value (if exeTime > exeMax:)
Why does the dictionary persists out of the scope of the maxExeTime function execution?
Thanks to the links an the redirection to duplicate questions, I discovered closure which was a concept I never see before. Good. And I understand why it does not work in my test with the local variable exeMax since I didn't declare it as nonlocal. But I didn't do it either for the dictionary storeInfo, and it is working. Why does this type of object have a different behavior?
Edit
#kindall what you say explains why it is necessary to use nonlocal when I use and integer directly since it seems that integers have a different behavior/rules than other objects, and I want to modify the value in the inner function.
But I still don't understand why if exeTime < exeMax: fails when exeTime < storeInfo["exeMax"] does not, and then why the next code is valid.
>>> a = 12
>>> def m(x):
... return a*x
...
>>> m(3)
36
>>> a = 15
>>> m(3)
45
For the moment, all these differences in behavior make the variable scope definition looking fuzzy for me. I need to find a clear definition of it, with, I hope, a small set of rules and no exception.
I am working on a project is to convert text into numbers. (For example, "hello world" would be converted to "8 5 12 12 15 27 23 15 18 12 4").
In line 10 of my code, the for loop causes the following error message:
Traceback (most recent call last):
File "C:\Users\gabri\PycharmProjects\padding\main.py", line 15, in <module>
converter(plaintext)
File "C:\Users\gabri\PycharmProjects\padding\main.py", line 10, in converter
for n in plaintext:
TypeError: 'types.GenericAlias' object is not iterable
Process finished with exit code 1
My code is as follows:
alphabet = ("a","b","c","d","e","f","g","h","i","j","k","l","m",'n',"o","p","q","r",'s','t','u','v','w','x','y','z')
def getplaintext():
global plaintext
plaintext = list[input("Enter plaintext:.....")]
print(plaintext)
def converter(plaintext):
for n in plaintext:
print(n)
getplaintext()
converter(plaintext)
Does anybody know what is causing this error?
You need to use list with (), not [].
plaintext = list(input("Enter plaintext:.....")) # With ()
In newer versions of Python, container types such as list can be hinted directly to specify the type of the elements the container holds. By using square braces here, you create a generic type hint of a list (a "generic alias"). A generic alias for a list is not iterable, as it is not actually a list. This is what causes your error.
I have a lot of txt, I want to read it, and plus them(every txt have same shape of array)
for i in base_n:
dfp_base=np.loadtxt(base_n,skiprows=2,usecols=(1,2,3))
dfp_base+=dfp_base
print dfp_base
but it's will only plus the end of files
I try to assign a variable but it's will give me an error
for i in base_n:
dfp_base=np.loadtxt(base_n,skiprows=2,usecols=(1,2,3))
dfp_base_s+=dfp_base
print dfp_base_s
UnboundLocalError: local variable 'dfp_base_s' referenced before assignment
how to fix it?
EDIT
i define a zero array and solve this problem
dfp_base_s=np.zeros(shape=(30,3))
your problem that you are trying to assign to var that not referenced before assignment
see on below:
for i in range(1,10):
dfp_base=1
dfp_base_s+=dfp_base
NameError Traceback (most recent call last)
<ipython-input-2-24596062a447> in <module>
1 for i in range(1,10):
2 dfp_base=1
----> 3 dfp_base_s+=dfp_base
4
NameError: name 'dfp_base_s' is not defined
but if you initialize before the loop that will work
dfp_base_s = 0
for i in range(1,10):
dfp_base=1
dfp_base_s+=dfp_base
dfp_base_s
9
While trying to solve a problem on Hackerank(The Problem). I checked the solutions of people who have solved this problem. Here is the solution from one person-
n = input()
l = []
for _ in range(n):
s = raw_input().split()
cmd = s[0]
args = s[1:]
if cmd !="print":
cmd += "("+ ",".join(args) +")"
eval("l."+cmd)
else:
print l
I cannot understand line 8 and line 9, can someone explain me these lines? Can i write line 8 and line 9 in Python 3 as i'm learning Python 3 ? How ?
Basically, cmd is constructed by appending the command (say "insert"), to the operands. This cmd forms a correct python expression (for example l.insert(0,5), to insert 5 at index 0, in list l).
Here, l. is hardcoded(start of line 9), cmd is initialized in cmd = s[0], and operands are added in line 8.
eval(str) evaluates the command str, in string format, as if it were in a command line.
It would be nice to just include the problem :) . The input is a (text) file as below:
Sample Input 0
12
insert 0 5
insert 1 10
insert 0 6
print
remove 6
append 9
append 1
sort
print
pop
reverse
print
And the expected output for a correct answer is as below:
Sample Output 0
[6, 5, 10]
[1, 5, 9, 10]
[9, 5, 1]
Before looking at the answer you quoted it would be good to read about eval; it takes the argument provided and tries to run it as a python expression using the global and local namespace. So in this case it needs only the local for the "l"-list and "cmd"-tuple.
What is happening is the following:
Empty list l is created.
The "command" (cmd) single-value list is parsed from the line by slicing (cmd = s[0]), since every line starts with or only has a list method
The other arguments are placed in args
Line 8 (as asked): These other arguments are then joined in a string tuple. So "insert 0 5" gives "insert" for l and "(0, 5)" for cmd
Line 8 continued (as asked): cmd is then combined with args using string concatenation (read here for a good and bad example) resulting in "insert(0,5)" as value for cmd
Line 9 (as asked): the eval parameter is yet another string concatenation yielding "l.insert(0,5)" as final expression to be interpreted. Which then inserts integer value 5 on spot 0 in list l (pushing forward any other values already in l)
Hope it helps, keep on trucking!
So I am fairly new to Python as I am sure will become apparent.
Anyways, is there a limit to the number of arguments I can pass when using .format?
I have a list of 8000 numbers that need to replace existing numbers in a long input in various places in the input. At the moment, I am planning on doing this:
text = """ very long input with many {0}..{1}..{8000} in various places """
file = open('new_input', 'w')
file.write(text.format(x,x1,x2,....x8000))
Any advice would be much appreciated!
As wim notes, you could do it with argument unpacking, but if you actually passed them positionally as individual named arguments, it wouldn't work; there is a limit of 255 explicitly provided individual arguments.
Demonstration:
>>> globals().update(('x{}'.format(i), i) for i in range(8000))
>>> codestr = '("{{}}"*8000).format({})'.format(', '.join('x{}'.format(i) for i in range(8000)))
>>> eval(codestr)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
SyntaxError: more than 255 arguments
The limit is due to how the CALL_FUNCTION opcode is defined; it's encoded as a single byte indicating the opcode, then one byte for the number of positional arguments, and one for the number of keyword arguments. While in theory it could handle up to 510 total arguments, they actually impose a combined limit of 255 arguments, presumably for consistency. So you can't actually call a function with more than 255 total arguments without involving * or ** unpacking.
This is all technically an implementation detail BTW; there is no language requirement that it work this way, so it could change in a future release of CPython (the reference interpreter) and behave differently in any other interpreter (most of which don't produce or use CPython bytecode anyway) right now.
I'm not aware of any hard limit and 8000 is not that big anyway, I think it should not be any problem.
Example with positional templating:
>>> text = "{} "*8000
>>> text = text.format(*range(8000))
>>> '{' in text
False
>>> text[:50]
'0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 '
>>> text[-50:]
'7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 '
Example with name templating:
>>> s = ' '.join(['{{x{}}}'.format(i) for i in range(8000)])
>>> d = {'x{}'.format(i):i for i in range(8000)}
>>> s[:25] + '...' + s[-24:]
'{x0} {x1} {x2} {x3} {x4} ... {x7997} {x7998} {x7999}'
>>> s = s.format(**d)
>>> s[:25] + '...' + s[-24:]
'0 1 2 3 4 5 6 7 8 9 10 11...7995 7996 7997 7998 7999'