Documenting Python warts on Stack Overflow

I am thinking about [python-wart] on SO. There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations. Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues - no way to edit description to make it more clear - no voting/stars to percieve how important is this issue - no comment/noise filtering and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day SO at least allows: + voting + community wiki edits + useful comment upvoting + sorted lists + user editable tags (adding new warts is easy) This post is a result of facing with numerous locals/settrace/exec issues that are closed on tracker. I also have my own list of other issues (logging/subprocess) at GC project, which I might be unable to maintain in future. There is also some undocumented stuff (subprocess deadlocks) that I'm investigating, but don't have time for a write-up. So I'd rather move this somewhere where it could be updated. -- anatoly t.

On 12/25/2012 7:10 PM, anatoly techtonik wrote:
I am thinking about [python-wart] on SO. There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues - no way to edit description to make it more clear - no voting/stars to percieve how important is this issue - no comment/noise filtering and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day
SO at least allows: + voting + community wiki edits + useful comment upvoting + sorted lists + user editable tags (adding new warts is easy)
1) Stack Overflow probably won't accept this as a question. 2) a bunch of people answering "what is a wart" is not a way to get the Python community to agree on what needs to be changed in the language. People with ideas need to write them up thoughtfully with proposals for improvements, and then engage meaningfully in the discussion that follows. You seem to think that people just need to identify "warts" and then we can start changing the language to remove them. What you consider a "wart" is probably the result of a complex balance of competing forces. Changing Python is hard. We take backward compatibility very seriously, and that sometimes makes it hard to "remove warts." --Ned.
This post is a result of facing with numerous locals/settrace/exec issues that are closed on tracker. I also have my own list of other issues (logging/subprocess) at GC project, which I might be unable to maintain in future. There is also some undocumented stuff (subprocess deadlocks) that I'm investigating, but don't have time for a write-up. So I'd rather move this somewhere where it could be updated. -- anatoly t.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Wed, Dec 26, 2012 at 4:21 PM, Ned Batchelder <ned@nedbatchelder.com>wrote:
On 12/25/2012 7:10 PM, anatoly techtonik wrote:
I am thinking about [python-wart] on SO. There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues - no way to edit description to make it more clear - no voting/stars to percieve how important is this issue - no comment/noise filtering and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day
SO at least allows: + voting + community wiki edits + useful comment upvoting + sorted lists + user editable tags (adding new warts is easy)
1) Stack Overflow probably won't accept this as a question.
That's why it is proposed as a community wiki. 2) a bunch of people answering "what is a wart" is not a way to get the
Python community to agree on what needs to be changed in the language. People with ideas need to write them up thoughtfully with proposals for improvements, and then engage meaningfully in the discussion that follows.
You seem to think that people just need to identify "warts" and then we can start changing the language to remove them. What you consider a "wart" is probably the result of a complex balance of competing forces. Changing Python is hard. We take backward compatibility very seriously, and that sometimes makes it hard to "remove warts."
You've nailed it. The goal of listing warts on SO is not to prove that some language suxx [1], but to provide answers to question about *why* some particular wart exists. "wart" may not be the best word, because from the other side of rebalancing things there is most likely some "feature", but when people experience problems, they usually face only one side of the story [2] As I already said it is impossible to fully master the language without a complete coverage of such things. These things are equally interesting for users and for future contributors. There are the starting points in making the next better generation dynamic language (if the one is possible). SO is a FAQ site, not a web-page or a wiki, so I expect there to be answers with research on the history of design decisions behind the balancing of the language, the sources of "warts" and things that are balancing them on the other side. I expect there to find analysis what features will have to be removed in order for some specific "wart" to be gone, and I see it as a perfect entrypoint for learning high-level things about programming languages. Some people may get a feeling that a SO list like that will make a huge negative impact on Python development. I don't know how to respond to these concerns. =) In my life I haven't seen a person who abandoned Python completely after picking it up. That should mean something. From my side I'd like to thank to all core developers and say that you are doing the right thing. Unicode and Python 3 was hard, but even grumpy trolls like me start to like it. The next year will be the next exciting step in Python development. My IMHO is that it became mature enough to openly discuss its "bad child habits" in details and make fun of them accepting they as they are. Take it easy, and have a good year ahead! ;) 1. http://wiki.theory.org/YourLanguageSucks 2. http://adsoftheworld.com/media/ambient/bbc_world_soldier

2) a bunch of people answering "what is a wart" is not a way to get the
Python community to agree on what needs to be changed in the language. People with ideas need to write them up thoughtfully with proposals for improvements, and then engage meaningfully in the discussion that follows.
You seem to think that people just need to identify "warts" and then we can start changing the language to remove them. What you consider a "wart" is probably the result of a complex balance of competing forces. Changing Python is hard. We take backward compatibility very seriously, and that sometimes makes it hard to "remove warts."
You've nailed it. The goal of listing warts on SO is not to prove that some language suxx [1], but to provide answers to question about *why* some particular wart exists. "wart" may not be the best word, because from the other side of rebalancing things there is most likely some "feature", but when people experience problems, they usually face only one side of the story [2]
As I already said it is impossible to fully master the language without a complete coverage of such things. These things are equally interesting for users and for future contributors. There are the starting points in making the next better generation dynamic language (if the one is possible).
SO is a FAQ site, not a web-page or a wiki, so I expect there to be answers with research on the history of design decisions behind the balancing of the language, the sources of "warts" and things that are balancing them on the other side. I expect there to find analysis what features will have to be removed in order for some specific "wart" to be gone, and I see it as a perfect entrypoint for learning high-level things about programming languages.
Yet again, while I don't speak for the whole Python dev community, I predict this will not be officially endorsed. As for explaining why some things are the way they are, there are plenty of blog articles on the web trying to explain Python internals. Nick Coghlan has some very good ones (with the benefit of his being actually in the position to say *why* things are this way historically), Guido has articles on the history of Python, and even my humble blog has some internals pieces (which are more focused on the "how" instead of "why"). Consider directing your energies and obvious love for Python to constructive channels like contributing similar articles of your own. I'm sure that you'll be able to find core devs willing to review such articles and discuss them prior to your posting them. Also feel free to collect all such articles in some central location and maintaining the list - this actually could be very helpful for a lot of Python fans and devs alike. Eli

On Tue, Dec 25, 2012 at 4:10 PM, anatoly techtonik <techtonik@gmail.com>wrote:
I am thinking about [python-wart] on SO. There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues - no way to edit description to make it more clear - no voting/stars to percieve how important is this issue - no comment/noise filtering and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day
SO at least allows: + voting + community wiki edits + useful comment upvoting + sorted lists + user editable tags (adding new warts is easy)
This post is a result of facing with numerous locals/settrace/exec issues that are closed on tracker. I also have my own list of other issues (logging/subprocess) at GC project, which I might be unable to maintain in future. There is also some undocumented stuff (subprocess deadlocks) that I'm investigating, but don't have time for a write-up. So I'd rather move this somewhere where it could be updated. --
Is this a question or just a rant? If it's a question, I must have missed what it is exactly that you're asking? The web is a pretty free place. Feel free to create such a tag on Stack Overflow and maintain it, if the SO community agrees it has merit. Don't expect the Python developers to officially endorse it, because "warts" is a very subjective issue. A "wart" for one person is a reasonable behavior for another. Eli

2012/12/26 anatoly techtonik <techtonik@gmail.com>:
I am thinking about [python-wart] on SO.
I'm not sure that StackOverflow is the best place for such project. (Note: please avoid abreviation, not all people know this website.)
There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
Sorry, but what is a wart in Python?
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues
When an issue is closed with "won't fix", "works for me", "invalid" or something like this, a comment always explain why. If you don't understand or such comment is missing, you can ask for more information. If you don't agree, the bug tracker is maybe not the right place for such discussion. The python-ideas mailing list is maybe a better place :-) Sometimes, the best thing to do is to propose a patch to enhance the documentation.
- no way to edit description to make it more clear
You can add comments, it's almost the same.
- no voting/stars to percieve how important is this issue
Votes are a trap. It's not how Python is developed. Python core developers are not paid to work on Python, and so work only on issues which interest them. I don't think that votes would help to fix an issue. If you want an issue to be closed: - ensure that someone else reproduced it: if not, provide more information - help to analyze the issue and track the bug in the code - propose a patch with tests and documentation
- no comment/noise filtering
I don't have such problem. Can you give an example of issue which contains many useless comments?
and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day
Sorry, I don't understand, maybe because I don't know what a wart is. -- If I understood correctly, you would like to list some specific issues like print() not flushing immediatly stdout if you ask to not write a newline (print "a", in Python 2 or print("a", end=" ") in Python 3). If I understood correctly, and if you want to improve Python, you should help the documentation project. Or if you can build a website listing such issues *and listing solutions* like calling sys.stdout.flush() or using print(flush=True) (Python 3.3+) for the print issue. A list of such issue without solution doesn't help anyone. Victor

Hello and happy New Year! On Sun, Dec 30, 2012 at 11:20:34PM +0100, Victor Stinner <victor.stinner@gmail.com> wrote:
If I understood correctly, you would like to list some specific issues like print() not flushing immediatly stdout if you ask to not write a newline (print "a", in Python 2 or print("a", end=" ") in Python 3). If I understood correctly, and if you want to improve Python, you should help the documentation project. Or if you can build a website listing such issues *and listing solutions* like calling sys.stdout.flush() or using print(flush=True) (Python 3.3+) for the print issue.
A list of such issue without solution doesn't help anyone.
I cannot say for Anatoly but for me warts are: -- things that don't exist where they should (but the core team object or they are hard to implement or something); -- things that exist where they shouldn't; they are hard to fix because removing them would break backward compatibility; -- things that are implemented in strange, inconsistent ways. A few examples: -- things that don't exist in the language where they should: anonymous code blocks (multiline lambdas); case (switch) statements; do/until loops; -- things that exist in the language where they shouldn't: else clause in 'for' loops (documentation doesn't help); -- things that don't exist in the stdlib where they should: asynchronous network libs (ftp/http/etc); GUI toolkit wrappers (GTK and/or Qt); SQL DB API drivers; SSL (key/certificate generation and parsing); restricted execution (remember rexec and Bastion?); -- things that exist in the stdlib where they shouldn't: tkinter (Tk is the rarest GUI toolkit in use), turtle; smtpd.py (it's a program, not a library); -- things that are implemented in strange, inconsistent ways: limited expression syntax in decorators (only attr access and calls); heapq (not object-oriented). Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Mon, 31 Dec 2012 04:00:12 +0400 Oleg Broytman <phd@phdru.name> wrote:
Hello and happy New Year!
On Sun, Dec 30, 2012 at 11:20:34PM +0100, Victor Stinner <victor.stinner@gmail.com> wrote:
If I understood correctly, you would like to list some specific issues like print() not flushing immediatly stdout if you ask to not write a newline (print "a", in Python 2 or print("a", end=" ") in Python 3). If I understood correctly, and if you want to improve Python, you should help the documentation project. Or if you can build a website listing such issues *and listing solutions* like calling sys.stdout.flush() or using print(flush=True) (Python 3.3+) for the print issue.
A list of such issue without solution doesn't help anyone.
I cannot say for Anatoly but for me warts are:
-- things that don't exist where they should (but the core team object or they are hard to implement or something); -- things that exist where they shouldn't; they are hard to fix because removing them would break backward compatibility; -- things that are implemented in strange, inconsistent ways.
A few examples: [snip]
The problem is you are listing examples which *in your opinion* are issues with Python. Other people would have different ideas of what is an issue and what is not. This can't be the right methodology if we want to write a piece of Python docs. Only things which are *well-known* annoyances can qualify. I also disagree that missing features are "warts"; they are just missing features, not something unpleasant that's difficult to get rid of. Regards Antoine.

On Wed, Jan 2, 2013 at 8:55 AM, Antoine Pitrou <solipsis@pitrou.net> wrote:
The problem is you are listing examples which *in your opinion* are issues with Python. Other people would have different ideas of what is an issue and what is not. This can't be the right methodology if we want to write a piece of Python docs. Only things which are *well-known* annoyances can qualify.
My understanding of a "Python wart" is that it's something that cannot be changed without readdressing some fundamental design. For example, Python has decided that indentation and line-endings are significant - that a logical statement ends at end-of-line. Python has further decided that line continuation characters are unnecessary inside parenthesized expressions. Resultant wart: Breaking a massive 'for' loop between its assignment list and its iterable list doesn't work, even though breaking it anywhere else does. (This question came up on python-list a little while ago.) Why should it be an error to break it here, but not there? Why can't I split it like this: for x,y,z in start_point, continuation_point, end_point : pass when it's perfectly legal to split it like this: for ( x,y,z ) in ( start_point, continuation_point, end_point ): pass Well, because you can't. It's a little odd what you can and can't do, until you understand the underlying system fairly well. It's something that's highly unlikely to change; one of the premises would have to be sacrificed (or at least modified) to achieve it. Something that could be changed if the devs had enough time is a tracker issue (or a "show me some code" issue - you want to complain, you can do the work to fix it). Something that could be changed, but would break backward compatibility is a prime candidate for __future__ and/or Python 4 (like the change of the division operator - that change introduced its own oddities, some of which may be warts, eg that int/int->float but sqrt(float) !-> complex). A wart is different from both of the above. ChrisA

On Jan 2, 8:16 am, Chris Angelico <ros...@gmail.com> wrote:
It's a little odd what you can and can't do, until you understand the underlying system fairly well. It's something that's highly unlikely to change; one of the premises would have to be sacrificed (or at least modified) to achieve it.
By this definition, though, every feature of Python that someone doesn't understand is a wart. For a new user, mutable default parameters is a wart, but once you understand Python's execution & object models, it's just the way the language is. Generally, I find "wart" means "something the user doesn't like about the language even if it makes internal sense".

On Wed, Jan 2, 2013 at 10:17 AM, alex23 <wuwei23@gmail.com> wrote:
On Jan 2, 8:16 am, Chris Angelico <ros...@gmail.com> wrote:
It's a little odd what you can and can't do, until you understand the underlying system fairly well. It's something that's highly unlikely to change; one of the premises would have to be sacrificed (or at least modified) to achieve it.
By this definition, though, every feature of Python that someone doesn't understand is a wart. For a new user, mutable default parameters is a wart, but once you understand Python's execution & object models, it's just the way the language is.
Generally, I find "wart" means "something the user doesn't like about the language even if it makes internal sense".
That's pretty much it, yeah. The warts of Python are the gotchas that need to be grokked before you can call yourself fluent in the language. Might feel as though the designers "got it wrong", or were making an arbitrary choice, but whatever it is, the language behaves that way and you have to get to know it. I agree that mutable defaults as a wart. PHP's scoping rules are simpler than Python's. A variable inside a function is local unless it's explicitly declared global; function names are global. (That's not the whole set of rules, but close enough for this argument.) Python, on the other hand, adds the oddity that a name referenced inside a function is global unless, somewhere in that function, it's assigned to. This is a Python wart that bites people (see the first question in http://toykeeper.net/warts/python/ for instance), but it's a consequence of putting "variables" and "functions" into a single namespace called "name bindings", plus the decision to not require variable declarations (C, for instance, has the same notion of "everything's a name", but instead of declaring globals, declares locals). Python's scoping rules are vastly superior to PHP's, but a bit more complicated, and may need a bit of explanation. (Incidentally, of all the warts listed in the page I linked above, two give a quick and easy error message, two have better ways of doing things (don't use +=, use append/extend), and only one is really a wart - mutable default values. Well, that and the behaviour of += on something in a tuple, but .extend dodges that one too.) Documenting these sorts of oddities is a good thing, as long as the underlying goal is one of new programmer education and not "hey you idiots who develop this language, here's all the things you did wrong". ChrisA

On 02/01/13 10:46, Chris Angelico wrote:
PHP's scoping rules are simpler than Python's. A variable inside a function is local unless it's explicitly declared global; function names are global. (That's not the whole set of rules, but close enough for this argument.) Python, on the other hand, adds the oddity that a name referenced inside a function is global unless, somewhere in that function, it's assigned to.
As given, comparing only treatment of locals and globals, I don't agree that this makes PHP's scoping rules simpler. PHP: if the name refers to a function: - the name is always global; otherwise: - the name is local unless explicitly declared global. Python: if the name is declared global: - the name is always global; otherwise: - the name is global unless implicitly declared local. (Implicitly local means "the name is bound to somewhere in the body of the function".) Of course, in reality Python includes further complexity: closures and nonlocal, neither of which are available in PHP due to the lack of local functions: http://gadgetopia.com/post/4089 PHP is simpler because it does less. -- Steven

On Wed, Jan 2, 2013 at 1:00 PM, Steven D'Aprano <steve@pearwood.info> wrote:
On 02/01/13 10:46, Chris Angelico wrote:
PHP's scoping rules are simpler than Python's. A variable inside a function is local unless it's explicitly declared global; function names are global. (That's not the whole set of rules, but close enough for this argument.) Python, on the other hand, adds the oddity that a name referenced inside a function is global unless, somewhere in that function, it's assigned to.
As given, comparing only treatment of locals and globals, I don't agree that this makes PHP's scoping rules simpler.
PHP: if the name refers to a function: - the name is always global;
Not quite. Python has the concept of "names" which might be bound to function objects, or might be bound to simple integers. PHP has two completely separate namespaces. <?php function foo() { echo "Function foo\n"; } $foo = 1; echo "foo: ".$foo."\n"; foo(); ?> The variable $foo and the function foo() don't collide, so this isn't a rule that governs where the name "foo" is looked up. Python has no such distinction, so code like this does exactly what you would expect: def foo(): pass bar = foo def quux(): bar() # No assignment in the function, so look for a global name 'bar'.
PHP is simpler because it does less.
Right. And the rules of a Turing tarpit like Ook are even simpler. Further proof that design warts are not, in and of themselves, necessarily bad. ChrisA

On Tue, Jan 01, 2013 at 03:17:34PM -0800, alex23 <wuwei23@gmail.com> wrote:
On Jan 2, 8:16 am, Chris Angelico <ros...@gmail.com> wrote:
It's a little odd what you can and can't do, until you understand the underlying system fairly well. It's something that's highly unlikely to change; one of the premises would have to be sacrificed (or at least modified) to achieve it.
By this definition, though, every feature of Python that someone doesn't understand is a wart. For a new user, mutable default parameters is a wart, but once you understand Python's execution & object models, it's just the way the language is.
Generally, I find "wart" means "something the user doesn't like about the language even if it makes internal sense".
What about warts that don't have internal sense? Mutable default parameters are just artifacts of the implementation. What is their "internal sense"? Paraphrasing Alan Cooper from "The Inmates are Running the Asylum": The phrase "experienced Python programmer" really means the person has been hurt so many times that the scar tissue is thick enough so he no longer feels the pain. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Wed, Jan 2, 2013 at 11:01 AM, Oleg Broytman <phd@phdru.name> wrote:
What about warts that don't have internal sense? Mutable default parameters are just artifacts of the implementation. What is their "internal sense"?
They let you use a function for something where you'd otherwise need to instantiate an object and play with it. Take caching, for instance: def name_lookup(name,cache={}): if name not in cache: cache[name] = some_lengthy_operation # prune the cache of old stuff to keep its size down return cache[name] You can ignore the default argument and pretend it's all magic, or you can explicitly run a separate cache: name_lookup("foo",{}) # easy way to say "bypass the cache" # Do a bunch of lookups that won't be in the main cache, and which would only pollute the main cache for later local_name_cache = {} [name_lookup(n,local_name_cache) for n in names] The other consideration here is of side effects. It's all very well to wave a magic wand and say that: def foo(x,y=[]): pass will create a unique list for each y, but what about: def foo(x,y=open("main.log","w")): pass or similar? Should it reopen the log every time? Should it reevaluate the expression? There's an easy way to spell it if you want that behaviour: def foo(x,y=None): if y is None: y=whatever_expression_you_want (or using object() if None is a legal arg). Whichever way mutable objects in default args are handled, there are going to be strangenesses. Therefore the best thing to do is (almost certainly) the simplest.
Paraphrasing Alan Cooper from "The Inmates are Running the Asylum": The phrase "experienced Python programmer" really means the person has been hurt so many times that the scar tissue is thick enough so he no longer feels the pain.
That applies to PHP, and possibly to C (though if you treat C as "all the power of assembly language, coupled with all the readability of assembly language", then it doesn't hurt nearly as much as if you try to treat it as a modern high level language). I'm not so sure it applies to Python. ChrisA

On Wed, Jan 02, 2013 at 11:34:47AM +1100, Chris Angelico <rosuav@gmail.com> wrote:
Whichever way mutable objects in default args are handled, there are going to be strangenesses. Therefore the best thing to do is (almost certainly) the simplest.
And the simples thing would be... let me think... forbid mutable defaults altogether? Or may be make them read-only? Current implementation is the simplest from the implementation point of view, but it requires additional documentation, especially for novice users. Is it really the simplest? Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Jan 2, 10:01 am, Oleg Broytman <p...@phdru.name> wrote:
Paraphrasing Alan Cooper from "The Inmates are Running the Asylum": The phrase "experienced Python programmer" really means the person has been hurt so many times that the scar tissue is thick enough so he no longer feels the pain.
To me, that's nonsense. The pain people are experiencing with "warts" like mutable defaults is entirely from trying to force Python to fit mental models they've constructed of other languages. The "internal sense" of mutable defaults is that everything is an object, and that functions arguments are declared at definition and not run-time. What you call "implementation artifact" I see as expected behaviour; any other implementation that didn't provide this wouldn't be Python in a number of fundamental ways.

On Tue, Jan 01, 2013 at 04:54:34PM -0800, alex23 <wuwei23@gmail.com> wrote:
The pain people are experiencing with "warts" like mutable defaults is entirely from trying to force Python to fit mental models they've constructed of other languages.
Yes. And preserving this mental model is important. There is a common mental model for similar imperative languages, common set of built-in types (chars, strings, integers, floats) and containers (arrays and matrices), common set of operations (addition is always spelled as infix 'plus' sign, logical AND -- as '&' or '&&'); there are functions with parameters -- usually written inside round parentheses; in object-oriented languages there are classes with inheritance... So it's perfectly natural when people using one language expect features found in other languages, and expect those features to work in similar ways. Sure, every particular language deviate from that common model. Often people can tolerate the deviation, sometimes they even praise it for some reasons. But when a deviation makes pain for too many developers -- there is certainly a problem. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Jan 2, 1:08 pm, Oleg Broytman <p...@phdru.name> wrote:
So it's perfectly natural when people using one language expect features found in other languages, and expect those features to work in similar ways.
I think anyone coming from one language to another expecting the latter to be just like the first is either an inexperienced or a bad programmer. There is no way you can make Python fit either the call by reference or call by value models, although people regularly try, and the attempt is always painful & torturous to watch. So already Python has "deviated" drastically from the base expectations of most (generally static-type lang'd) programmers. Is this a problem, or is this one of the fundamental design decisions of Python that makes it appealing? (For me, not having to deal with either of the call by reference or value models is one of the main reasons I prefer to work with Python.) The Lisp/Scheme community might take exception over claims that addition is "always" an infix operation as well.
Often people can tolerate the deviation, sometimes they even praise it for some reasons.
I don't really follow what you're trying to say here. I'm not "tolerating" any "deviations" in Python, I'm actively using it because I prefer its entire design. If anything, I'm choosing it _because_ it deviates from other language's approaches. What you seem to be advocating is that all languages be nothing more than syntactic sugar for the same underlying model. In that case, what advantage is there in having any language other than some baseline accepted one, like C?

On Wed, Jan 02, 2013 at 02:59:39AM -0800, alex23 <wuwei23@gmail.com> wrote:
What you seem to be advocating is that all languages be nothing more than syntactic sugar for the same underlying model.
Yes, von Neumann architecture.
In that case, what advantage is there in having any language other than some baseline accepted one, like C?
So now we know why C is still the most popular language. Other languages have their advantages, though. Their syntactic sugar is sweeter or have different tastes. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Wed, 2 Jan 2013 15:35:45 +0400 Oleg Broytman <phd@phdru.name> wrote:
On Wed, Jan 02, 2013 at 02:59:39AM -0800, alex23 <wuwei23@gmail.com> wrote:
What you seem to be advocating is that all languages be nothing more than syntactic sugar for the same underlying model. Yes, von Neumann architecture.
So all the differences between FORTRAN II, PROLOG and Python are syntactic sugar? I guess that makes preference in programming languages just a matter of taste. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/ Independent Software developer/SCM consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

On Wed, Jan 02, 2013 at 07:29:28AM -0600, Mike Meyer <mwm@mired.org> wrote:
On Wed, 2 Jan 2013 15:35:45 +0400 Oleg Broytman <phd@phdru.name> wrote:
On Wed, Jan 02, 2013 at 02:59:39AM -0800, alex23 <wuwei23@gmail.com> wrote:
What you seem to be advocating is that all languages be nothing more than syntactic sugar for the same underlying model. Yes, von Neumann architecture.
So all the differences between FORTRAN II, PROLOG and Python are syntactic sugar? I guess that makes preference in programming languages just a matter of taste.
In the original message I used the word "imperative". I am crawling off of the discussion to my cave. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

alex23 wrote:
There is no way you can make Python fit either the call by reference or call by value models, although people regularly try,
No, what happens is that different people have different ideas about what those terms mean, and they talk past each other. So they've become useless nowadays, and are best avoided altogether unless you want to start a month-long argument. -- Greg

alex23 wrote:
The "internal sense" of mutable defaults is that everything is an object, and that functions arguments are declared at definition and not run-time. What you call "implementation artifact" I see as expected behaviour; any other implementation that didn't provide this wouldn't be Python in a number of fundamental ways.
What the people who object to this behaviour are really complaining about is not that the default value is mutable, but that the default expression is not re-evaluated on every call. To me, the justification for this is clear: most of the time, evaluation on every call is not necessary, so doing it would be needlessly inefficient. For those cases where you need a fresh value each time, there is a straightforward way to get it. -- Greg

On Jan 2, 2:25 pm, Greg Ewing <greg.ew...@canterbury.ac.nz> wrote:
What the people who object to this behaviour are really complaining about is not that the default value is mutable, but that the default expression is not re-evaluated on every call.
Sorry, I should have said "mutable arguments" over "defaults", because the problem also bites people passing mutable objects to functions and expecting them to be copied.
To me, the justification for this is clear: most of the time, evaluation on every call is not necessary, so doing it would be needlessly inefficient. For those cases where you need a fresh value each time, there is a straightforward way to get it.
Absolutely agreed. I have deliberately used this behaviour on a number of occasions in ways that I believe makes my code clearer, so it always frustrates me to hear it described as a "wart".

On 02/01/13 11:01, Oleg Broytman wrote:
On Tue, Jan 01, 2013 at 03:17:34PM -0800, alex23<wuwei23@gmail.com> wrote:
On Jan 2, 8:16 am, Chris Angelico<ros...@gmail.com> wrote:
It's a little odd what you can and can't do, until you understand the underlying system fairly well. It's something that's highly unlikely to change; one of the premises would have to be sacrificed (or at least modified) to achieve it.
By this definition, though, every feature of Python that someone doesn't understand is a wart. For a new user, mutable default parameters is a wart, but once you understand Python's execution& object models, it's just the way the language is.
Generally, I find "wart" means "something the user doesn't like about the language even if it makes internal sense".
What about warts that don't have internal sense? Mutable default parameters are just artifacts of the implementation. What is their "internal sense"?
They are not artifacts of the implementation, they are a consequence of a deliberate design choice of Python. Default values in function definitions are set *once*, when the function object is created. Only the function body is run every time the function is called, not the function definition. So whether you do this: def ham(x=0): x += 1 return x or this: def spam(x=[]): x.append(1) return x the default value for both functions is a single object created once and reused every time you call the function. The consequences of this may be too subtle for beginners to predict, and that even experienced coders sometimes forget makes it a wart, but it makes perfect internal sense: * in Python, bindings ALWAYS occur when the code is executed; * in Python, "x=<whatever>" is a binding; * even inside a function definition; * def is a statement which is executed at run time, not something performed at compile time; * therefore, inside the statement "def spam(x=[]): ..." the binding x=[] occurs ONCE ONLY. The same list object is always used for the default value, not a different one each time. Early binding of function defaults should, in my opinion, be preferred over late binding because: * given early binding, it is clean to get late binding semantics with just one extra line. Everything you need remains encapsulated inside the function: def spam(x=None): if x is None: x = [] x.append(1) return x * given late binding, it is ugly to get early binding semantics, since it requires you to create a separate global "constant" for every argument needing an early binding: _SPAM_DEFAULT_ARG = [] # Don't touch this! def spam(x=None): if x is None: x = _SPAM_DEFAULT_ARG x.append(1) return x -- Steven

On Wed, Jan 2, 2013 at 11:55 AM, Steven D'Aprano <steve@pearwood.info> wrote:
* in Python, bindings ALWAYS occur when the code is executed;
* in Python, "x=<whatever>" is a binding;
* even inside a function definition;
Hey, that's a cool way of looking at it! I never thought of it that way. So default arguments are simply assigned to right back at function definition time, even though they're locals. Neat! ChrisA

On Wed, Jan 2, 2013 at 10:01 AM, Oleg Broytman <phd@phdru.name> wrote:
On Tue, Jan 01, 2013 at 03:17:34PM -0800, alex23 <wuwei23@gmail.com> wrote:
On Jan 2, 8:16 am, Chris Angelico <ros...@gmail.com> wrote:
It's a little odd what you can and can't do, until you understand the underlying system fairly well. It's something that's highly unlikely to change; one of the premises would have to be sacrificed (or at least modified) to achieve it.
By this definition, though, every feature of Python that someone doesn't understand is a wart. For a new user, mutable default parameters is a wart, but once you understand Python's execution & object models, it's just the way the language is.
Generally, I find "wart" means "something the user doesn't like about the language even if it makes internal sense".
FWIW, I prefer the term "traps for the unwary" over "warts", since it's less judgmental and better covers the goal of issues for people which can cause problems with learning the language. I highlight some of the examples related to the import system here: http://python-notes.boredomandlaziness.org/en/latest/python_concepts/import_...
What about warts that don't have internal sense? Mutable default parameters are just artifacts of the implementation. What is their "internal sense"?
Um, no. Mutable default arguments make perfect sense once you understand the difference between compile time, definition time and execution time for a function. Defaults are evaluated at definition time, thus they are necessarily shared across all invocations of the function. If you don't want them shared, you use a sentinel value like None to postpone the creation to execution time. They're a trap for the unwary, but not a wart. Else clauses on loops are arguably closer to qualifying as a genuine wart (see http://python-notes.boredomandlaziness.org/en/latest/python_concepts/break_e...), since they're not much shorter than the explicit sentinel value based alternative, and significantly less intuitive. However, because they exist, and people *will* encounter them in real world code, every beginner will eventually have to learn what they mean. The other complaint discussed in the thread, regarding "Why don't compound statement keywords and their trailing colon count as parentheses for purposes of ignoring line breaks?" has to do with a mix of implementation simplicity and error quality. Pairing up "if"/":", "with"/":", "for"/":" etc would certainly be possible, but may result in the infamous "missing semi-colon" style of C syntax error (or missing paren style of Lisp error), where the fault may be reported well away from the missing character, or with an error that is extremely hard for a beginner to translate into "you left out a character here". Given the likely detrimental effect on error quality, and the ability to use actual parens or backslashes for line continuation. The Design FAQ and Programming FAQ are intended to be the repository for answers to this kind of question. Addition of new questions and answers is handled like any other patch: via the tracker (and some of the existing answers could likely do with updates as well). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Wed, Jan 02, 2013 at 11:07:58AM +1000, Nick Coghlan <ncoghlan@gmail.com> wrote:
Mutable default arguments make perfect sense once you understand the difference between compile time, definition time and execution time for a function. Defaults are evaluated at definition time, thus they are necessarily shared across all invocations of the function.
I.e., users have to understand the current implementation. Mutable defaults are not a language design choice, they are dictated by the implementation, right? Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Wed, Jan 2, 2013 at 1:16 PM, Oleg Broytman <phd@phdru.name> wrote:
On Wed, Jan 02, 2013 at 11:07:58AM +1000, Nick Coghlan <ncoghlan@gmail.com> wrote:
Mutable default arguments make perfect sense once you understand the difference between compile time, definition time and execution time for a function. Defaults are evaluated at definition time, thus they are necessarily shared across all invocations of the function.
I.e., users have to understand the current implementation. Mutable defaults are not a language design choice, they are dictated by the implementation, right?
No, they're not an implementation accident, they're part of the language design. It's OK if you don't like them, but please stop claiming they're a CPython implementation artifact. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Wed, 2 Jan 2013 13:25:35 +1000 Nick Coghlan <ncoghlan@gmail.com> wrote:
On Wed, Jan 2, 2013 at 1:16 PM, Oleg Broytman <phd@phdru.name> wrote:
On Wed, Jan 02, 2013 at 11:07:58AM +1000, Nick Coghlan <ncoghlan@gmail.com> wrote:
Mutable default arguments make perfect sense once you understand the difference between compile time, definition time and execution time for a function. Defaults are evaluated at definition time, thus they are necessarily shared across all invocations of the function.
I.e., users have to understand the current implementation. Mutable defaults are not a language design choice, they are dictated by the implementation, right?
No, they're not an implementation accident, they're part of the language design. It's OK if you don't like them, but please stop claiming they're a CPython implementation artifact.
Let's call them a compromise then, but calling them a language feature sounds delusional. I can't remember ever taking advantage of the fact that mutable default arguments are shared accross function invocations. Regards Antoine.

On Wed, Jan 2, 2013 at 6:29 PM, Antoine Pitrou <solipsis@pitrou.net> wrote:
Let's call them a compromise then, but calling them a language feature sounds delusional. I can't remember ever taking advantage of the fact that mutable default arguments are shared accross function invocations.
One common use is caching, as I mentioned earlier (with a contrived example). Another huge benefit is efficiency - construct a heavy object once and keep using it. There are others. It's a feature that can bite people, but no less a feature for that. ChrisA

On 2 January 2013 08:12, Chris Angelico <rosuav@gmail.com> wrote:
On Wed, Jan 2, 2013 at 6:29 PM, Antoine Pitrou <solipsis@pitrou.net> wrote:
Let's call them a compromise then, but calling them a language feature sounds delusional. I can't remember ever taking advantage of the fact that mutable default arguments are shared accross function invocations.
One common use is caching, as I mentioned earlier (with a contrived example). Another huge benefit is efficiency - construct a heavy object once and keep using it. There are others.
It's a feature that can bite people, but no less a feature for that.
A further (and important) use case is introspection. If default values were only added at call time (rather than definition time) then you couldn't introspect the default value - so documentation tools (and other tools) couldn't have access to them. Added to which, "evaluation at call time" has its own unexpected and weird behaviour. Consider: x = 3 def fun(a=x): pass del x With evaluation at call time this code fails - and indeed any *re-binding* of x in the definition scope (at any subsequent time - possibly far removed from the function definition) affects the function. So default values being bound at definition times have advantages for efficiency and introspection, they have use cases for caching, and it removes some unexpected behaviour. It's definitely a language feature. All the best, Michael
ChrisA _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- http://www.voidspace.org.uk/ May you do good and not evil May you find forgiveness for yourself and forgive others May you share freely, never taking more than you give. -- the sqlite blessing http://www.sqlite.org/different.html

On 02/01/13 18:29, Antoine Pitrou wrote:
On Wed, 2 Jan 2013 13:25:35 +1000 Nick Coghlan<ncoghlan@gmail.com> wrote:
On Wed, Jan 2, 2013 at 1:16 PM, Oleg Broytman<phd@phdru.name> wrote:
On Wed, Jan 02, 2013 at 11:07:58AM +1000, Nick Coghlan<ncoghlan@gmail.com> wrote:
Mutable default arguments make perfect sense once you understand the difference between compile time, definition time and execution time for a function. Defaults are evaluated at definition time, thus they are necessarily shared across all invocations of the function.
I.e., users have to understand the current implementation. Mutable defaults are not a language design choice, they are dictated by the implementation, right?
No, they're not an implementation accident, they're part of the language design. It's OK if you don't like them, but please stop claiming they're a CPython implementation artifact.
Let's call them a compromise then, but calling them a language feature sounds delusional. I can't remember ever taking advantage of the fact that mutable default arguments are shared accross function invocations.
I've never taken advantage of multiprocessing. Does that mean that it is "delusional" to call multiprocessing a feature? On the other hand, I have made use of early binding of function defaults, and consider it a good feature of the language. Early binding is not just for mutable defaults. -- Steven

Le Wed, 02 Jan 2013 20:31:54 +1100, Steven D'Aprano <steve@pearwood.info> a écrit :
I.e., users have to understand the current implementation. Mutable defaults are not a language design choice, they are dictated by the implementation, right?
No, they're not an implementation accident, they're part of the language design. It's OK if you don't like them, but please stop claiming they're a CPython implementation artifact.
Let's call them a compromise then, but calling them a language feature sounds delusional. I can't remember ever taking advantage of the fact that mutable default arguments are shared accross function invocations.
I've never taken advantage of multiprocessing. Does that mean that it is "delusional" to call multiprocessing a feature?
multiprocessing fills a definite use case (and quite an important one). Early binding of function arguments fills no use case that cannot also be filled using a private global, a closure, or a class or function attribute; at best it only saves one or two lines of typing. Regards Antoine.

On Jan 2, 5:29 pm, Antoine Pitrou <solip...@pitrou.net> wrote:
Let's call them a compromise then, but calling them a language feature sounds delusional. I can't remember ever taking advantage of the fact that mutable default arguments are shared accross function invocations.
I'd say it's slightly more delusional to believe that if _you_ haven't used a language feature, that it's not a "feature".

RE:
I can't remember ever taking advantage of the fact that mutable default arguments are shared accross function invocations.
Can you remember taking advantage of the fact Python is logical, consistent, and elegant? I tend to think its lack of syntactic sugar and exceptions set it apart. Although there are sometimes things that could bite you, there's a lot of value in having those things be perfectly predictable, like having default argument values evaluated once, when the function declaration is evaluated. To do it any other way would introduce an unnecessary "except when" into the explanation of Python. Shane Green www.umbrellacode.com 805-452-9666 | shane@umbrellacode.com On Jan 2, 2013, at 3:08 AM, alex23 <wuwei23@gmail.com> wrote:
On Jan 2, 5:29 pm, Antoine Pitrou <solip...@pitrou.net> wrote:
Let's call them a compromise then, but calling them a language feature sounds delusional. I can't remember ever taking advantage of the fact that mutable default arguments are shared accross function invocations.
I'd say it's slightly more delusional to believe that if _you_ haven't used a language feature, that it's not a "feature". _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Wed, Jan 2, 2013 at 12:07 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
FWIW, I prefer the term "traps for the unwary" over "warts", since it's less judgmental and better covers the goal of issues for people which can cause problems with learning the language.
Sure. I prefer a shorter keyword-like name, but I think we're talking about the same thing here. ChrisA

On 02/01/13 15:27, Chris Angelico wrote:
On Wed, Jan 2, 2013 at 12:07 PM, Nick Coghlan<ncoghlan@gmail.com> wrote:
FWIW, I prefer the term "traps for the unwary" over "warts", since it's less judgmental and better covers the goal of issues for people which can cause problems with learning the language.
Sure. I prefer a shorter keyword-like name, but I think we're talking about the same thing here.
"Gotcha". Actually I prefer to distinguish between gotchas and warts. A gotcha is something that makes sense and even has a use, but can still surprise those who aren't expecting it. (E.g. mutable defaults.) A wart is something that has no use, but can't (easily, or at all) be removed. Example: t = (None, [], None) t[1] += [0] Even though the list is successfully modified, the operation still fails with an exception. -- Steven

Nick Coghlan <ncoghlan@gmail.com> writes:
FWIW, I prefer the term "traps for the unwary" over "warts", since it's less judgmental and better covers the goal of issues for people which can cause problems with learning the language.
I limit my use of “wart” to traps for the unwary which are acknowledged by most core developers to have been a sub-optimal design decision. They are things one needs to know about Python, the language, which if the designers had their druthers would not have been such a trap – but now we're stuck with them for backward compatibility or lack of a feasible better design, etc. In other words, I don't call it a “wart” unless the core developers agree with me that it's a wart :-) -- \ “There is no reason anyone would want a computer in their | `\ home.” —Ken Olson, president, chairman and founder of Digital | _o__) Equipment Corp., 1977 | Ben Finney

On 1/1/2013 7:01 PM, Oleg Broytman wrote:
What about warts that don't have internal sense? Mutable default parameters are just artifacts of the implementation. What is their "internal sense"?
This has been discussed (asked and answered) several times on python-list. -- Terry Jan Reedy

On 02/01/13 09:16, Chris Angelico wrote:
My understanding of a "Python wart" is that it's something that cannot be changed without readdressing some fundamental design. For example, Python has decided that indentation and line-endings are significant - that a logical statement ends at end-of-line. Python has further decided that line continuation characters are unnecessary inside parenthesized expressions. Resultant wart: Breaking a massive 'for' loop between its assignment list and its iterable list doesn't work, even though breaking it anywhere else does.
A truly poor example. You can't break a for loop between its assignment and iterable for the same reason you can't break any other statement at an arbitrary place. That's not how Python does things: statements must be on a single logical line.
(This question came up on python-list a little while ago.) Why should it be an error to break it here, but not there? Why can't I split it like this:
for x,y,z in start_point, continuation_point, end_point : pass
As you say above, logical statements end at end-of-line. There is an end-of-line following "for x,y,z in". Why would anyone think that you should be able to split the statement there? - is there a line-continuation that would let you continue over multiple physical lines? no - is there a parenthesized expression that would let you continue over multiple physical lines? no None of the conditions for splitting statements over multiple physical lines apply, and so the standard rule applies: statements end at end-of-line. This is not a wart any more than the inability to write: y = x + 1; is a wart. Maybe you're used to being able to do that in some (but not all) semi-colon languages, but they are not Python, any more than Python is Forth where you might be used to writing: x 1 + y ! To some degree warts are in the eye of the beholder, but failure of Python to be "just like language Foo" is not a wart.
when it's perfectly legal to split it like this:
for ( x,y,z ) in ( start_point, continuation_point, end_point ): pass
Well, because you can't. It's a little odd what you can and can't do,
"Why can't I drive straight through red lights, when I'm allowed to drive through green lights? That's a little odd!" No it is not. It is a fundamental aspect of Python's syntax.
until you understand the underlying system fairly well. It's something that's highly unlikely to change; one of the premises would have to be sacrificed (or at least modified) to achieve it.
Something that could be changed if the devs had enough time is a tracker issue (or a "show me some code" issue - you want to complain, you can do the work to fix it). Something that could be changed, but would break backward compatibility is a prime candidate for __future__ and/or Python 4 (like the change of the division operator - that change introduced its own oddities, some of which may be warts, eg that int/int->float but sqrt(float) !-> complex).
Are you talking about math.sqrt or cmath.sqrt or some other sqrt? In general, Python 3 now extends float to complex under regular arithmetic: py> (-100.0)**0.5 (6.123031769111886e-16+10j) math.sqrt(-100.0) on the other hand continues to raise, because the math module is by design limited to producing real-values. cmath.sqrt(-100.0) continues to give a complex result, again by design. -- Steven

On Wed, Jan 2, 2013 at 10:57 AM, Steven D'Aprano <steve@pearwood.info> wrote:
You can't break a for loop between its assignment and iterable for the same reason you can't break any other statement at an arbitrary place. That's not how Python does things: statements must be on a single logical line.
This is not a wart any more than the inability to write:
y = x + 1;
is a wart. Maybe you're used to being able to do that in some (but not all) semi-colon languages)
To some degree warts are in the eye of the beholder, but failure of Python to be "just like language Foo" is not a wart.
Of course. I'm just trying to find examples that have actually come up on python-list, rather than contriving my own. As per my definition of wart as given above, these are NOT things that need to be fixed - just things that need to be understood. Rule: One Python statement must be on one line. (This is the bit where Python differs from, say, C.) Modifying rule: Python statements can be broken across multiple lines, given certain conditions. Wart: There are other conditions that, though they seem superficially similar to the legal ones, don't make for valid split points. Even though a human might say that it's obvious and unambiguous that the statement continues, the rules don't allow it.
eg int/int->float but sqrt(float) !-> complex).
Are you talking about math.sqrt or cmath.sqrt or some other sqrt?
In general, Python 3 now extends float to complex under regular arithmetic:
py> (-100.0)**0.5 (6.123031769111886e-16+10j)
math.sqrt(-100.0) on the other hand continues to raise, because the math module is by design limited to producing real-values. cmath.sqrt(-100.0) continues to give a complex result, again by design.
Hmm, I was doing that one from memory. Since the ** operator happily returns complex, it was probably math.sqrt that was in question. I withdraw this one; the operators are consistent amongst themselves, all will extend to the "next type up" if necessary. (Or at least, this pair do. There might be a wart elsewhere, but this ain't it.) ChrisA

Hi! On Tue, Jan 01, 2013 at 10:55:05PM +0100, Antoine Pitrou <solipsis@pitrou.net> wrote:
On Mon, 31 Dec 2012 04:00:12 +0400 Oleg Broytman <phd@phdru.name> wrote:
On Sun, Dec 30, 2012 at 11:20:34PM +0100, Victor Stinner <victor.stinner@gmail.com> wrote:
If I understood correctly, you would like to list some specific issues like print() not flushing immediatly stdout if you ask to not write a newline (print "a", in Python 2 or print("a", end=" ") in Python 3). If I understood correctly, and if you want to improve Python, you should help the documentation project. Or if you can build a website listing such issues *and listing solutions*
-- things that don't exist where they should (but the core team object or they are hard to implement or something); -- things that exist where they shouldn't; they are hard to fix because removing them would break backward compatibility; -- things that are implemented in strange, inconsistent ways.
A few examples: [snip]
The problem is you are listing examples which *in your opinion* are issues with Python. Other people would have different ideas of what is an issue and what is not. This can't be the right methodology if we want to write a piece of Python docs.
Absolutely not. I collected the list of examples in reply to a question "what are warts and why one cannot just document solutions?" I hope I managed to show that warts are built (or unbuilt, so to say) so deep in Python and the stdlib design it's impossible to fix them with code or documentation. Fixing them require major design changes.
Only things which are *well-known* annoyances can qualify.
Well, some warts are quite well-known. My counter overflows when I try to count how many times anonymous code blocks have been proposed and rejected. IIRC Mr. van Rossum admitted that for/else was a design mistake. One wart is being worked on right now: async libs redesign.
I also disagree that missing features are "warts"; they are just missing features, not something unpleasant that's difficult to get rid of.
Some of those missing features are near to impossible to get rid of. The idea of anonymous code blocks is rejected constantly so no one would dare to create a patch. As for their unpleasantness -- it's in the eye of the beholder, of course. I'm not going to fight tooth and nail for my vision. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Wed, Jan 2, 2013 at 9:49 AM, Oleg Broytman <phd@phdru.name> wrote:
I also disagree that missing features are "warts"; they are just missing features, not something unpleasant that's difficult to get rid of.
Some of those missing features are near to impossible to get rid of. The idea of anonymous code blocks is rejected constantly so no one would dare to create a patch. As for their unpleasantness -- it's in the eye of the beholder, of course. I'm not going to fight tooth and nail for my vision.
This is why the "wart" term in an inherently bad choice: it polarises disputes, and creates arguments where none needs to exist. If you instead split them into "hard problems" and "traps for the unwary", it's easier to have a more rational discussion and come up with a shared list. Interoperable asynchronous IO is an inherently hard problem - Guido's probably the only person in the world capable of gathering sufficient interest from the right people to come up with a solution that the existing async frameworks will be willing to support. Packaging and software distribution is an inherently hard problem (all current packaging systems suck, with even the best of them being either language or platform specific), made even harder in the Python case by the presence of an existing 90% solution in setuptools. Anonymous blocks in a language with a strong statement/expression dichotomy is an inherently hard problem (hence the existence of not one but two deferred PEPs on the topic: PEP 403 and 3150) Switch statements in a language without compile time named constants are an inherently hard problem, and some of the demand for this construct is reduced due to the availability of higher-order programming features (i.e. dynamic dispatch to stored callables) (hence the rejected PEPs 275 and 3103) A do/until loop has the problem of coming up with an elegant syntax that is demonstrably superior to while/if/break (hence the deferred PEP 315) The design space for things that Python *could* do is unimaginably vast. The number of changes we can make that won't have the net effect of making the language worse is vanishingly small by comparison. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Oleg Broytman <phd@phdru.name> wrote:
Well, some warts are quite well-known. My counter overflows when I try to count how many times anonymous code blocks have been proposed and rejected. IIRC Mr. van Rossum admitted that for/else was a design mistake.
As I recall it, that wasn't because they were a bad idea per se, but because the minor upside they provide isn't worth the confusion they create for newcomers. But since we're referencing the BDFL, IIRC he isn't against anonymous code blocks (and I believe that is by far the most proposed/requested feature) per se. The proposals all seem to fail in one of three ways: 1) embedding them in expressions when indentation denotes block structure just invites unreadable code; 2) putting them in a separate block requires a name, and we already have def if the programmer provides it; or 3) providing an implicit name for a separate block isn't enough of a win to violate "explicit is better than implicit". There have been some let/where type suggestions, but those are more about namespaces than anonymous code blocks. -- Sent from my Android tablet with K-9 Mail. Please excuse my swyping.

On 02/01/13 17:04, Mike Meyer wrote:
Oleg Broytman<phd@phdru.name> wrote:
Well, some warts are quite well-known. My counter overflows when I try to count how many times anonymous code blocks have been proposed and rejected. IIRC Mr. van Rossum admitted that for/else was a design mistake.
As I recall it, that wasn't because they were a bad idea per se, but because the minor upside they provide isn't worth the confusion they create for newcomers.
There would be a lot less confusion if they weren't called "else". Even now, I have to explicitly remind myself that the else block doesn't run if the for loop is empty, but *after* the for block. # Python 4000 proposal: for x in seq: ... then: # this is skipped by a break else: # this runs only if seq is empty -- Steven

On Wed, Jan 2, 2013 at 8:27 PM, Steven D'Aprano <steve@pearwood.info> wrote:
There would be a lot less confusion if they weren't called "else". Even now, I have to explicitly remind myself that the else block doesn't run if the for loop is empty, but *after* the for block.
# Python 4000 proposal: for x in seq: ... then: # this is skipped by a break else: # this runs only if seq is empty
Calling it "else" makes perfect sense if you're searching for something. for x in lst: if x.is_what_we_want(): break else: x=thing() lst.append(x) ChrisA

On 02/01/13 20:37, Chris Angelico wrote:
On Wed, Jan 2, 2013 at 8:27 PM, Steven D'Aprano<steve@pearwood.info> wrote:
There would be a lot less confusion if they weren't called "else". Even now, I have to explicitly remind myself that the else block doesn't run if the for loop is empty, but *after* the for block.
# Python 4000 proposal: for x in seq: ... then: # this is skipped by a break else: # this runs only if seq is empty
Calling it "else" makes perfect sense if you're searching for something.
for x in lst: if x.is_what_we_want(): break else: x=thing() lst.append(x)
Not really. The "else" doesn't match the "if", it matches the "for". That's the problem really. Besides, your example is insufficiently general. You can't assume that the "else" immediately follows the "if", let alone the correct if. for x in lst: if x.is_what_we_want(): break do_something() and_another_thing() if today is Tuesday: print("we must be in Belgium") else: x = thing() lst.append(x) So at best it makes *imperfect* sense, sometimes. -- Steven

On Wed, Jan 2, 2013 at 8:49 PM, Steven D'Aprano <steve@pearwood.info> wrote:
On 02/01/13 20:37, Chris Angelico wrote:
Calling it "else" makes perfect sense if you're searching for something.
for x in lst: if x.is_what_we_want(): break else: x=thing() lst.append(x)
Not really. The "else" doesn't match the "if", it matches the "for". That's the problem really. Besides, your example is insufficiently general. You can't assume that the "else" immediately follows the "if", let alone the correct if.
for x in lst: if x.is_what_we_want(): break do_something() and_another_thing() if today is Tuesday: print("we must be in Belgium") else: x = thing() lst.append(x)
So at best it makes *imperfect* sense, sometimes.
Thinking functionally, the for loop is searching for an element in the list. It'll either find something (and break) or not find anything (and raise StopIteration). If it finds something, do stuff and break, else do other stuff. The "else" of the logic corresponds to the "else:" clause. Not saying it's always right, but it does at least make some sense in that particular application, which is a reasonably common one. I've coded exactly that logic in C++, using a goto to do a "break and skip the else clause" (with a comment to the effect that I'd rather be writing Python...). ChrisA

On Wed, 2 Jan 2013 03:49:16 +0400 Oleg Broytman <phd@phdru.name> wrote:
The problem is you are listing examples which *in your opinion* are issues with Python. Other people would have different ideas of what is an issue and what is not. This can't be the right methodology if we want to write a piece of Python docs.
Absolutely not. I collected the list of examples in reply to a question "what are warts and why one cannot just document solutions?" I hope I managed to show that warts are built (or unbuilt, so to say) so deep in Python and the stdlib design it's impossible to fix them with code or documentation.
Now please stop FUDding. It is outrageous to claim that missing features are "impossible to fix with code or documentation". If you come with a reasonable syntax for anonymous code blocks (and have a patch to back that up), I'm sure they would be accepted. If you can't or don't want to, then you can't accuse our community of being biased against anonymous code blocks. Regards Antoine.

On 12/30/2012 7:00 PM, Oleg Broytman wrote:
A list of such issue without solution doesn't help anyone.
I cannot say for Anatoly but for me warts are:
Another list that to me is off-topic for this list. Go to python-list, which is meant for such things. If you have a (one) specific idea for improving (c)python, that is not an energy sucking rehash of rejected ideas, then post is. -- Terry Jan Reedy

I'm a young developer (22) that is aspiring to contribute to the python language and I think another perspective could help the conversation. What I believe Anataoly is asking for, albeit phrased in a different manner, is the ability to clearly see what the core issues/needs are in the language. I've been able to discern through time, and the python mailing lists, that packaging, multitasking, and timezone support are areas that could use help. Sure, 'wart' is subjective, but I believe the point made in between the lines is valid. Is there a place that holds the key improvements that the python language needs, so that we can work to it better? If that's the bug tracker, is there a method already in place that signals areas that need improvements or fixes? [I know that there are severity levels, etc :)] FWIW I've joined the python-mentor list, have read most of the devguide, and lurked on the bug tracker; I still feel like there is tons of context that I'm missing, which has me chasing PEPs constantly - So I'm definitely able to resonate the with this thread. I apologize if I'm waay off target. _Ryan
Victor Stinner <mailto:victor.stinner@gmail.com> December 30, 2012 4:20 PM 2012/12/26 anatoly techtonik<techtonik@gmail.com>:
I am thinking about [python-wart] on SO.
I'm not sure that StackOverflow is the best place for such project. (Note: please avoid abreviation, not all people know this website.)
There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
Sorry, but what is a wart in Python?
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues
When an issue is closed with "won't fix", "works for me", "invalid" or something like this, a comment always explain why. If you don't understand or such comment is missing, you can ask for more information.
If you don't agree, the bug tracker is maybe not the right place for such discussion. The python-ideas mailing list is maybe a better place :-)
Sometimes, the best thing to do is to propose a patch to enhance the documentation.
- no way to edit description to make it more clear
You can add comments, it's almost the same.
- no voting/stars to percieve how important is this issue
Votes are a trap. It's not how Python is developed. Python core developers are not paid to work on Python, and so work only on issues which interest them.
I don't think that votes would help to fix an issue.
If you want an issue to be closed: - ensure that someone else reproduced it: if not, provide more information - help to analyze the issue and track the bug in the code - propose a patch with tests and documentation
- no comment/noise filtering
I don't have such problem. Can you give an example of issue which contains many useless comments?
and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day
Sorry, I don't understand, maybe because I don't know what a wart is.
--
If I understood correctly, you would like to list some specific issues like print() not flushing immediatly stdout if you ask to not write a newline (print "a", in Python 2 or print("a", end=" ") in Python 3). If I understood correctly, and if you want to improve Python, you should help the documentation project. Or if you can build a website listing such issues *and listing solutions* like calling sys.stdout.flush() or using print(flush=True) (Python 3.3+) for the print issue.
A list of such issue without solution doesn't help anyone.
Victor _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas anatoly techtonik <mailto:techtonik@gmail.com> December 25, 2012 6:10 PM I am thinking about [python-wart] on SO. There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues - no way to edit description to make it more clear - no voting/stars to percieve how important is this issue - no comment/noise filtering and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day
SO at least allows: + voting + community wiki edits + useful comment upvoting + sorted lists + user editable tags (adding new warts is easy)
This post is a result of facing with numerous locals/settrace/exec issues that are closed on tracker. I also have my own list of other issues (logging/subprocess) at GC project, which I might be unable to maintain in future. There is also some undocumented stuff (subprocess deadlocks) that I'm investigating, but don't have time for a write-up. So I'd rather move this somewhere where it could be updated. -- anatoly t. _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Sun, 30 Dec 2012 18:06:08 -0600 Ryan Macy <ryan@hackery.io> wrote:
I'm a young developer (22) that is aspiring to contribute to the python language and I think another perspective could help the conversation. What I believe Anataoly is asking for, albeit phrased in a different manner, is the ability to clearly see what the core issues/needs are in the language. I've been able to discern through time, and the python mailing lists, that packaging, multitasking, and timezone support are areas that could use help. Sure, 'wart' is subjective, but I believe the point made in between the lines is valid.
I'm not sure Anatoly is talking about things that have to be improved, rather than things which are lacking (in his opinion, or in the general opinion) and which nevertheless won't be fixed for various reasons. These things would have a place in the FAQ, if Anatoly wants to contribute documentation patches: http://docs.python.org/dev/faq/index.html Regards Antoine.

Ryan Macy writes:
I'm a young developer (22) that is aspiring to contribute to the python language and I think another perspective could help the conversation. What I believe Anataoly is asking for, albeit phrased in a different manner, is the ability to clearly see what the core issues/needs are in the language.
Good luck on that. Just as you write, it is in fact a human ability, not a collection of facts that can be published. AFAICS, the core issues are what block core developers from getting applied work done. (Or cause them to stumble in process, for that matter.) The reason for this, based on introspection and watching a few Nobel prizewinners work, is that people working at that level have an uncanny ability to *ask* the right questions, and do so recursively. Of course they're usually really fast and accurate at answering them, too, but answering smallish research questions is an upperclass undergrad student[1] skill. The knack for filtering out inessential questions and zeroing in on the bottleneck is what makes them great. The flip side, of course, is that because a core developer is blocked, he or she is working on it. So maybe you won't get a chance to make a big contribution there -- it will be solved by the time you figure out what to do. ;-)
Is there a place that holds the key improvements that the python language needs, so that we can work to it better? If that's the bug tracker,
Bingo!
is there a method already in place that signals areas that need improvements or fixes? [I know that there are severity levels, etc :)]
The problem is that "need" is mostly subjective. In Python there are several objectifiable criteria, encoded in the venerable Zen of Python, and more recently in the thread answering Ned Batchelder's question on what makes a good change to the stdlib. But if you look at them, I suspect that you'll come to the same conclusion that I do: need is defined by what at least some programmers often want to do and are likely to do imperfectly, even if they do it repeatedly. That's "need", and it's dynamic, only imperfectly correlated with the state of the language. The only reliable measure of need is what somebody is willing to provide a high-quality patch for. Just Do It! :-)
[There is] context that I'm missing, which has me chasing PEPs constantly
Well, when you catch one, take it out to lunch. Spend some time in conversation with it. Figure out what the person who wrote it was thinking, and why. :-)
- So I'm definitely able to resonate the with this thread.
I apologize if I'm waay off target.
Not at all. I just don't think there's a royal road to core contribution. The flip side of that is that as far as defining "need" goes, what you perceive as important is no less important than what Guido does. It's just that he has a proven knack for picking questions that others value too, and for giving answers that untangle the language, as well as solving a practical problem. But that doesn't mean you should work on what Guido thinks is important just because he thinks it's important. If you resonate with the need he feels, then you will find ways to contribute to resolving it. I haven't seen the word "channel" around here recently, but trying to channel the core developers on problems you encounter is a good way to get started. Try to anticipate what they'll say if you post (or in response to somebody else's post that interests you). When conversing with a PEP, try to figure out what it's going to propose as the solution before you read it. Try to figure out what problems it will need to solve to achieve its goal, etc. Steve

I consider Anatoly's post to be off-topic, obnoxious, and best ignored. On 12/30/2012 5:20 PM, Victor Stinner wrote: I am only responding because Eli and then Victor responded, largely repeating things that have been said before (and ignored) on many of the same issues.
2012/12/26 anatoly techtonik <techtonik@gmail.com>:
I am thinking about [python-wart] on SO.
The purpose of python-ideas is to discuss possible ideas for improving future versions of Python and the reference CPython implementation, including its included documentation. Announcements of independent personal activities are off topic. Announcements of thoughts about such activities are, to me, even more so. I have lots of thoughts about things I *might* do, and I am sure many others do too. Should we all post them here? I think not. I am actually working on, not just thinking about, a book that showcases many of the positive features of Python. But I do not think that an announcement post here is particularly on-topic. As for 'obnoxious', this is not just a post about thoughts, but of thoughts to abuse another forum to trash python, and a trashy justification for doing so.
There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
There is, of course, a tracker with, at the moment,3771 open issues. That is already too many. Repeatly regurgitating closed issue is an obnoxious distraction.
Sorry, but what is a wart in Python?
A Python behavior that Anatoly does not like and that the CPython developers cannot, will not*, or have not yet# changed. By extension, our disliked-by-him actions are also warts. This ego-centric view is more of 'obnoxious'. * Perhaps because we consider the whole community, not just one person. # Perhaps because of ignorance or lack of interest. Berating us for not doing something that he will also not do (write a patch) is more of 'obnoxious'.
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues
One can easily search the tracker for closed issues with any particular resolution. One can even limit the search for such issue with 'techtonik' on the nosy list. Results: 'rejected' 17 'invalid' 17 'won't fix' 10 'works for me' 17 The numbers are smaller if 'techtonik' is entered instead in the creator box. This is the core list of issues Anatoly would consider 'lost warts'. They are not lost, just not prominently displayed to the world in the way he would like. Spreading disinformation is more of 'obnoxious'.
- no way to edit description to make it more clear
There is no description field. The title of an issue and other descriptive headers can be edited and often are. There is an audit trail of changes. The description of a issue can be and sometimes is re-stated by the original author or others in successive messages. As a matter of audit trail policy, messages cannot be edited. They can be deleted from an issue (and that fact noted, and by who) but not (normally, anyway) from the database. So, more disinformation. Calling a disagreement over policy a 'wart' is disengenous.
- no voting/stars to percieve how important is this issue
Proposed and rejected before. Again: the devs don't do what Anatoly wants, its a wart. -- Terry Jan Reedy

Terry Reedy writes:
I consider Anatoly's post to be off-topic, obnoxious, and best ignored.
On 12/30/2012 5:20 PM, Victor Stinner wrote:
I am only responding because Eli and then Victor responded, largely repeating things that have been said before (and ignored) on many of the same issues.
+1
2012/12/26 anatoly techtonik <techtonik@gmail.com>:
I am thinking about [python-wart] on SO.
The purpose of python-ideas is to discuss possible ideas for improving future versions of Python and the reference CPython implementation, including its included documentation.
I think it would be fair to s/included//. See the doc site search engine thread, which nobody (including you) seems to think off-topic.
Announcements of independent personal activities are off topic.
Not at all. Announcing a PyPI project and requesting testing for potential stdlib inclusion, for example. Doesn't fit exactly, but what's the preferred venue?
Announcements of thoughts about such activities are, to me, even more so.
It's the lack of any pre-posting filter whatsoever, combined with a lack of patches, that leads me to ignore Anatoly. This is more of the same. Nevertheless, a desire for a list of "important unsolved problems" is common (cf Ryan's post).
Sorry, but what is a wart in Python?
A Python behavior that Anatoly does not like and that the CPython developers cannot, will not*, or have not yet# changed. By extension, our disliked-by-him actions are also warts.
That is apparently Anatoly's operational definition, yes. However, it's easy to define conceptually. A wart in Python is an un-Pythonic functionality, or an un-Pythonic implementation of functionality. The print statement was a wart. It was an interesting idea, like syntactic indentation. The former didn't work for Python, the latter did and still does.[1] That makes it clear to me why Anatoly's proposal is perverse. The word "Pythonic" itself cannot be defined by stars on a Roundup issue or user posts to StackOverflow. Ultimately it's defined by Guido, I suppose, but by now many developers have been shown to have an excellent sense, sufficient to get Guido to change his mind on occasion. It is not, however, a matter for democratic decision. The word "wart" itself is useful, when used by those know what "Pythonic" means. It's a warning: you will break your teeth if you just try to bite it off. So it's not very useful in guiding the work of new developers, because the bar is high and the benefits small. Most warts in Python 3 (and there are far fewer than Anatoly seems to think) will have to wait for Python 4, absent solutions of true genius. Footnotes: [1] As a way of tweaking the nose of paren-lovers, if nothing else.

We already have a collection of "warts" or "gotchas": http://docs.python.org/3/faq/design.html#why-must-dictionary-keys-be-immutab... http://docs.python.org/3/faq/design.html#why-doesn-t-list-sort-return-the-so... http://docs.python.org/3/faq/design.html#why-are-default-values-shared-betwe... http://docs.python.org/3/faq/design.html#why-can-t-raw-strings-r-strings-end... and so on. Note that that document is probably extremely out of date, but there is an existing place for them. On Tue, Dec 25, 2012 at 7:10 PM, anatoly techtonik <techtonik@gmail.com>wrote:
I am thinking about [python-wart] on SO. There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues - no way to edit description to make it more clear - no voting/stars to percieve how important is this issue - no comment/noise filtering and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day
SO at least allows: + voting + community wiki edits + useful comment upvoting + sorted lists + user editable tags (adding new warts is easy)
This post is a result of facing with numerous locals/settrace/exec issues that are closed on tracker. I also have my own list of other issues (logging/subprocess) at GC project, which I might be unable to maintain in future. There is also some undocumented stuff (subprocess deadlocks) that I'm investigating, but don't have time for a write-up. So I'd rather move this somewhere where it could be updated. -- anatoly t.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- Jasper

On Tue, Dec 25, 2012 at 7:10 PM, anatoly techtonik <techtonik@gmail.com> wrote:
I am thinking about [python-wart] on SO. There is no currently a list of Python warts, and building a better language is impossible without a clear visibility of warts in current implementations.
Why Roundup doesn't work ATM. - warts are lost among other "won't fix" and "works for me" issues - no way to edit description to make it more clear - no voting/stars to percieve how important is this issue - no comment/noise filtering and the most valuable - there is no query to list warts sorted by popularity to explore other time-consuming areas of Python you are not aware of, but which can popup one day
SO at least allows: + voting + community wiki edits + useful comment upvoting + sorted lists + user editable tags (adding new warts is easy)
This post is a result of facing with numerous locals/settrace/exec issues that are closed on tracker. I also have my own list of other issues (logging/subprocess) at GC project, which I might be unable to maintain in future. There is also some undocumented stuff (subprocess deadlocks) that I'm investigating, but don't have time for a write-up. So I'd rather move this somewhere where it could be updated.
On Sun, Dec 30, 2012 at 11:31 PM, Jasper St. Pierre <jstpierre@mecheye.net> wrote:
We already have a collection of "warts" or "gotchas":
http://docs.python.org/3/faq/design.html#why-must-dictionary-keys-be-immutab... http://docs.python.org/3/faq/design.html#why-doesn-t-list-sort-return-the-so... http://docs.python.org/3/faq/design.html#why-are-default-values-shared-betwe... http://docs.python.org/3/faq/design.html#why-can-t-raw-strings-r-strings-end...
and so on. Note that that document is probably extremely out of date, but there is an existing place for them.
When much older Python 2.x-s were still in their heyday, there were some popular 3rd-party lists: http://lwn.net/Articles/43059/ http://zephyrfalcon.org/labs/python_pitfalls.html http://www.ferg.org/projects/python_gotchas.html (FWICT, Andrew Kuchling's article led to the "warts" terminology.) Cheers, Chris
participants (21)
-
alex23
-
anatoly techtonik
-
Antoine Pitrou
-
Ben Finney
-
Chris Angelico
-
Chris Rebert
-
Eli Bendersky
-
Ethan Furman
-
Greg Ewing
-
Jasper St. Pierre
-
Michael Foord
-
Mike Meyer
-
Ned Batchelder
-
Nick Coghlan
-
Oleg Broytman
-
Ryan Macy
-
Shane Green
-
Stephen J. Turnbull
-
Steven D'Aprano
-
Terry Reedy
-
Victor Stinner