Negative array indicies and slice()
Andrew Robinson
andrew3 at r3dsolutions.com
Mon Oct 29 15:34:24 EDT 2012
On 10/29/2012 05:02 PM, Steven D'Aprano wrote:
> 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):
> ...
No, I don't think it big and complicated. I do think it has timing
implications which are undesirable because of how *much* slices are used.
In an embedded target -- I have to optimize; and I will have to reject
certain parts of Python to make it fit and run fast enough to be useful.
>>> 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?
>
Ahh -- The I don't know approach! It's only unexpected if one is a bad
programmer...!
> 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]
<snip>
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.
Right, which means that people developing the libraries made
contradictory assumptions.
> 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/
>
I read that post carefully; and the author purposely notes that he is
exaggerating.
BUT Your point is still well taken.
What you are talking about is namespace preservation; and I am thinking
about it. I can preserve it -- but only if I disallow true Python
primitives in my own interpreter; I can't provide two sets in the memory
footprint I am using.
From my perspective, the version of Python that I compile will not be
supported by the normal python help; The predecessor which first forged
this path, Pymite, has the same problems -- however, the benefits
ought-weigh the disadvantages; and the experiment yielded useful
information on what is redundant in Python (eg: range is not supported)
and when that redundancy is important for some reason.
If someone had a clear explanation of the disadvantages of allowing an
iterator, or a tuple -- in place of a slice() -- I would have no qualms
dropping the subject. However, I am not finding that yet. I am finding
very small optimization issues...
The size of an object is at least 8 bytes. Hence, three numbers is
going to be at least 24 bytes; and that's 24 bytes in *excess* of the
size of slice() or tuple () which are merely containers. So -- There
*ARE* savings in memory when using slice(), but it isn't really 2x
memory -- its more like 20% -- once the actual objects are considered.
The actual *need* for a slice() object still hasn't been demonsrated. I
am thinking that the implementation of __getitem__() is very poor
probably because of legacy issues.
A tuple can also hold None, so ( 1, None, 2 ) is still a valid Tuple.
Alternately: An iterator, like xrange(), could be made which takes None
as a parameter, or a special value like 'inf'.
Since these two values would never be passed to xrange by already
developed code, allowing them would not break working code.
I am only aware of one possible reason that slice() was once thought to
be necessary; and that is because accessing the element of a tuple would
recursively call __getitem__ on the tuple. But, even that is easily
dismissed once the fixed integer indexes are considered.
Your thoughts? Do you have any show stopper insights?
More information about the Python-list
mailing list