Negative array indicies and slice()

Steven D'Aprano steve+comp.lang.python at pearwood.info
Mon Oct 29 20:02:25 EDT 2012


On Mon, 29 Oct 2012 08:42:39 -0700, Andrew Robinson wrote:

>>> But, why can't I just overload the existing __getitem__ for lists and
>>> not bother writing an entire class?

You say that as if writing "an entire class" was a big complicated 
effort. It isn't. It is trivially simple, a single line:

class MyList(list):
    ...


plus the __getitem__ definition, which you would have to write anyway. It 
is a trivial amount of extra effort.


>> You can just overload that one method in a subclass of list.  Being
>> able to monkey-patch __getitem__ for the list class itself would not be
>> advisable, as it would affect all list slicing anywhere in your program
>> and possibly lead to some unexpected behaviors.
>
> That's what I am curious about.
> What unexpected behaviors would a "monkey patch" typically cause? 

What part of "unexpected" is unclear?

Monkey-patching is poor programming technique because it leads to 
*unexpected* and *impossible to predict* interactions between *distant* 
parts of the code. It leads to impossible to predict differences between 
the source code on disk and the actual running code. It leads to 
impossible to predict differences between documented behaviour and actual 
behaviour.

Let me see if I can illustrate a flavour of the sort of things that can 
happen if monkey-patching built-ins were allowed.

You create a list and print it:

# simulated output
py> x = [5, 2, 4, 1]
py> print(x)
[1, 2, 4, 5]

What? How did that happen? That's not the list you provided. The order 
has been lost.

So you dig deep into your code, and you don't find anything. And you read 
the Python documentation for lists, and don't find anything. And you 
google the Internet, and don't find anything. And you ask for help, and 
everybody says you're crazy because when they duplicate your code they 
get the expected behaviour. And you report a bug in Python, and it gets 
closed as "cannot replicate".

Finally you search deep into the libraries used in your code, and *five 
days later* discover that your code uses library A which uses library B 
which uses library C which uses library D which installs a harmless 
monkey-patch to print, but only if library E is installed, and you just 
happen to have E installed even though your code never uses it, AND that 
monkey-patch clashes with a harmless monkey-patch to list.__getitem__ 
installed by library F. And even though each monkey-patch alone is 
harmless, the combination breaks your code's output.



Python allows, but does not encourage, monkey-patching of code written in 
pure Python, because it sometimes can be useful. It flat out prohibits 
monkey-patching of builtins, because it is just too dangerous.

Ruby allows monkey-patching of everything. And the result was predictable:

http://devblog.avdi.org/2008/02/23/why-monkeypatching-is-destroying-ruby/


-- 
Steven



More information about the Python-list mailing list