Ran into some interesting Python behavior today. I though I was writing
print("{}".format("some value"))
but instead I wrote
print("{}").format("some value")
and funnily enough it worked. So my question is, how does this work?
Digging deeper
This behavior seems to be python2 specific.
Python2.7
>>> print("{}").format("testing")
testing
Python3.4
>>> print("{}").format("testing)
File "<stdin>", line 1
print("{}").format("testing)
^
SyntaxError: EOL while scanning string literal
It also seems like the print function of python2 doesn't have a return value but Python3 does? so that confuses me even more.
Python2.7
>>> type(print("testing))
File "<stdin>", line 1
type(print("testing))
^
SyntaxError: invalid syntax
>>> a = print("testing")
File "<stdin>", line 1
a = print("testing")
^
SyntaxError: invalid syntax
Python3.4
>>> type(print("{}"))
{}
<class 'NoneType'>
>>> a = print("{}")
{}
>>> a
>>> type(a)
<class 'NoneType'>
In Python 2, print is a statement, not a function (unless you do from __future__ import print_function at the top of your module). This means that the parentheses around the thing you're printing are not part of a function call, but just treated as grouping parentheses. In the situation you describe ("{}") is the same as "{}" (the parens do nothing), so the format call works just like you'd expect if you wrote "{}".format(...).
In Python 3, print is a function, so the parentheses are not optional and can't be put in the wrong place. print returns None, so you're almost certainly going to get an error if you do print(something).something_else, since None doesn't have a something_else attribute.
In Python 2.7, print is a statement; this means that
print("{}").format("testing")
prints one expression, the result of the expression ("{}").format("testing"). That is, the format method is called on the (parenthesized) string before the print statement is evaluated. If you use
from __future__ import print_function
in the 2.7 examples, you'll get identical behavior to Python 3.
You're missing the closing quote after some strings (e.g. "testing).
As others are saying, Python 2 doesn't have a print() function, it has a print statement. Your strings (even if they were properly closed) are not what and where you think they are.
In Python 2, print is a statement keyword like raise, not a function. Parentheses aren't used for its arguments, and so print("{}").format("testing") is parsed as though you'd written print ("{}").format("testing"), which is the same as print(("{}").format("testing")). Because print is a statement, it cannot be used as an expression, and therefore it cannot have a return value.
If you want print in Python 2 to act like Python 3's print function, place this line at the top of your file:
from __future__ import print_function
Related
In Python 2.7 both the following will do the same
print("Hello, World!") # Prints "Hello, World!"
print "Hello, World!" # Prints "Hello, World!"
However the following will not
print("Hello,", "World!") # Prints the tuple: ("Hello,", "World!")
print "Hello,", "World!" # Prints the words "Hello, World!"
In Python 3.x parenthesis on print is mandatory, essentially making it a function, but in 2.7 both will work with differing results. What else should I know about print in Python 2.7?
In Python 2.x print is actually a special statement and not a function*.
This is also why it can't be used like: lambda x: print x
Note that (expr) does not create a Tuple (it results in expr), but , does. This likely results in the confusion between print (x) and print (x, y) in Python 2.7
(1) # 1 -- no tuple Mister!
(1,) # (1,)
(1,2) # (1, 2)
1,2 # 1 2 -- no tuple and no parenthesis :) [See below for print caveat.]
However, since print is a special syntax statement/grammar construct in Python 2.x then, without the parenthesis, it treats the ,'s in a special manner - and does not create a Tuple. This special treatment of the print statement enables it to act differently if there is a trailing , or not.
Happy coding.
*This print behavior in Python 2 can be changed to that of Python 3:
from __future__ import print_function
It's all very simple and has nothing to do with forward or backward compatibility.
The general form for the print statement in all Python versions before version 3 is:
print expr1, expr2, ... exprn
(Each expression in turn is evaluated, converted to a string and displayed with a space between them.)
But remember that putting parentheses around an expression is still the same expression.
So you can also write this as:
print (expr1), (expr2), ... (expr3)
This has nothing to do with calling a function.
Here we have interesting side effect when it comes to UTF-8.
>> greek = dict( dog="σκύλος", cat="γάτα" )
>> print greek['dog'], greek['cat']
σκύλος γάτα
>> print (greek['dog'], greek['cat'])
('\xcf\x83\xce\xba\xcf\x8d\xce\xbb\xce\xbf\xcf\x82', '\xce\xb3\xce\xac\xcf\x84\xce\xb1')
The last print is tuple with hexadecimal byte values.
Basically in Python before Python 3, print was a special statement that printed all the strings if got as arguments. So print "foo","bar" simply meant "print 'foo' followed by 'bar'". The problem with that was it was tempting to act as if print were a function, and the Python grammar is ambiguous on that, since (a,b) is a tuple containing a and b but foo(a,b) is a call to a function of two arguments.
So they made the incompatible change for 3 to make programs less ambiguous and more regular.
(Actually, I think 2.7 behaves as 2.6 did on this, but I'm not certain.)
I noticed that in the following snippet both approaches give the same result:
>>> a = [1,2,3]
>>> print(a[0])
1
>>> print(a)[0]
1
>>>
I was a bit surprised, as I would have expected print(a) to return a string, so then subscript 0 to just return the first character (Ie: [). However, it seems Python interprets it as a list?
Anybody able to clarify please?
As mentioned, you're using python 2.x, where print is a statement, not a function — so print(a)[0] being parsed as print a[0] — treating braces as parsing priority modifier.
Important thing — print does not return what you're printing. It sends data to stream (stdout by default). If you're using python 3.x (where print is a function) or use from __future__ import print_function — functions will send data to stream and return None as result. So print(a)[0] will resolve to "send content of a to stdout and return None[0]", later will raise IndexError
As #jonrsharpe mentioned in the comment block, you're probably running python 2.x.
print statement was replaced in python 3.x with print() function
>>> print(a)[0]
[1, 2, 3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not subscriptable
In Python 2.7 both the following will do the same
print("Hello, World!") # Prints "Hello, World!"
print "Hello, World!" # Prints "Hello, World!"
However the following will not
print("Hello,", "World!") # Prints the tuple: ("Hello,", "World!")
print "Hello,", "World!" # Prints the words "Hello, World!"
In Python 3.x parenthesis on print is mandatory, essentially making it a function, but in 2.7 both will work with differing results. What else should I know about print in Python 2.7?
In Python 2.x print is actually a special statement and not a function*.
This is also why it can't be used like: lambda x: print x
Note that (expr) does not create a Tuple (it results in expr), but , does. This likely results in the confusion between print (x) and print (x, y) in Python 2.7
(1) # 1 -- no tuple Mister!
(1,) # (1,)
(1,2) # (1, 2)
1,2 # 1 2 -- no tuple and no parenthesis :) [See below for print caveat.]
However, since print is a special syntax statement/grammar construct in Python 2.x then, without the parenthesis, it treats the ,'s in a special manner - and does not create a Tuple. This special treatment of the print statement enables it to act differently if there is a trailing , or not.
Happy coding.
*This print behavior in Python 2 can be changed to that of Python 3:
from __future__ import print_function
It's all very simple and has nothing to do with forward or backward compatibility.
The general form for the print statement in all Python versions before version 3 is:
print expr1, expr2, ... exprn
(Each expression in turn is evaluated, converted to a string and displayed with a space between them.)
But remember that putting parentheses around an expression is still the same expression.
So you can also write this as:
print (expr1), (expr2), ... (expr3)
This has nothing to do with calling a function.
Here we have interesting side effect when it comes to UTF-8.
>> greek = dict( dog="σκύλος", cat="γάτα" )
>> print greek['dog'], greek['cat']
σκύλος γάτα
>> print (greek['dog'], greek['cat'])
('\xcf\x83\xce\xba\xcf\x8d\xce\xbb\xce\xbf\xcf\x82', '\xce\xb3\xce\xac\xcf\x84\xce\xb1')
The last print is tuple with hexadecimal byte values.
Basically in Python before Python 3, print was a special statement that printed all the strings if got as arguments. So print "foo","bar" simply meant "print 'foo' followed by 'bar'". The problem with that was it was tempting to act as if print were a function, and the Python grammar is ambiguous on that, since (a,b) is a tuple containing a and b but foo(a,b) is a call to a function of two arguments.
So they made the incompatible change for 3 to make programs less ambiguous and more regular.
(Actually, I think 2.7 behaves as 2.6 did on this, but I'm not certain.)
Why this simple function is not working in python 2.7?
>>> def a(b,h):
... return b*h/2
... a(3,4)
File "<stdin>", line 3
a(3,4)
^
SyntaxError: invalid syntax
>>>
In the interactive interpreter, you'll need to add a blank line to close off the statement before the function is defined:
>>> def a(b,h):
... return b*h/2
...
>>>
Once you do, a new >>> prompt appears and you can enter the a(3,4) call.
From the Python reference documentation on Interactive input:
Note that a (top-level) compound statement must be followed by a blank line in interactive mode; this is needed to help the parser detect the end of the input.
Note that you may run into issues with integer division here; in Python 2 if both operands to the / division operator are integers, you'll get an integer result. See How can I force division to be floating point? Division keeps rounding down to 0 for work-arounds.
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