Why is print a keyword in python and not a function?
Because Guido has decided that he made a mistake. :)
It has since been corrected: try Python 3, which dedicates a section of its release notes to describing the change to a function.
For the whole background, see PEP 3105 and the several links provided in its References section!
print was a statement in Python because it was a statement in ABC, the main inspiration for Python (although it was called WRITE there). That in turn probably had a statement instead of a function as it was a teaching language and as such inspired by basic. Python on the other hand, turned out to be more than a teaching language (although it's good for that too).
However, nowadays print is a function. Yes, in Python 2 as well, you can do
from __future__ import print_function
and you are all set. Works since Python 2.6.
It is now a function in Python 3.
The print statement in Python 2.x has some special syntax which would not be available for an ordinary function. For example you can use a trailing , to suppress the output of a final newline or you can use >> to redirect the output to a file. But all this wasn't convincing enough even to Guido van Rossum himself to keep it a statement -- he turned print into a function in Python 3.x.
An answer that draws from what I appreciate about the print statement, but not necessarily from the official Python history...
Python is, to some extent, a scripting language. Now, there are lots of definitions of "scripting language", but the one I'll use here is: a language designed for efficient use of short or interactive programs. Such languages tend to allow one-line programs without excessive boilerplate; make keyboard input easier (for instance, by avoiding excessive punctuation); and provide built-in syntax for common tasks (convenience at the possible expense of purity). In Python's case, printing a value is a very common thing to do, especially in interactive mode. Requiring print to be a function seems unnecessarily inconvenient here. There's a significantly lower risk of error with the special syntax that does the right thing 99% of the time.
I will throw in my thoughts on this:
In Python 2.x print is not a statement by mistake, or because printing to stdout is such a basic thing to do. Everything else is so thought-through or has at least understandable reasons that a mistake of that order would seem odd. If communicating with stdout would have been cosidered so basic, communicating with stdin would have to be just as important, yet input() is a function.
If you look at the list of reserved keywords and the list of statements which are not expressions, print clearly stands out which is another hint that there must be very specific reasons.
I think print had to be a statement and not an expression, to avoid a security breach in input(). Remember that input() in Python2 evaluates whatever the user types into stdin. If the user typed print a and a holds a list of all passwords, that would be quiet catastrophic.
Apparently, the ability of input() to evaluate expressions was considered more important than print being a normal built-in function.
Related
Why would my code be an appropriate style for Java, but not for Python?
dct=getDictionary()
if dct.has_key(3):
invokeTriples(dct[3])
postProcessForTriples()
print("Done for triples")
if dct.has_key(7):
invokeSeptuples(dct[7])
postProcessForOthers()
print("All done!")
Personally, I don't see the problem. Can you explain what she meant by 'appropriate'? And maybe give me a good idea of the approach I should take to making it more appropriate?
python is entirely based on indentation so your if statements being indented is wrong (since they don't need to be)
You also have your dct indented by 1, your if 3 more and then your internals of if statement 4 more so your indentation is not consistent.
Finally your statement is pretty ambiguous since your code isn't actually styled for java.
here is how your code should probably be formatted
dct=getDictionary()
if dct.has_key(3):
invokeTriples(dct[3])
postProcessForTriples()
print("Done for triples")
if dct.has_key(7):
invokeSeptuples(dct[7])
postProcessForOthers()
print("All done!")
Haven't used python for like 4 years so might be wrong but pretty sure that's how it works
Without seeing the rest of the code it's hard to say exactly what the commenter might be referring to, but a few things stand out even without context:
The names don't follow standard Python conventions (e.g. snake_case)
Indentation is wonky (this would cause a runtime error in Python because indentation matters)
has_key is deprecated; I don't think I've ever seen it used in actual Python code.
A more "pythonic" version of this code might look like:
dct = get_dictionary()
if 3 in dct:
invoke_triples(dct[3])
post_process_triples()
print("Done for triples")
if 7 in dct:
invoke_septuples(dct[7])
post_process_others()
print("All done!")
Your exact question is, "Why would my code be an appropriate style for Java, but not for Python?"
So, if I as an instructor gave you that comment, I would mean that you have not complied with PEP 8 -- Style Guide for Python Code. And, as your instructor that is an expectation I have of your code.
Your professor is basically asking you to compare Java and Python. Since I am more experienced with java, I can tell you that you should compare the external libraries you used and calling if statement method.
If you have any further questions, feel free to ask.
I can't help you much because your question is generic
Have a good day!
I've seen this multiple times in multiple places, but never have found a satisfying explanation as to why this should be the case.
So, hopefully, one will be presented here. Why should we (at least, generally) not use exec() and eval()?
EDIT: I see that people are assuming that this question pertains to web servers – it doesn't. I can see why an unsanitized string being passed to exec could be bad. Is it bad in non-web-applications?
There are often clearer, more direct ways to get the same effect. If you build a complex string and pass it to exec, the code is difficult to follow, and difficult to test.
Example: I wrote code that read in string keys and values and set corresponding fields in an object. It looked like this:
for key, val in values:
fieldName = valueToFieldName[key]
fieldType = fieldNameToType[fieldName]
if fieldType is int:
s = 'object.%s = int(%s)' % (fieldName, fieldType)
#Many clauses like this...
exec(s)
That code isn't too terrible for simple cases, but as new types cropped up it got more and more complex. When there were bugs they always triggered on the call to exec, so stack traces didn't help me find them. Eventually I switched to a slightly longer, less clever version that set each field explicitly.
The first rule of code clarity is that each line of your code should be easy to understand by looking only at the lines near it. This is why goto and global variables are discouraged. exec and eval make it easy to break this rule badly.
When you need exec and eval, yeah, you really do need them.
But, the majority of the in-the-wild usage of these functions (and the similar constructs in other scripting languages) is totally inappropriate and could be replaced with other simpler constructs that are faster, more secure and have fewer bugs.
You can, with proper escaping and filtering, use exec and eval safely. But the kind of coder who goes straight for exec/eval to solve a problem (because they don't understand the other facilities the language makes available) isn't the kind of coder that's going to be able to get that processing right; it's going to be someone who doesn't understand string processing and just blindly concatenates substrings, resulting in fragile insecure code.
It's the Lure Of Strings. Throwing string segments around looks easy and fools naïve coders into thinking they understand what they're doing. But experience shows the results are almost always wrong in some corner (or not-so-corner) case, often with potential security implications. This is why we say eval is evil. This is why we say regex-for-HTML is evil. This is why we push SQL parameterisation. Yes, you can get all these things right with manual string processing... but unless you already understand why we say those things, chances are you won't.
eval() and exec() can promote lazy programming. More importantly it indicates the code being executed may not have been written at design time therefore not tested. In other words, how do you test dynamically generated code? Especially across browsers.
Security aside, eval and exec are often marked as undesirable because of the complexity they induce. When you see a eval call you often don't know what's really going on behind it, because it acts on data that's usually in a variable. This makes code harder to read.
Invoking the full power of the interpreter is a heavy weapon that should be only reserved for very tricky cases. In most cases, however, it's best avoided and simpler tools should be employed.
That said, like all generalizations, be wary of this one. In some cases, exec and eval can be valuable. But you must have a very good reason to use them. See this post for one acceptable use.
In contrast to what most answers are saying here, exec is actually part of the recipe for building super-complete decorators in Python, as you can duplicate everything about the decorated function exactly, producing the same signature for the purposes of documentation and such. It's key to the functionality of the widely used decorator module (http://pypi.python.org/pypi/decorator/). Other cases where exec/eval are essential is when constructing any kind of "interpreted Python" type of application, such as a Python-parsed template language (like Mako or Jinja).
So it's not like the presence of these functions are an immediate sign of an "insecure" application or library. Using them in the naive javascripty way to evaluate incoming JSON or something, yes that's very insecure. But as always, its all in the way you use it and these are very essential functions.
I have used eval() in the past (and still do from time-to-time) for massaging data during quick and dirty operations. It is part of the toolkit that can be used for getting a job done, but should NEVER be used for anything you plan to use in production such as any command-line tools or scripts, because of all the reasons mentioned in the other answers.
You cannot trust your users--ever--to do the right thing. In most cases they will, but you have to expect them to do all of the things you never thought of and find all of the bugs you never expected. This is precisely where eval() goes from being a tool to a liability.
A perfect example of this would be using Django, when constructing a QuerySet. The parameters passed to a query accepts keyword arguments, that look something like this:
results = Foo.objects.filter(whatever__contains='pizza')
If you're programmatically assigning arguments, you might think to do something like this:
results = eval("Foo.objects.filter(%s__%s=%s)" % (field, matcher, value))
But there is always a better way that doesn't use eval(), which is passing a dictionary by reference:
results = Foo.objects.filter( **{'%s__%s' % (field, matcher): value} )
By doing it this way, it's not only faster performance-wise, but also safer and more Pythonic.
Moral of the story?
Use of eval() is ok for small tasks, tests, and truly temporary things, but bad for permanent usage because there is almost certainly always a better way to do it!
Allowing these function in a context where they might run user input is a security issue, and sanitizers that actually work are hard to write.
Same reason you shouldn't login as root: it's too easy to shoot yourself in the foot.
Don't try to do the following on your computer:
s = "import shutil; shutil.rmtree('/nonexisting')"
eval(s)
Now assume somebody can control s from a web application, for example.
Reason #1: One security flaw (ie. programming errors... and we can't claim those can be avoided) and you've just given the user access to the shell of the server.
Try this in the interactive interpreter and see what happens:
>>> import sys
>>> eval('{"name" : %s}' % ("sys.exit(1)"))
Of course, this is a corner case, but it can be tricky to prevent things like this.
Some python-2.7 and python-3.x functions have the same name, but perform differently. Can I import use a py2.7 function in python-3.x one, by changing its name?
The motivating example is python-2.7's "print", i.e. print "TEXT" which does not use without parenthesis, compared to print("TEXT") in python 3. Can I keep the python 2 "print" by binding it to something like pr?
(By the way, the issue for me is typing and escaping the brackets. The keys ( and ) are harder to press than a space bar. Also, because my IDE puts them in automatically, I then need to move my cursor out of it.)
Note: I asked this previously, yet has been wrongly marked as a duplicate.
Again, to be clear, I'm specifically asking if I can bind a python 2 function to a new name in order to use its functionality in python-3.x.
Can I bind python-2.7's `print` in python-3.x, allowing me to use `print` without parenthesis in python-3.x?
I do not know how to contact moderators via internal message or correct this wrongful flag.
The real solution is to configure your IDE, rather than try and hack your way around those configuration problems.
That said, the Python 2 print statement with a space and no parenthesis does not exist in Python 3. While you can find ways to use the function from Python 2, the syntax cannot be used.
If your real problem is with the parentheses in print() for python 3, then no, as far as I know there's not really a solution. If it's a different function, you could always do
def funcName(arg):
return anotherFunc(arg)
or as chepner comments
funcName = anotherFunc
effectively renaming anotherFunc().
As for your IDE specific issues, there's probably a way to turn off the automatic parentheses (or you could just use the arrow keys on your keyboard) and the more you use the parentheses, the faster you'll get using them, which is probably a good thing, as they're used in basically every function you'll ever use.
Finally, it's best not to force a language to do a specific thing that it doesn't really provide for. You don't use GOTOs in Python - they're not built in for a reason. You can write them using other methods. You use parentheses in python 3 - don't try to change that! There's another reason not to alter a language in the way you're describing - it decreases the readability of your code. Everyone will know what you mean when you write
''.join(something)
but not when you write
randomFuncName(something)
and then in some obscure spot you have a function like the one described above that renames ''.join.
Python is a "whitespace delimited" language. However, the use of semicolons are allowed. For example, the following works, but it is frowned upon:
print("Hello!");
print("This is valid");
I've been using Python for several years now, and the only time I have ever used semicolons is in generating one-time command-line scripts with Python:
python -c "import inspect, mymodule; print(inspect.getfile(mymodule))"
Or adding code in comments on Stack Overflow (i.e., "you should try import os; print os.path.join(a,b)")
I also noticed in this answer to a similar question that the semicolon can also be used to make one line if blocks, as in
if x < y < z: print(x); print(y); print(z)
which is convenient for the two usage examples I gave (command-line scripts and comments).
The above examples are for communicating code in paragraph form or making short snippets, but not something I would expect in a production codebase.
Here is my question: in Python, is there ever a reason to use the semicolon in a production code? I imagine that they were added to the language solely for the reasons I have cited, but it’s always possible that Guido had a grander scheme in mind.
No opinions please; I'm looking either for examples from existing code where the semicolon was useful, or some kind of statement from the python docs or from Guido about the use of the semicolon.
PEP 8 is the official style guide and says:
Compound statements (multiple statements on the same line) are generally discouraged.
(See also the examples just after this in the PEP.)
While I don't agree with everything PEP 8 says, if you're looking for an authoritative source, that's it. You should use multi-statement lines only as a last resort. (python -c is a good example of such a last resort, because you have no way to use actual linebreaks in that case.)
I use semicolons in code all of the time. Our code folds across lines quite frequently, and a semicolon is a definitive assertion that a statement is ending.
output, errors, status = generate_output_with_errors_and_status(
first_monstrous_functional_argument(argument_one_to_argument
, argument_two_to_argument)
, second_argument);
See? They're quite helpful to readability.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
A while ago, when I was learning Javascript, I studied Javascript: the good parts, and I particularly enjoyed the chapters on the bad and the ugly parts. Of course, I did not agree with everything, as summing up the design defects of a programming language is to a certain extent subjective - although, for instance, I guess everyone would agree that the keyword with was a mistake in Javascript. Nevertheless, I find it useful to read such reviews: even if one does not agree, there is a lot to learn.
Is there a blog entry or some book describing design mistakes for Python? For instance I guess some people would count the lack of tail call optimization a mistake; there may be other issues (or non-issues) which are worth learning about.
You asked for a link or other source, but there really isn't one. The information is spread over many different places. What really constitutes a design mistake, and do you count just syntactic and semantic issues in the language definition, or do you include pragmatic things like platform and standard library issues and specific implementation issues? You could say that Python's dynamism is a design mistake from a performance perspective, because it makes it hard to make a straightforward efficient implementation, and it makes it hard (I didn't say completely impossible) to make an IDE with code completion, refactoring, and other nice things. At the same time, you could argue for the pros of dynamic languages.
Maybe one approach to start thinking about this is to look at the language changes from Python 2.x to 3.x. Some people would of course argue that print being a function is inconvenient, while others think it's an improvement. Overall, there are not that many changes, and most of them are quite small and subtle. For example, map() and filter() return iterators instead of lists, range() behaves like xrange() used to, and dict methods like dict.keys() return views instead of lists. Then there are some changes related to integers, and one of the big changes is binary/string data handling. It's now text and data, and text is always Unicode. There are several syntactic changes, but they are more about consistency than revamping the whole language.
From this perspective, it appears that Python has been pretty well designed on the language (syntax and sematics) level since at least 2.x. You can always argue about indentation-based block syntax, but we all know that doesn't lead anywhere... ;-)
Another approach is to look at what alternative Python implementations are trying to address. Most of them address performance in some way, some address platform issues, and some add or make changes to the language itself to more efficiently solve certain kinds of tasks. Unladen swallow wants to make Python significantly faster by optimizing the runtime byte-compilation and execution stages. Stackless adds functionality for efficient, heavily threaded applications by adding constructs like microthreads and tasklets, channels to allow bidirectional tasklet communication, scheduling to run tasklets cooperatively or preemptively, and serialisation to suspend and resume tasklet execution. Jython allows using Python on the Java platform and IronPython on the .Net platform. Cython is a Python dialect which allows calling C functions and declaring C types, allowing the compiler to generate efficient C code from Cython code. Shed Skin brings implicit static typing into Python and generates C++ for standalone programs or extension modules. PyPy implements Python in a subset of Python, and changes some implementation details like adding garbage collection instead of reference counting. The purpose is to allow Python language and implementation development to become more efficient due to the higher-level language. Py V8 bridges Python and JavaScript through the V8 JavaScript engine – you could say it's solving a platform issue. Psyco is a special kind of JIT that dynamically generates special versions of the running code for the data that is currently being handled, which can give speedups for your Python code without having to write optimised C modules.
Of these, something can be said about the current state of Python by looking at PEP-3146 which outlines how Unladen Swallow would be merged into CPython. This PEP is accepted and is thus the Python developers' judgement of what is the most feasible direction to take at the moment. Note it addresses performance, not the language per se.
So really I would say that Python's main design problems are in the performance domain – but these are basically the same challenges that any dynamic language has to face, and the Python family of languages and implementations are trying to address the issues. As for outright design mistakes like the ones listed in Javascript: the good parts, I think the meaning of "mistake" needs to be more explicitly defined, but you may want to check out the following for thoughts and opinions:
FLOSS Weekly 11: Guido van Rossum (podcast August 4th, 2006)
The History of Python blog
Is there a blog entry or some book describing design mistakes for Python?
Yes.
It's called the Py3K list of backwards-incompatible changes.
Start here: http://docs.python.org/release/3.0.1/whatsnew/3.0.html
Read all the Python 3.x release notes for additional details on the mistakes in Python 2.
My biggest peeve with Python - and one which was not really addressed in the move to 3.x - is the lack of proper naming conventions in the standard library.
Why, for example, does the datetime module contain a class itself called datetime? (To say nothing of why we have separate datetime and time modules, but also a datetime.time class!) Why is datetime.datetime in lower case, but decimal.Decimal is upper case? And please, tell me why we have that terrible mess under the xml namespace: xml.sax, but xml.etree.ElementTree - what is going on there?
Try these links:
http://c2.com/cgi/wiki?PythonLanguage
http://c2.com/cgi/wiki?PythonProblems
Things that frequently surprise inexperienced developers are candidate mistakes. Here is one, default arguments:
http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/
A personal language peeve of mine is name binding for lambdas / local functions:
fns = []
for i in range(10):
fns.append(lambda: i)
for fn in fns:
print(fn()) # !!! always 9 - not what I'd naively expect
IMO, I'd much prefer looking up the names referenced in a lambda at declaration time. I understand the reasons for why it works the way it does, but still...
You currently have to work around it by binding i into a new name whos value doesn't change, using a function closure.
This is more of a minor problem with the language, rather than a fundamental mistake, but: Property overriding. If you override a property (using getters and setters), there is no easy way of getting the parent class' property.
Yeah, it's strange but I guess that's what you get for having mutable variables.
I think the reason is that the "i" refers to a box which has a mutable value and the "for" loop will change that value over time, so reading the box value later gets you the only value there is left.
I don't know how one would fix that short of making it a functional programming language without mutable variables (at least without unchecked mutable variables).
The workaround I use is creating a new variable with a default value (default values being evaluated at DEFINITION time in Python, which is annoying at other times) which causes copying of the value to the new box:
fns = []
for i in range(10):
fns.append(lambda j=i: j)
for fn in fns:
print(fn()) # works
I find it surprising that nobody mentioned the global interpreter lock.
One of the things I find most annoying in Python is using writelines() and readlines() on a file. readlines() not only returns a list of lines, but it also still has the \n characters at the end of each line, so you have to always end up doing something like this to strip them:
lines = [l.replace("\n", "").replace("\r", "") for l in f.readlines()]
And when you want to use writelines() to write lines to a file, you have to add \n at the end of every line in the list before you write them, sort of like this:
f.writelines([l + "\n" for l in lines])
writelines() and readlines() should take care of endline characters in an OS independent way, so you don't have to deal with it yourself.
You should just be able to go:
lines = f.readlines()
and it should return a list of lines, without \n or \r characters at the end of the lines.
Likewise, you should just be able to go:
f.writelines(lines)
To write a list of lines to a file, and it should use the operating systems preferred enline characters when writing the file, you shouldn't need to do this yourself to the list first.
My biggest dislike is range(), because it doesn't do what you'd expect, e.g.:
>>> for i in range(1,10): print i,
1 2 3 4 5 6 7 8 9
A naive user coming from another language would expect 10 to be printed as well.
You asked for liks; I have written a document on that topic some time ago: http://segfaulthunter.github.com/articles/biggestsurprise/
I think there's a lot of weird stuff in python in the way they handle builtins/constants. Like the following:
True = "hello"
False = "hello"
print True == False
That prints True...
def sorted(x):
print "Haha, pwned"
sorted([4, 3, 2, 1])
Lolwut? sorted is a builtin global function. The worst example in practice is list, which people tend to use as a convenient name for a local variable and end up clobbering the global builtin.