Language design

S

Steven D'Aprano

Some time ago, Tom Christiansen wrote about the "Seven Deadly Sins of
Perl":

http://www.perl.com/doc/FMTEYEWTK/versus/perl.html


What design mistakes, traps or gotchas do you think Python has? Gotchas
are not necessarily a bad thing, there may be good reasons for it, but
they're surprising.

To get started, here are a couple of mine:


- Python is so dynamic, that there is hardly anything at all that can be
optimized at compile time.

- The behaviour of mutable default variables is a gotcha.

- Operators that call dunder methods like __add__ don't use the same
method resolution rules as regular methods, they bypass the instance and
go straight to the type, at least for new-style classes.
 
A

Antoon Pardon

Op 10-09-13 08:09, Steven D'Aprano schreef:
Some time ago, Tom Christiansen wrote about the "Seven Deadly Sins of
Perl":

http://www.perl.com/doc/FMTEYEWTK/versus/perl.html


What design mistakes, traps or gotchas do you think Python has? Gotchas
are not necessarily a bad thing, there may be good reasons for it, but
they're surprising.

To get started, here are a couple of mine:


- Python is so dynamic, that there is hardly anything at all that can be
optimized at compile time.

- The behaviour of mutable default variables is a gotcha.

- Operators that call dunder methods like __add__ don't use the same
method resolution rules as regular methods, they bypass the instance and
go straight to the type, at least for new-style classes.

Slice semantics in combination with negative indices.

Take ls = range[10]

What is the reverse of ls[a : b]? It is [b-1 : a-1: -1]

Except of course when a == 0 or b == 0.
 
C

Chris Angelico

What design mistakes, traps or gotchas do you think Python has? Gotchas
are not necessarily a bad thing, there may be good reasons for it, but
they're surprising.

Significant indentation. It gets someone every day, it seems.

The fact that importing twice doesn't reexecute any code.

The whole "consenting adults" philosophy. I happen to quite like it,
as do many of the regulars here, but it does trip up a lot of
programmers who've come from other languages.

Like you say, not necessarily a bad thing; but Admiral Ackbars all the same.

ChrisA
 
N

Nobody

* Python requires every programmer to know, or quickly learn, the basics
of Unicode: to know that text is not, and never will be again,
synonymous with a sequence of bytes.

If only the Python developers would learn the same lesson ...

Some of them are so hooked on Unicode that they won't accept that
sometimes a sequence of bytes really is just a sequence of bytes. Primary
example: most of the POSIX API.
 
S

Steven D'Aprano

If only the Python developers would learn the same lesson ...

Some of them are so hooked on Unicode that they won't accept that
sometimes a sequence of bytes really is just a sequence of bytes.
Primary example: most of the POSIX API.

And lo, Guido's Time Machine strikes again. Python 3 has not one but TWO
built-in types for handling sequences of bytes:

* bytes # immutable string of bytes
* bytearray # mutable array of bytes


and most routines that handle file names accept either text strings or
bytes strings:


py> open('aß', 'w').write("hello\n")
6
py> open(b'a\xc3\x9f', 'r').read()
'hello\n'
 
C

Chris Rebert

* No explicit variable declarations (modulo `global`+`nonlocal`) means
that variable name typos can't be reliably detected at compile-time.
* The value of the loop variable at call-time for functions defined
within a loop trips people up.
* No self-balancing tree datatype of any kind is included in the std lib.
* Function scope rather than block scope (e.g. `while` doesn't
introduce a new scope) [Personally, I don't have much of a problem
with this, but some people do.]
* No anonymous block syntax (cf. Ruby or Smalltalk). Makes it
harder/uglier to define/use custom control structures. The `with`
statement would have been unnecessary.

Cheers,
Chris
 
C

Chris Angelico

* The value of the loop variable at call-time for functions defined
within a loop trips people up.

Related: The confusion of 'with' vs __del__ vs del wrt open files etc.
Using 'with' does not guarantee the object's destruction, but the
destruction of the object and the exiting of the with block do have
the same effect, which is confusing. Personally, I'd prefer a
guarantee that this name expires at this point, plus a guarantee that
- if there are no other references - the object will be cleaned up
immediately; it's generally true in CPython, and if that could
actually be made a language feature, there'd be no need for 'with' and
no issues with confusing people.

ChrisA
 
B

Burak Arslan

What design mistakes, traps or gotchas do you think Python has?

My favourite gotcha is this:

elt, = elts

It's a nice and compact way to do both:

assert len(elts) == 0
elt = elts[0]

but it sure looks strange at first sight. As a bonus, it works on any
iterable, not just ones that support __getitem__.

burak
 
W

Wayne Werner

The sooner we replace the erroneous
“text is ASCII†in the common wisdom with “text is Unicodeâ€, the
better.

I'd actually argue that it's better to replace the common wisdom with
"text is binary data, and we should normally look at that text through
Unicode eyes". A little less catchy, but more accurate ;)

-W
 
D

Dave Angel

I'd actually argue that it's better to replace the common wisdom with
"text is binary data, and we should normally look at that text through
Unicode eyes". A little less catchy, but more accurate ;)

-W

"Text is unicode, but text files are binary, and need to be decoded on
read, and encoded on write. Most other external textual data is also
binary, and similarly need to be converted before use"
 
N

Neil Cerutti

What design mistakes, traps or gotchas do you think Python has?

My favourite gotcha is this:

elt, = elts

It's a nice and compact way to do both:

assert len(elts) == 0
elt = elts[0]

I'm confused. Your rewrite looks like an assertion error or an
IndexError.
 
C

Chris Angelico

My favourite gotcha is this:

elt, = elts

It's a nice and compact way to do both:

assert len(elts) == 0
elt = elts[0]

I'm confused. Your rewrite looks like an assertion error or an
IndexError.

Presumably he meant to assert that the length is 1. If elts is a list,
then yes, these are equivalent, though the expanded form is actually a
bit different (since any iterable can be used).

ChrisA
 
M

Markus Rother

Hello all,

Thanks for this thread. Here are my two cents...

What design mistakes, traps or gotchas do you think Python has? Gotchas
are not necessarily a bad thing, there may be good reasons for it, but
they're surprising.

"""
1. Occasionally, one encounters a strange idiom. Syntactically
legal and consistent, though:
-8


2. Reduce removed from standard library. That is a big fail, in
my opinion.


3. The default return value of methods is None instead of self.
If it was self, it would be possible to chain method calls (which
is called a cascade in smalltalk).

lst = []
lst.append(1).append(2).append(3) ## FAIL
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'append'


Instead, this works:

...
... def add(self, e):
... self.append(e)
... return self
...[1, 2, 3]


A very practical use case is, that the return value of None makes
all of these methods unusable for reduce.

from functools import reduce ...
many = [{1: 'a'}, {2: 'b'}, {3: 'c'}] ...
reduce(lambda d, other : d.update(other), many, {}) ## FAIL
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'update'


Again, one would have to define an update function with an
explicit return value.
many = [{1: 'a'}, {2: 'b'}, {3: 'c'}] ...
def fn(d, other):
... d.update(other)
... return d
...{1: 'a', 2: 'b', 3: 'c'}


4. As has been mentioned already, some built-in functions do magic
stuff behind the scenes:

NotImplemented


which yields True when cast to boolean.
"""

Greets,
Markus
 
E

Ethan Furman

4. As has been mentioned already, some built-in functions do magic
stuff behind the scenes:

That's why they're called magic methods. ;)

False

But:
bool(().__eq__([]))
True

This is not a trap, this is simply the wrong way to do it. The magic methods (aka dunder methods) are there for Python
to call, not you (except under special circumstances, such as when writing your own dunder methods).
 
M

Mark Janssen

* Imports are fiendishly complex, hidden below deceptively simple
syntax.

It's a reasonable expectation that one can import a module from a
source code file given its path on the filesystem, but this turns out
to be much more complicated than in many other languages.

Why is this so difficult? Add a Graph class to the collections module
(networkx is quite good) and simply check for circular imports. The
remaining difficulty I encounter is because the user hasn't defined
their PYTHONPATH variable.
 
M

Mark Janssen

1) It tried to make Object the parent of every class. No one's close
enough to God to make that work.
2) It didn't make dicts inherit from sets when they were added to Python.
3) It used the set literal for dict, so that there's no obvious way to
do it. This didn't get changed in Py3k.
4?) It allowed [reference] variables to be used as dict keys. This
creates a parsing difficulty for me, mentally. Keys should be direct,
hashable values, not hidden in a variable name.

A few of the top of the head....

Mark
 
P

Prasad, Ramit

Mark said:
1) It tried to make Object the parent of every class. No one's close
enough to God to make that work.
2) It didn't make dicts inherit from sets when they were added to Python.
3) It used the set literal for dict, so that there's no obvious way to
do it. This didn't get changed in Py3k.
4?) It allowed [reference] variables to be used as dict keys. This
creates a parsing difficulty for me, mentally. Keys should be direct,
hashable values, not hidden in a variable name.

What do you mean by 4? Do you mean that keys should only be hardcoded?
I am going to assume you meant something different, as that sounds like
a terrible idea to me...
A few of the top of the head....

Mark

This email is confidential and subject to important disclaimers and conditions including on offers for the purchase or sale of securities, accuracy andcompleteness of information, viruses, confidentiality, legal privilege, andlegal entity disclaimers, available at http://www.jpmorgan.com/pages/disclosures/email.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top