Saturday, August 27, 2011

Incrementing and Decrementing

Depending on the language/style you're coming from, you may have run into this very early or not at all:
>>> x = 1
>>> ++x
1
>>> x
1
>>> x++
File "", line 1
x++
^
SyntaxError: invalid syntax

Somewhat confusing! The supposed pre-increment operator doesn't generate an error, but it doesn't work, either. The post-increment raises a syntax error. Same thing happens with the decrement operator (--).

The reason for this madness is that Python doesn't have increment and decrement operators like those in C/C++/PHP. The "increment operator" is actually being interpreted as two identity operators, i.e., vanilla plus signs:
+(+x)
This usually has no effect on Python number types. The "decrement operator" double-negates the number, again, having no apparent effect.


So why doesn't Python have increment/decrement operators? It's probably to keep Python's interpreter simple. Guido says simple is better than complex, thusly Python's interpreter won't get more complex than LL(1). Not that LL(1) can't do this, but in general complexifications aren't necessary when you can just do:
>>> x = x + 1 # or
>>> x += 1
You only need one right way to do things, and here you have two. Don't get greedy.



Metablog note: Gist embeds somewhat nicely in Blogger, but doesn't show up in the RSS, so we're back to monospace blockquotes.

Wednesday, August 24, 2011

Range woes

If you've ever iterated, you probably know about the built-in range() and xrange() functions. They usually do the job, but neither is perfect. xrange() can't deal with numbers larger than the system max integer, while range() chokes on very long ranges:



If you simply must have numbers larger than sys.maxint, then you need to use range() while limiting the length with a start argument.

Thursday, August 18, 2011

Passing Parameters 4 Ways at Once


>>> def foo(a,b,c,d): print a, b, c, d
...
>>> foo(1, *(2,), c=3, **{'d':4} )
1 2 3 4

Friday, August 5, 2011

Stealth Metaclass

>>> class StealthMeta(type):
...    def __new__(cls, name, bases, attrs):
...        del attrs['__metaclass__']
...        return type.__new__(cls, name, bases, attrs)
...
>>> class A(object):
...    __metaclass__ = StealthMeta
...
>>> A.__metaclass__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'A' has no attribute '__metaclass__'
>>> isinstance(A, StealthMeta)
True

Decorate then Meta, or Meta then Decorate?

Which is applied second, a meta-class or a class decorator?

>>> def add_a(cls):
...    cls.a = "decorator!"
...    return cls
...
>>> class MetaA(type):
...    def __new__(cls, name, bases, attrs):
...       attrs["a"] = "metaclass!"
...       return type.__new__(cls, name, bases, attrs)
...
>>> @add_a
... class Test(object):
...    __metaclass__=MetaA
...
>>> Test.a
'decorator!'