A suggestion for Python 3 vs Python 2

Hi python developers, I notice that one major change in python 3 is that it makes 'print' as a standard function, and it will require typing (). I do understand that it makes python language more consistent because most of the python functionalities are implemented as function calls. As you know, reading from and writing to IO is a high frequency operation. By entropy coding theorem (e.g. Huffman coding), an efficient language should assign shorter language code to more frequent tasks. Typing a '(' requires holding SHIFT and pressing 9, the input effort is much higher than that in Python 2. Also, specifying IO has changed from >>* to file=*, which also becomes more inconvenient. I hope you we can take a look at user's code and see what are the most commonly used functions and try to shorten the language codes for those functions. Assigning shortest language codes to most frequently used functions will make python the best programming language in the world. What I suggest is that either we can treat those most common functions like print as a special command to avoid typing (), or we add alias to these most common functions, so that if the user types: print >>fp1, 'hello world' Internally, it is equivalent to calling function print('hello world', file=fp1) Another suggestion is that 'enumerate' is also frequently used, hopefully we can shorten the command as well. Any comments? Wang Xuancong National University of Singapore

On Tue, Nov 12, 2013 at 2:45 PM, Xuancong Wang <xuancong84@gmail.com> wrote:
Yes, I/O is a very common operation; but not all I/O gets its own statement. Python doesn't have a keyword for reading input (REXX, for instance, has 'say' for output and 'pull' for input), and admittedly output IS more common than input, but I still don't see that having a keyword for one of them is really beneficial. Advantages of print being a function: * You can override it. Can't do that with a special language element. * It can be used in map, lambda, and other expression contexts. * Precedence etc follows the normal rules of functions - the arguments are all tidily enclosed. * Keyword arguments, rather than magical syntax, handle the oddities like end=" ". * You can easily alias it: "p = print; p('Hello, world!')" Advantages of print being a statement: * You don't have to hit Shift to create console output. Parsimony is important in design. Why have a statement when it can just be a built-in? Every keyword needs to justify itself, and far more than just "make this faster to type". Console output is common, but not half as common as, say, assignment, which is why assignment gets an extremely short and easy-to-type token. Basic arithmetic gets operators; "square root" doesn't, it just gets a named function. The less the language has to do (and the more the standard library does), the easier the language is to grok.
From the Zen of Python: Special cases aren't special enough to break the rules.
The rule is that function-like operations get called as functions. Maybe this would be a small benefit, but the cost of special-casing print is high. Anyway, you already get a single function name for it - it's not "sys.stdout.write(...)" - so it's already been given quite a boost in readability :) ChrisA

Xuancong Wang wrote:
As you know, reading from and writing to IO is a high frequency operation.
Actually, no, I don't know that. Thinking about the code I write, the proportion of it devoted to textual output is probably less than 1%, often far less. So by your argument it should have a rather verbose encoding! -- Greg

On Tue, Nov 12, 2013 at 07:44:03PM +1300, Greg Ewing wrote:
I agree strongly! print is simply not important enough to dedicated compiler magic to have it behave differently from every other function. I just picked one random project of mine, and found 23 instances of print in 1644 lines of code, or just under 1.4% of lines. In another project, I had zero instances of print in 2149 lines. In another project, I had 11 instances of the string print, but only 1 was the print statement (the rest were in documentation), out of 791 lines, approximately 0.1%. Consistency is far more important than saving a few key strokes. If print magically treats parentheses as optional, so that these are the same: print a, b, c, sep="**" print(a, b, c, sep="**") people will be confused why print is so special and they can't do the same with any arbitrary function: result = 1 + my_function a, b, c, keyword_argument=42 And of course, there is the problem that leaving out the parentheses makes it ambiguous in Python 3. Does this: my_tuple = (100, 200, print 42, "hello") print "42" and generate the tuple (100, 200, None, "hello"), or does it print "42 hello" and generate the tuple (100, 200, None)? -- Steven

On Tue, Nov 12, 2013 at 10:30 AM, Steven D'Aprano <steve@pearwood.info> wrote:
I bet that most people here started with Python at time when UX as a definition was unknown, but things that resulted in good UX were called 'pythonic'. http://www.youtube.com/watch?v=Ovj4hFxko7c Now about strong agreement from Steven. I believe this agreement is strictly theoretical. You know - "In theory, practice and theory are the same, but in practice..." - of this type. If we leave the discussion of "dedicated compiler magic" and "proper editor" aside and discuss only the User eXperience - don't you think that fast-typing "print var" is more convenient than "print(var)"? I believe that nobody objects against a better UX, but Steven pinpointed the conflicting point, which I'd like to stress - "dedicated compiler magic". I dislike enforced () in Py3k print as much as two other authors who raised questions about it here in the past week, but I kind of accept it existence for two reasons: 1. it is a clear mark of Python 3 compatible code 2. it makes Python interpreter interpret code faster [1], more reliable [1], less resource consuming [1] on low level platforms, such as Raspberry PI [1]: reference needed - I haven't seen any proof, except maybe a picture of difference in a parse tree (which probably got simplified, because print is now a function, and more complicated, because yield is not) Solution. My position is that I'd like to have both: 1. simple "print<SPACE>something" statement as a development aid for quick troubleshooting/debugging/hacking/writing (which may map to a function with single argument call) 2. print() function, for overriding, sending to other functions as param etc.
When researching programs, 90% of code I type are prints, which are never committed anywhere. When developing, I believe it is about 30%, because it is several orders faster to check that all inputs/outputs work correctly than to write proper test suite. So, your metrics is mostly relevant for the primary "print typing" use case that I personally find very annoying if applied to Python 3.
The first case is "print as statement". The second is "print as expression". People won't be confused, because 'result = print a,b,a' syntax is incorrect in the scenario I proposed.
Will it be good if only 'my_tuple = (100, 200, print(42), "hello")' syntax is supported in expression? -- anatoly t.

anatoly techtonik writes:
the User eXperience - don't you think that fast-typing "print var" is more convenient than "print(var)"?
Sure, but I don't type either: I typically type "pr<TAB>v<CLOVERLEAF+/>". I might need to type another letter or CLOVERLEAF+/ multiple times depending on context. This DTRTs in both Python 2 and Python 3 buffers. This is true in interpreter buffers as well as in programs being saved to files. And similar statements are true in all my coding, whatever language. Why complain about Python syntax when upgrading development tools could gives the same improvements without complicating Python?

On Wed, Nov 13, 2013 at 6:12 AM, Stephen J. Turnbull <stephen@xemacs.org> wrote:
I presume this is some kind of IDE you're running. I can't install and use IDEs in every shell / os / embed system / translated language where I have to debug my Python code.
Why complain about Python syntax when upgrading development tools could gives the same improvements without complicating Python?
This wisdom is absent from Python install instruction, so until it is there, we may discuss alternatives. So, what's wrong with supporting both: 1. print xxx - as a statement (which maps to function call) 2. print(xxx) - as an expression (which is a function call) ?

2013/11/13 anatoly techtonik <techtonik@gmail.com>:
Python2:
print (1,2) (1, 2)
Python3:
print (1,2) 1 2
What is your suggestion? Repeat Ruby's failure to make function call whitespace-insensitive?
That's horrible. Besides, how do you want code like this one to behave?
print = log print xxx
Or this:
I think it simply not worth it. Elazar

On Wed, Nov 13, 2013 at 10:22 PM, אלעזר <elazarg@gmail.com> wrote:
That's horrible. Ok, I agree - this is the reason why it might be impossible to make both statement and a function. But between two ambiguities I chose that the function syntax takes precedence, because "print xxx" is a limited helper for fast-typing, with well-known limitations. More arguments - I doubt people often print tuples without formatting, and even if they do this, it is the code that they usually read immediately and can spot the mistake, so it doesn't hurt. It is not beautiful to have such ambiguity, and may not be recommended, and still "print xxx" is a nice feature to have.
What is your suggestion? Repeat Ruby's failure to make function call whitespace-insensitive?
I don't know Ruby. Where I can read more about this Ruby's fail?
They should both map to print as expression, meaning print as a function, i.e. to the first one.
"print xxx" translates to simplified print() call on the language level.
The same. When you get AST, it is already print call, or the statement can be translated to expression just after AST is received.

2013/11/13 anatoly techtonik <techtonik@gmail.com>: the result. Since the second line has a space after the function name, Ruby assumes that the parentheses around the method call have been omitted. The parentheses that appear after the space are used to group a subexpression, but the entire expression (3+2)+1 is used as the method argument. If warnings are enabled (with -w), Ruby issues a warning whenever it sees ambiguous code like this. The solution to this whitespace dependency is straightforward: * Never put a space between a method name and the opening parenthesis. * If the first argument to a method begins with an open parenthesis, always use parentheses in the method invocation. For example, write f((3+2)+1). * Always run the Ruby interpreter with the -w option so it will warn you if you forget either of the rules above! """ I think avoiding this problem is better than dodging it and have a special warning, Even if print does not return meaningful value in the first place.
So you want Python to behave like this:
That's pretty incosistent and will surprise beginners. My own feelings is that this feature is the kind of thing that can make a person leave the language, or never begin using it in the first place; Things like this are part of the reason I don't use Ruby. And all this to save keystrokes? If it was part of a bigger feature, like ML's curried functions syntax, it would have been great - things like: perr = print sys.stderr perr "Bad command or file name" But keystrokes just can't be the reason for introducing such inconsistencies. Elazar

On Nov 13, 2013, at 12:44, אלעזר <elazarg@gmail.com> wrote:
I know this is getting way off topic, but the real problem with doing curried/auto-partial functions in Python isn't the parens, it's the variable arguments. An auto-partial function has to accumulate parameters if it doesn't get enough, execute when it does. (Currying gives you that for free, because it means you only get one argument at a time, but you can do auto-partials without currying.) With print, how do you know when it has "enough" arguments? You can write a decorator that only works on functions with fixed parameter counts pretty easily: @autopartial def spam(word, n): for _ in range(n): print(word) eggs = spam('eggs') eggs(3) But to handle a vararg function, you'd need a separate syntax for partializing vs. calling. Using a different operator like [] or % or << seems attractive at first, but it can't handle keywords. You could add a method, so spam._(n=5) returns partial(spam, n=5), but ._ is hideous, and anything meaningful like bind or partial is no longer a shortcut. You could use a special argument value, and ... looks perfect, especially as args[-1]: spam('eggs', ...). Until you consider keywords args, which come after args[-1]. So the best you can do is args[0]: spam(..., 'eggs', n=3). That isn't terrible, but I'm not sure it's nice enough to be worth the cost of people not understanding what it's doing.

But to handle a vararg function, you'd need a separate syntax for partializing vs. calling.
I personally like the _ notation used by scala; with macros<https://github.com/lihaoyi/macropy#quick-lambdas>you could easily write something like: f[spam(_, 5)] f[spam(_, n=_)] Which desugars into lambda x: spam(x, 5) lambda x, y: spam(x, n=y) If you were willing to special-case further, you could simply have spam(_, 5) spam(_, n=_) be representative of the partial-application. Granted _ is already used for other things (e.g. i18n) but that's a solvable problem (make i18n use __, let partial application use $). On Wed, Nov 13, 2013 at 7:13 PM, Andrew Barnert <abarnert@yahoo.com> wrote:

On Nov 13, 2013, at 20:17, Haoyi Li <haoyi.sg@gmail.com> wrote:
Actually, you can get about 80% of the way without macros. I've got an expression template library (that I never finished) that lets you write things like this: _2 ** (1 - _1) Where _1 and _2 are clever objects that turn this into an equivalent of: lambda x, y: y ** (1 - x) (Although it's actually a chain of calls, one for each operator.) The big missing part is handling function calls. It's easy when the function is one of your magic lambda args: _1(0) becomes lambda f: f(0). But when the function is a normal function, there's no __rcall__ to override, so you have to write it like this: _(f)(_1) And you need similar tricks whenever you have an expression where neither argument is magic but you want the value delayed. For example, to get lambda: a+b you need to write _(a) + b. And there's also the fact that not every operator in Python is overloadable. Anyway, I like the explicitly-numbered arguments better than the single _, because it allows you to use the same argument multiple times in the expression. (Plus, I already used plain _ as the wrapper to turn a normal value into a magic delayed value.) But I'll bet you could design it so _ works like in Scala, but _1 through _9 work my way (much as format strings can take both {} and {0}). As for why they're 1-based instead of 0-based, I don't remember; I suspect the only explanation is that I'm an idiot. Anyway, the big problem with the _ delay function is that sometimes you want a value closure, and sometimes a name, and the only way I could think of to handle both is to spell the latter as _('x'), which is ugly, and seems to encourage dynamic strings as arguments (which work, but it's as bad an idea as using globals()['x'] or eval('x') in normal code), and worst of all it looks exactly like gettext, which is a great way to confuse people. I later realized that with a bit of frame hacking, I could write a separate function _n(x). Tearing everything apart to make that work is where I ran out of steam and ended up with an incomplete library.

On Wed, Nov 13, 2013 at 07:13:19PM -0800, Andrew Barnert wrote:
I disagree. The real problem is the ambiguity. Given: y = divmod(x) did I intend for y to be a partial function, or did I mean to type divmod(x, 3) but mess up? Given how few coders come from a functional programming background, my money is that it's an error. In languages with static typing, it's easy for the compiler to resolve this: if y is declared as a function object, then I meant for the partial application. If y is declared as an int, then it's an error. But you can't do this in Python. [...]
But to handle a vararg function, you'd need a separate syntax for partializing vs. calling.
We have that. It's called functools.partial :-) Aside: am I the only one who wishes there was a functools.rpartial, that binds from the right instead of the left?
And why is this a problem? You read code more often than you type it, and quite frankly, creating partial applications of functions shouldn't be so common in real-world code that it needs to be so concise.
You could use a special argument value, and ... looks perfect, especially as args[-1]: spam('eggs', ...).
You and I have very different ideas about perfection. -- Steven

On 2013-11-14, at 16:05 , Steven D'Aprano <steve@pearwood.info> wrote:
In most of those languages, y likely isn’t explicitly typed and its type will be inferred depending on how it’s used.
If y is declared as an int, then it's an error. But you can’t do this in Python.
But it’ll likely blow up a few lines below when you try to perform arithmetic operations on a function (not that this is a good thing, but it’s no different from a function returning an unexpected None)
I’ve wanted this as well. Or the ability to somehow “fill holes”. Scala- or Clojure-type parse transforms are pretty neat for that (write the call with holes/placeholders, the call is deferred as a function taking arguments to fill the placeholders) Examples of Scala have already been provided, in Clojure it’s an explicit reader form: #(foo 1 2 %) is equivalent (and expanded) to (fn [arg] (foo 1 2 arg))

On Nov 14, 2013, at 7:47, אלעזר <elazarg@gmail.com> wrote:
This example doesn't actually show rpartial--but it's enough to make it obvious to anyone how you'd do that in Clojure, so that's ok.
I don't know why, but to me that strongly implies that I'm binding argument -1 (after 0 or more arguments, or maybe 1 or more), rather than argument 2 (after exactly 1). But that's not necessarily a bad thing. But if other people expect it to bind 2, they'll be surprised when they try it on a 3-argument (or variable-argument) function. (And yes, I realize that mixing 1-based arg counting with python negative indices is potentially confusing. I don't think it's confusing in this particular case, but in, say, documentation for a stdlib function it could be.)

On Thu, Nov 14, 2013 at 9:58 AM, Andrew Barnert <abarnert@yahoo.com> wrote:
How about: from functools import partial, __ sub5 = partial(sub, __, 5) xyz = partial(x, __, y, __, z) (Not quote sure what number of _ would work.) Then you could use ... to do the -1 argument binding: xyz = partial(x, __, y, ..., z) Incidentally, since partial(x) doesn't do anything useful (why does it not raise an exception?) would the following ever be reasonable to support? sub5 = partial(sub)(__, 5) The advantage is that the signature of the partial function stands alone making it easier to read. That is, def new_partial(func, *args, **kwargs): if not args and not kwargs: return partial(partial, func) return partial(func, *args, **kwargs) Probably the status quo wins. --- Bruce I'm hiring: http://www.cadencemd.com/info/jobs Latest blog post: Alice's Puzzle Page http://www.vroospeak.com Learn how hackers think: http://j.mp/gruyere-security

2013/11/14 Bruce Leban <bruce@leapyear.org>:
You get this automatically for partial-as-method: partial_sub = sub.partial sub5 = partial_sub(_, 5) It will not happen in accident (or at least it is very unlikely) so there'll be no need for an exception; when it does happen in accident, the behavior is easily understood. You also get cleaner separation of the parameters' roles - after all, x.foo *is* partial(<things>). Elazar

On Nov 14, 2013, at 7:05, Steven D'Aprano <steve@pearwood.info> wrote:
This may be a reason not to do it, but it's not something that makes it hard or impossible to do it. Variable arguments _are_ something that makes it hard or impossible to do it.
That's not how it works in any of the languages we're talking about. They have a type inference system, usually based on Hindley-Milner, not a C-style nominal type system. Of course sometimes declared (or elsewhere-inferred) variable types will resolve an ambiguity during unification, but that's not the usual case; declared or inferred function types do so far more often. divmod is int*int->int*int (or, in a curried language, int->int->int*int), and therefore this expression is only typable if it's a partial, and y's type is inferred from the type the expression has as a partial. (And if you've declared y to have an explicit type that isn't compatible with the partial, you get a unification error.) If you allow varargs functions, where the type can be int->int or int*int->int, HM doesn't work. And, not coincidentally, none of these languages allow varargs functions.
Yes, but the (sub-)thread started off with (summarizing) "I wish we had something more brief/simple/Scala-like for partials than functools.partial". And functools.partial is not an answer to that.
Aside: am I the only one who wishes there was a functools.rpartial, that binds from the right instead of the left?
I've often wanted that. I've even built it a few times. It has the same problem with keyword arguments and keyword-only params that auto-partialing does, but it doesn't feel like as much of a limitation--you just wouldn't ever use it in those cases (especially since you can often just bind the argument by keyword in those cases). I've also occasionally wanted a partial where you specify the indices of the arguments as keywords (which gives you rpartial just by using -1), so I could more easily bind the second of three (or even of variable) arguments. But that comes up less often.
I assume you're not asking about why ._ being hideous is a problem, but why .partial being not a shortcut is a problem, right? Offering foo.partial(n=5) as an alternative for partial(foo, n=5) doesn't provide any benefit--it's not easier to read, more obvious to write, shorter, or better in any other way. It just gives you two obvious ways to do it instead of one. Which is bad.
It's common in many application areas. For example, I have a row of radio buttons. Instead of defining 5 separate callback functions, I write one callback function that takes a number from 0 to 4, and then I bind each button to partial(callback, n). Many people today instead bind each button to a lambda, I suspect because the tkinter tutorials all use lambda for this purpose instead of partial. I've also seen people write an explicit make_btn_callback function so they can bind each button to make_btn_callback(n) Anyway, compare these three and tell me you see zero benefit in the last one: Button(frame, str(i), lambda event: click(i, event)) Button(frame, str(i), partial(click, i)) Button(frame, str(i), click(i, ...))

creating partial applications of functions shouldn't be so common in real-world code that it needs to be so concise.
I don't quite agree with this; I think a lot of people use some sort of partial application every day and just don't know it. - Of the times you use lambda, how often does it redirects all arguments to a single function, with the rest hard coded? - How often do you instantiate a class (with some args), call a method on that class (with some args) and then throw it away, never to be seen again? Both of these are basically crufty approximations for partial application, and I see them pretty often, especially the second one. On Thu, Nov 14, 2013 at 9:45 AM, Andrew Barnert <abarnert@yahoo.com> wrote:

On 13/11/2013 18:58, anatoly techtonik wrote:
Nothing. All that's needed is for somebody to write and champion a PEP, write the code, unit tests and documentation and away we go. Are you volunteering? -- Python is the second best programming language in the world. But the best has yet to be invented. Christian Tismer Mark Lawrence

Xuancong Wang writes:
I notice that one major change in python 3 is that it makes 'print' as a standard function, and it will require typing ().
What makes you think typing "()" is required? True, it needs to be present in the file, but typing is not necessarily required. Eg, if you use Emacs, you can define an abbreviation such that pr SPC automatically produces "print()"; with a little more effort you could define a "skeleton" which positions the cursor between the parentheses. I don't know if IDLE or WingIDE will do this for you, but certainly you could add such a feature to IDLE. I imagine other editors have similar possibilities. If there's really so much demand for it, I imagine Emacs's python-mode and IDLE at least will add those features. This kind of technology is getting quite advanced; predictive input methods are essential in Japanese, and I would suppose in Chinese as well. Spoken input is now a proven technology. I really don't think it's a good idea to argue about typing efficiency in this day and age; the changes you suggest are likely to be obsolete within a few years.

On Nov 11, 2013, at 19:45, Xuancong Wang <xuancong84@gmail.com> wrote:
Another suggestion is that 'enumerate' is also frequently used, hopefully we can shorten the command as well.
One huge advantage of everything being regular functions is that it's ridiculously easy to experiment with this. Want to see what it's like to use "en" or "ix" or whatever instead of enumerate? Just do "en = enumerate", and you can start using it. See how it affects your typing speed, and the readability of your code. (Obviously it will make your code less readable to the general Python community, but ignore that; the interesting question is whether you--or, better, a small group you work in--find it readable once you get used to it). Meanwhile, I personally vastly prefer print as a function to a statement. I can pass print to a function instead of having to write an out-of-line wrapper with def. I can do quick joining without spaces, and no-newline-ing without having to mess with magic commas. But then, like most of the others who prefer print as a function, I don't actually use it nearly as much as the people who are complaining, so maybe that doesn't mean much.

On 12 Nov 2013 20:15, "Andrew Barnert" <abarnert@yahoo.com> wrote:
On Nov 11, 2013, at 19:45, Xuancong Wang <xuancong84@gmail.com> wrote:
Another suggestion is that 'enumerate' is also frequently used,
hopefully we can shorten the command as well.
One huge advantage of everything being regular functions is that it's
ridiculously easy to experiment with this. Want to see what it's like to use "en" or "ix" or whatever instead of enumerate? Just do "en = enumerate", and you can start using it. See how it affects your typing speed, and the readability of your code. (Obviously it will make your code less readable to the general Python community, but ignore that; the interesting question is whether you--or, better, a small group you work in--find it readable once you get used to it).
Meanwhile, I personally vastly prefer print as a function to a statement.
I can pass print to a function instead of having to write an out-of-line wrapper with def. I can do quick joining without spaces, and no-newline-ing without having to mess with magic commas. But then, like most of the others who prefer print as a function, I don't actually use it nearly as much as the people who are complaining, so maybe that doesn't mean much. A few months ago I came up with a working "call statement" implementation that would allow the parens to be omitted from all simple calls, not just print: http://bugs.python.org/issue18788 That shows such an approach is technically feasible, but it also makes it clear there are major readability issues if the LHS is allowed to be an arbitrary expression. I'm still vaguely curious what a full PEP for 3.5 (with a suitably constrained LHS) might look like, but I'm not interested enough to write it myself. Cheers, Nick.

On Tue, Nov 12, 2013 at 08:42:57PM +1000, Nick Coghlan wrote:
IPython has had this feature for a while: In [1]: len [] ------> len([]) Out[1]: 0 As IPython is attempting to be an interactive shell rather than just a REPL, that makes a certain amount of sense, but it does lead to some unfortunate situations: In [2]: len [] + len [] ------> len([] + len []) ------------------------------------------------------------ File "<ipython console>", line 1 len([] + len []) ^ SyntaxError: invalid syntax -- Steven

On Nov 12, 2013, at 11:45 AM, Xuancong Wang wrote:
You can blame me for the original print>> syntax, which was the best of the worst suggestions for extending the print statement in Python 2. I also had a hard time making the mental and physical (muscle memory) switch to print() function in Python 3. Having used print() now for several years in both Python 3 and Python 2[*], I can say without hesitation that I'm really glad this change was made. print as a function is just so much better in so many ways. I particularly like the ease with which it can be mocked for testing. -Barry [*] from __future__ import print_function

On Nov 14, 2013, at 10:12 AM, Antoine Pitrou wrote:
As a reminder, having to hold SHIFT to enter a parenthesis depends on your keyboard layout.
http://www.artima.com/weblogs/viewpost.jsp?thread=173477 pinkie-ly y'rs, -Barry

On Tue, Nov 12, 2013 at 2:45 PM, Xuancong Wang <xuancong84@gmail.com> wrote:
Yes, I/O is a very common operation; but not all I/O gets its own statement. Python doesn't have a keyword for reading input (REXX, for instance, has 'say' for output and 'pull' for input), and admittedly output IS more common than input, but I still don't see that having a keyword for one of them is really beneficial. Advantages of print being a function: * You can override it. Can't do that with a special language element. * It can be used in map, lambda, and other expression contexts. * Precedence etc follows the normal rules of functions - the arguments are all tidily enclosed. * Keyword arguments, rather than magical syntax, handle the oddities like end=" ". * You can easily alias it: "p = print; p('Hello, world!')" Advantages of print being a statement: * You don't have to hit Shift to create console output. Parsimony is important in design. Why have a statement when it can just be a built-in? Every keyword needs to justify itself, and far more than just "make this faster to type". Console output is common, but not half as common as, say, assignment, which is why assignment gets an extremely short and easy-to-type token. Basic arithmetic gets operators; "square root" doesn't, it just gets a named function. The less the language has to do (and the more the standard library does), the easier the language is to grok.
From the Zen of Python: Special cases aren't special enough to break the rules.
The rule is that function-like operations get called as functions. Maybe this would be a small benefit, but the cost of special-casing print is high. Anyway, you already get a single function name for it - it's not "sys.stdout.write(...)" - so it's already been given quite a boost in readability :) ChrisA

Xuancong Wang wrote:
As you know, reading from and writing to IO is a high frequency operation.
Actually, no, I don't know that. Thinking about the code I write, the proportion of it devoted to textual output is probably less than 1%, often far less. So by your argument it should have a rather verbose encoding! -- Greg

On Tue, Nov 12, 2013 at 07:44:03PM +1300, Greg Ewing wrote:
I agree strongly! print is simply not important enough to dedicated compiler magic to have it behave differently from every other function. I just picked one random project of mine, and found 23 instances of print in 1644 lines of code, or just under 1.4% of lines. In another project, I had zero instances of print in 2149 lines. In another project, I had 11 instances of the string print, but only 1 was the print statement (the rest were in documentation), out of 791 lines, approximately 0.1%. Consistency is far more important than saving a few key strokes. If print magically treats parentheses as optional, so that these are the same: print a, b, c, sep="**" print(a, b, c, sep="**") people will be confused why print is so special and they can't do the same with any arbitrary function: result = 1 + my_function a, b, c, keyword_argument=42 And of course, there is the problem that leaving out the parentheses makes it ambiguous in Python 3. Does this: my_tuple = (100, 200, print 42, "hello") print "42" and generate the tuple (100, 200, None, "hello"), or does it print "42 hello" and generate the tuple (100, 200, None)? -- Steven

On Tue, Nov 12, 2013 at 10:30 AM, Steven D'Aprano <steve@pearwood.info> wrote:
I bet that most people here started with Python at time when UX as a definition was unknown, but things that resulted in good UX were called 'pythonic'. http://www.youtube.com/watch?v=Ovj4hFxko7c Now about strong agreement from Steven. I believe this agreement is strictly theoretical. You know - "In theory, practice and theory are the same, but in practice..." - of this type. If we leave the discussion of "dedicated compiler magic" and "proper editor" aside and discuss only the User eXperience - don't you think that fast-typing "print var" is more convenient than "print(var)"? I believe that nobody objects against a better UX, but Steven pinpointed the conflicting point, which I'd like to stress - "dedicated compiler magic". I dislike enforced () in Py3k print as much as two other authors who raised questions about it here in the past week, but I kind of accept it existence for two reasons: 1. it is a clear mark of Python 3 compatible code 2. it makes Python interpreter interpret code faster [1], more reliable [1], less resource consuming [1] on low level platforms, such as Raspberry PI [1]: reference needed - I haven't seen any proof, except maybe a picture of difference in a parse tree (which probably got simplified, because print is now a function, and more complicated, because yield is not) Solution. My position is that I'd like to have both: 1. simple "print<SPACE>something" statement as a development aid for quick troubleshooting/debugging/hacking/writing (which may map to a function with single argument call) 2. print() function, for overriding, sending to other functions as param etc.
When researching programs, 90% of code I type are prints, which are never committed anywhere. When developing, I believe it is about 30%, because it is several orders faster to check that all inputs/outputs work correctly than to write proper test suite. So, your metrics is mostly relevant for the primary "print typing" use case that I personally find very annoying if applied to Python 3.
The first case is "print as statement". The second is "print as expression". People won't be confused, because 'result = print a,b,a' syntax is incorrect in the scenario I proposed.
Will it be good if only 'my_tuple = (100, 200, print(42), "hello")' syntax is supported in expression? -- anatoly t.

anatoly techtonik writes:
the User eXperience - don't you think that fast-typing "print var" is more convenient than "print(var)"?
Sure, but I don't type either: I typically type "pr<TAB>v<CLOVERLEAF+/>". I might need to type another letter or CLOVERLEAF+/ multiple times depending on context. This DTRTs in both Python 2 and Python 3 buffers. This is true in interpreter buffers as well as in programs being saved to files. And similar statements are true in all my coding, whatever language. Why complain about Python syntax when upgrading development tools could gives the same improvements without complicating Python?

On Wed, Nov 13, 2013 at 6:12 AM, Stephen J. Turnbull <stephen@xemacs.org> wrote:
I presume this is some kind of IDE you're running. I can't install and use IDEs in every shell / os / embed system / translated language where I have to debug my Python code.
Why complain about Python syntax when upgrading development tools could gives the same improvements without complicating Python?
This wisdom is absent from Python install instruction, so until it is there, we may discuss alternatives. So, what's wrong with supporting both: 1. print xxx - as a statement (which maps to function call) 2. print(xxx) - as an expression (which is a function call) ?

2013/11/13 anatoly techtonik <techtonik@gmail.com>:
Python2:
print (1,2) (1, 2)
Python3:
print (1,2) 1 2
What is your suggestion? Repeat Ruby's failure to make function call whitespace-insensitive?
That's horrible. Besides, how do you want code like this one to behave?
print = log print xxx
Or this:
I think it simply not worth it. Elazar

On Wed, Nov 13, 2013 at 10:22 PM, אלעזר <elazarg@gmail.com> wrote:
That's horrible. Ok, I agree - this is the reason why it might be impossible to make both statement and a function. But between two ambiguities I chose that the function syntax takes precedence, because "print xxx" is a limited helper for fast-typing, with well-known limitations. More arguments - I doubt people often print tuples without formatting, and even if they do this, it is the code that they usually read immediately and can spot the mistake, so it doesn't hurt. It is not beautiful to have such ambiguity, and may not be recommended, and still "print xxx" is a nice feature to have.
What is your suggestion? Repeat Ruby's failure to make function call whitespace-insensitive?
I don't know Ruby. Where I can read more about this Ruby's fail?
They should both map to print as expression, meaning print as a function, i.e. to the first one.
"print xxx" translates to simplified print() call on the language level.
The same. When you get AST, it is already print call, or the statement can be translated to expression just after AST is received.

2013/11/13 anatoly techtonik <techtonik@gmail.com>: the result. Since the second line has a space after the function name, Ruby assumes that the parentheses around the method call have been omitted. The parentheses that appear after the space are used to group a subexpression, but the entire expression (3+2)+1 is used as the method argument. If warnings are enabled (with -w), Ruby issues a warning whenever it sees ambiguous code like this. The solution to this whitespace dependency is straightforward: * Never put a space between a method name and the opening parenthesis. * If the first argument to a method begins with an open parenthesis, always use parentheses in the method invocation. For example, write f((3+2)+1). * Always run the Ruby interpreter with the -w option so it will warn you if you forget either of the rules above! """ I think avoiding this problem is better than dodging it and have a special warning, Even if print does not return meaningful value in the first place.
So you want Python to behave like this:
That's pretty incosistent and will surprise beginners. My own feelings is that this feature is the kind of thing that can make a person leave the language, or never begin using it in the first place; Things like this are part of the reason I don't use Ruby. And all this to save keystrokes? If it was part of a bigger feature, like ML's curried functions syntax, it would have been great - things like: perr = print sys.stderr perr "Bad command or file name" But keystrokes just can't be the reason for introducing such inconsistencies. Elazar

On Nov 13, 2013, at 12:44, אלעזר <elazarg@gmail.com> wrote:
I know this is getting way off topic, but the real problem with doing curried/auto-partial functions in Python isn't the parens, it's the variable arguments. An auto-partial function has to accumulate parameters if it doesn't get enough, execute when it does. (Currying gives you that for free, because it means you only get one argument at a time, but you can do auto-partials without currying.) With print, how do you know when it has "enough" arguments? You can write a decorator that only works on functions with fixed parameter counts pretty easily: @autopartial def spam(word, n): for _ in range(n): print(word) eggs = spam('eggs') eggs(3) But to handle a vararg function, you'd need a separate syntax for partializing vs. calling. Using a different operator like [] or % or << seems attractive at first, but it can't handle keywords. You could add a method, so spam._(n=5) returns partial(spam, n=5), but ._ is hideous, and anything meaningful like bind or partial is no longer a shortcut. You could use a special argument value, and ... looks perfect, especially as args[-1]: spam('eggs', ...). Until you consider keywords args, which come after args[-1]. So the best you can do is args[0]: spam(..., 'eggs', n=3). That isn't terrible, but I'm not sure it's nice enough to be worth the cost of people not understanding what it's doing.

But to handle a vararg function, you'd need a separate syntax for partializing vs. calling.
I personally like the _ notation used by scala; with macros<https://github.com/lihaoyi/macropy#quick-lambdas>you could easily write something like: f[spam(_, 5)] f[spam(_, n=_)] Which desugars into lambda x: spam(x, 5) lambda x, y: spam(x, n=y) If you were willing to special-case further, you could simply have spam(_, 5) spam(_, n=_) be representative of the partial-application. Granted _ is already used for other things (e.g. i18n) but that's a solvable problem (make i18n use __, let partial application use $). On Wed, Nov 13, 2013 at 7:13 PM, Andrew Barnert <abarnert@yahoo.com> wrote:

On Nov 13, 2013, at 20:17, Haoyi Li <haoyi.sg@gmail.com> wrote:
Actually, you can get about 80% of the way without macros. I've got an expression template library (that I never finished) that lets you write things like this: _2 ** (1 - _1) Where _1 and _2 are clever objects that turn this into an equivalent of: lambda x, y: y ** (1 - x) (Although it's actually a chain of calls, one for each operator.) The big missing part is handling function calls. It's easy when the function is one of your magic lambda args: _1(0) becomes lambda f: f(0). But when the function is a normal function, there's no __rcall__ to override, so you have to write it like this: _(f)(_1) And you need similar tricks whenever you have an expression where neither argument is magic but you want the value delayed. For example, to get lambda: a+b you need to write _(a) + b. And there's also the fact that not every operator in Python is overloadable. Anyway, I like the explicitly-numbered arguments better than the single _, because it allows you to use the same argument multiple times in the expression. (Plus, I already used plain _ as the wrapper to turn a normal value into a magic delayed value.) But I'll bet you could design it so _ works like in Scala, but _1 through _9 work my way (much as format strings can take both {} and {0}). As for why they're 1-based instead of 0-based, I don't remember; I suspect the only explanation is that I'm an idiot. Anyway, the big problem with the _ delay function is that sometimes you want a value closure, and sometimes a name, and the only way I could think of to handle both is to spell the latter as _('x'), which is ugly, and seems to encourage dynamic strings as arguments (which work, but it's as bad an idea as using globals()['x'] or eval('x') in normal code), and worst of all it looks exactly like gettext, which is a great way to confuse people. I later realized that with a bit of frame hacking, I could write a separate function _n(x). Tearing everything apart to make that work is where I ran out of steam and ended up with an incomplete library.

On Wed, Nov 13, 2013 at 07:13:19PM -0800, Andrew Barnert wrote:
I disagree. The real problem is the ambiguity. Given: y = divmod(x) did I intend for y to be a partial function, or did I mean to type divmod(x, 3) but mess up? Given how few coders come from a functional programming background, my money is that it's an error. In languages with static typing, it's easy for the compiler to resolve this: if y is declared as a function object, then I meant for the partial application. If y is declared as an int, then it's an error. But you can't do this in Python. [...]
But to handle a vararg function, you'd need a separate syntax for partializing vs. calling.
We have that. It's called functools.partial :-) Aside: am I the only one who wishes there was a functools.rpartial, that binds from the right instead of the left?
And why is this a problem? You read code more often than you type it, and quite frankly, creating partial applications of functions shouldn't be so common in real-world code that it needs to be so concise.
You could use a special argument value, and ... looks perfect, especially as args[-1]: spam('eggs', ...).
You and I have very different ideas about perfection. -- Steven

On 2013-11-14, at 16:05 , Steven D'Aprano <steve@pearwood.info> wrote:
In most of those languages, y likely isn’t explicitly typed and its type will be inferred depending on how it’s used.
If y is declared as an int, then it's an error. But you can’t do this in Python.
But it’ll likely blow up a few lines below when you try to perform arithmetic operations on a function (not that this is a good thing, but it’s no different from a function returning an unexpected None)
I’ve wanted this as well. Or the ability to somehow “fill holes”. Scala- or Clojure-type parse transforms are pretty neat for that (write the call with holes/placeholders, the call is deferred as a function taking arguments to fill the placeholders) Examples of Scala have already been provided, in Clojure it’s an explicit reader form: #(foo 1 2 %) is equivalent (and expanded) to (fn [arg] (foo 1 2 arg))

On Nov 14, 2013, at 7:47, אלעזר <elazarg@gmail.com> wrote:
This example doesn't actually show rpartial--but it's enough to make it obvious to anyone how you'd do that in Clojure, so that's ok.
I don't know why, but to me that strongly implies that I'm binding argument -1 (after 0 or more arguments, or maybe 1 or more), rather than argument 2 (after exactly 1). But that's not necessarily a bad thing. But if other people expect it to bind 2, they'll be surprised when they try it on a 3-argument (or variable-argument) function. (And yes, I realize that mixing 1-based arg counting with python negative indices is potentially confusing. I don't think it's confusing in this particular case, but in, say, documentation for a stdlib function it could be.)

On Thu, Nov 14, 2013 at 9:58 AM, Andrew Barnert <abarnert@yahoo.com> wrote:
How about: from functools import partial, __ sub5 = partial(sub, __, 5) xyz = partial(x, __, y, __, z) (Not quote sure what number of _ would work.) Then you could use ... to do the -1 argument binding: xyz = partial(x, __, y, ..., z) Incidentally, since partial(x) doesn't do anything useful (why does it not raise an exception?) would the following ever be reasonable to support? sub5 = partial(sub)(__, 5) The advantage is that the signature of the partial function stands alone making it easier to read. That is, def new_partial(func, *args, **kwargs): if not args and not kwargs: return partial(partial, func) return partial(func, *args, **kwargs) Probably the status quo wins. --- Bruce I'm hiring: http://www.cadencemd.com/info/jobs Latest blog post: Alice's Puzzle Page http://www.vroospeak.com Learn how hackers think: http://j.mp/gruyere-security

2013/11/14 Bruce Leban <bruce@leapyear.org>:
You get this automatically for partial-as-method: partial_sub = sub.partial sub5 = partial_sub(_, 5) It will not happen in accident (or at least it is very unlikely) so there'll be no need for an exception; when it does happen in accident, the behavior is easily understood. You also get cleaner separation of the parameters' roles - after all, x.foo *is* partial(<things>). Elazar

On Nov 14, 2013, at 7:05, Steven D'Aprano <steve@pearwood.info> wrote:
This may be a reason not to do it, but it's not something that makes it hard or impossible to do it. Variable arguments _are_ something that makes it hard or impossible to do it.
That's not how it works in any of the languages we're talking about. They have a type inference system, usually based on Hindley-Milner, not a C-style nominal type system. Of course sometimes declared (or elsewhere-inferred) variable types will resolve an ambiguity during unification, but that's not the usual case; declared or inferred function types do so far more often. divmod is int*int->int*int (or, in a curried language, int->int->int*int), and therefore this expression is only typable if it's a partial, and y's type is inferred from the type the expression has as a partial. (And if you've declared y to have an explicit type that isn't compatible with the partial, you get a unification error.) If you allow varargs functions, where the type can be int->int or int*int->int, HM doesn't work. And, not coincidentally, none of these languages allow varargs functions.
Yes, but the (sub-)thread started off with (summarizing) "I wish we had something more brief/simple/Scala-like for partials than functools.partial". And functools.partial is not an answer to that.
Aside: am I the only one who wishes there was a functools.rpartial, that binds from the right instead of the left?
I've often wanted that. I've even built it a few times. It has the same problem with keyword arguments and keyword-only params that auto-partialing does, but it doesn't feel like as much of a limitation--you just wouldn't ever use it in those cases (especially since you can often just bind the argument by keyword in those cases). I've also occasionally wanted a partial where you specify the indices of the arguments as keywords (which gives you rpartial just by using -1), so I could more easily bind the second of three (or even of variable) arguments. But that comes up less often.
I assume you're not asking about why ._ being hideous is a problem, but why .partial being not a shortcut is a problem, right? Offering foo.partial(n=5) as an alternative for partial(foo, n=5) doesn't provide any benefit--it's not easier to read, more obvious to write, shorter, or better in any other way. It just gives you two obvious ways to do it instead of one. Which is bad.
It's common in many application areas. For example, I have a row of radio buttons. Instead of defining 5 separate callback functions, I write one callback function that takes a number from 0 to 4, and then I bind each button to partial(callback, n). Many people today instead bind each button to a lambda, I suspect because the tkinter tutorials all use lambda for this purpose instead of partial. I've also seen people write an explicit make_btn_callback function so they can bind each button to make_btn_callback(n) Anyway, compare these three and tell me you see zero benefit in the last one: Button(frame, str(i), lambda event: click(i, event)) Button(frame, str(i), partial(click, i)) Button(frame, str(i), click(i, ...))

creating partial applications of functions shouldn't be so common in real-world code that it needs to be so concise.
I don't quite agree with this; I think a lot of people use some sort of partial application every day and just don't know it. - Of the times you use lambda, how often does it redirects all arguments to a single function, with the rest hard coded? - How often do you instantiate a class (with some args), call a method on that class (with some args) and then throw it away, never to be seen again? Both of these are basically crufty approximations for partial application, and I see them pretty often, especially the second one. On Thu, Nov 14, 2013 at 9:45 AM, Andrew Barnert <abarnert@yahoo.com> wrote:

On 13/11/2013 18:58, anatoly techtonik wrote:
Nothing. All that's needed is for somebody to write and champion a PEP, write the code, unit tests and documentation and away we go. Are you volunteering? -- Python is the second best programming language in the world. But the best has yet to be invented. Christian Tismer Mark Lawrence

Xuancong Wang writes:
I notice that one major change in python 3 is that it makes 'print' as a standard function, and it will require typing ().
What makes you think typing "()" is required? True, it needs to be present in the file, but typing is not necessarily required. Eg, if you use Emacs, you can define an abbreviation such that pr SPC automatically produces "print()"; with a little more effort you could define a "skeleton" which positions the cursor between the parentheses. I don't know if IDLE or WingIDE will do this for you, but certainly you could add such a feature to IDLE. I imagine other editors have similar possibilities. If there's really so much demand for it, I imagine Emacs's python-mode and IDLE at least will add those features. This kind of technology is getting quite advanced; predictive input methods are essential in Japanese, and I would suppose in Chinese as well. Spoken input is now a proven technology. I really don't think it's a good idea to argue about typing efficiency in this day and age; the changes you suggest are likely to be obsolete within a few years.

On Nov 11, 2013, at 19:45, Xuancong Wang <xuancong84@gmail.com> wrote:
Another suggestion is that 'enumerate' is also frequently used, hopefully we can shorten the command as well.
One huge advantage of everything being regular functions is that it's ridiculously easy to experiment with this. Want to see what it's like to use "en" or "ix" or whatever instead of enumerate? Just do "en = enumerate", and you can start using it. See how it affects your typing speed, and the readability of your code. (Obviously it will make your code less readable to the general Python community, but ignore that; the interesting question is whether you--or, better, a small group you work in--find it readable once you get used to it). Meanwhile, I personally vastly prefer print as a function to a statement. I can pass print to a function instead of having to write an out-of-line wrapper with def. I can do quick joining without spaces, and no-newline-ing without having to mess with magic commas. But then, like most of the others who prefer print as a function, I don't actually use it nearly as much as the people who are complaining, so maybe that doesn't mean much.

On 12 Nov 2013 20:15, "Andrew Barnert" <abarnert@yahoo.com> wrote:
On Nov 11, 2013, at 19:45, Xuancong Wang <xuancong84@gmail.com> wrote:
Another suggestion is that 'enumerate' is also frequently used,
hopefully we can shorten the command as well.
One huge advantage of everything being regular functions is that it's
ridiculously easy to experiment with this. Want to see what it's like to use "en" or "ix" or whatever instead of enumerate? Just do "en = enumerate", and you can start using it. See how it affects your typing speed, and the readability of your code. (Obviously it will make your code less readable to the general Python community, but ignore that; the interesting question is whether you--or, better, a small group you work in--find it readable once you get used to it).
Meanwhile, I personally vastly prefer print as a function to a statement.
I can pass print to a function instead of having to write an out-of-line wrapper with def. I can do quick joining without spaces, and no-newline-ing without having to mess with magic commas. But then, like most of the others who prefer print as a function, I don't actually use it nearly as much as the people who are complaining, so maybe that doesn't mean much. A few months ago I came up with a working "call statement" implementation that would allow the parens to be omitted from all simple calls, not just print: http://bugs.python.org/issue18788 That shows such an approach is technically feasible, but it also makes it clear there are major readability issues if the LHS is allowed to be an arbitrary expression. I'm still vaguely curious what a full PEP for 3.5 (with a suitably constrained LHS) might look like, but I'm not interested enough to write it myself. Cheers, Nick.

On Tue, Nov 12, 2013 at 08:42:57PM +1000, Nick Coghlan wrote:
IPython has had this feature for a while: In [1]: len [] ------> len([]) Out[1]: 0 As IPython is attempting to be an interactive shell rather than just a REPL, that makes a certain amount of sense, but it does lead to some unfortunate situations: In [2]: len [] + len [] ------> len([] + len []) ------------------------------------------------------------ File "<ipython console>", line 1 len([] + len []) ^ SyntaxError: invalid syntax -- Steven

On Nov 12, 2013, at 11:45 AM, Xuancong Wang wrote:
You can blame me for the original print>> syntax, which was the best of the worst suggestions for extending the print statement in Python 2. I also had a hard time making the mental and physical (muscle memory) switch to print() function in Python 3. Having used print() now for several years in both Python 3 and Python 2[*], I can say without hesitation that I'm really glad this change was made. print as a function is just so much better in so many ways. I particularly like the ease with which it can be mocked for testing. -Barry [*] from __future__ import print_function

On Nov 14, 2013, at 10:12 AM, Antoine Pitrou wrote:
As a reminder, having to hold SHIFT to enter a parenthesis depends on your keyboard layout.
http://www.artima.com/weblogs/viewpost.jsp?thread=173477 pinkie-ly y'rs, -Barry
participants (17)
-
anatoly techtonik
-
Andrew Barnert
-
Antoine Pitrou
-
Barry Warsaw
-
Bruce Leban
-
Chris Angelico
-
Ethan Furman
-
Greg Ewing
-
Haoyi Li
-
Mark Janssen
-
Mark Lawrence
-
Masklinn
-
Nick Coghlan
-
Stephen J. Turnbull
-
Steven D'Aprano
-
Xuancong Wang
-
אלעזר