More random python observations from a perl programmer

Tim Peters tim_one at email.msn.com
Sun Aug 22 03:11:42 EDT 1999


[posted & mailed]

[Tom Christiansen, on "in" and dicts]
> Well, it's the polymorphism thing.  If "+" is supposed to work on
> anything (which I don't agree with, but that's not my decision),

To the contrary, for your objects it *is* your decision whether they
implement semantics for "+"; by default, they won't.  For Python's builtin
types, it was Guido's decision, and most types *don't* implement "+" (for
example, none of function, dict, file, traceback, class, method, module or
type objects).  Polymorphism is a freedom in Python, not a requirement.

> I don't understand why "in" shouldn't.

Neither do we <wink>.  1.6 will probably introdoce a class __contains__
method to let users implement their own "in" semantics.

> I keep thinking that everything should work on everything.

The builtins strive to stick to those type/operator combos that make plain
sense; Guido has never been a fan of gratuitous orthogonality.

> For example, this surprises me:
>
>     x = {1:2, 3:4}
>     y = {10:20, 30:40}
>     z = x + y
>
> The latter isn't legal.

In the early years it was debated, and there were conflicting views about
what to do in case of collisions; so rather than introduce a continuing
source of surprises, the idea was dropped.  Merging dicts proved too useful
too often for that to stand, so a dict.update(otherdict) method was
introduced:  since it's most useful most often to merge in-place, and "x +
y" suggests anything *other* than in-place merging, a method was used
instead.  If += had been implemented first, I imagine dict merge would be
spelled via + instead.

> But in Perl, you can merge hashes easily.

Also in Python, although since there's no split between objects and
references to objects, unlike as in Perl the operation is always spelled the
same way.

> ...
> Of course, that's [in Perl] not super efficient.

It is in Python <wink>.

> And that overright duplicates, rather than making lists of them.
> Still, that's not a bad behaviour.

Ditto, ditto.

> I can't get used to not being able to do hash slices, as in
>
>     @revhash{values %hash} = keys %hash;
>
> Or
>
>     print sort(@hash{@desired})

General gather/scatter functions are short & easy to write, if you want
that.  For example, here's the harder one:

    def scatter(container, indices, values):
        for i in range(len(indices)):
            container[indices[i]] = values[i]
        # and some people like to return the mutated container here,
        # although most don't

Note something interesting here:  because of that dreaded <wink>
polymorphism, with 3 lines of code you've now implemented scattering for
lists, arrays, dicts, and all current & future user-defined sequence &
mapping types too!

What bothers me in the above is the "range(len(indices))" business:  it's
too common to be that wordy.  Parallel sequence iteration would be a good
language addition (to Python and Perl!).

Now that you've seen the obvious way, there's also a fast but obscure way:

    def scatter(contaioer, indices, values):
        import operator
        map(operator.setitem, (container,)*len(indices),
            indices, values)

That does the buik of the work at C speed.

there's-always-some-way-to-do-it<wink>-ly y'rs  - tim






More information about the Python-list mailing list