>>> class Slots(object): __slots__ = ()
...
>>> Slots.__slots__ = ('t',)
>>> Slots.__slots__
('t',)
>>> s2 = Slots()
>>> s2.t = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Slots' object has no attribute 't'
Kind of like "hey guys, check it out you can just duct tape down the dead-man's switch on this power tool and use it one handed". In Python.
Friday, September 30, 2011
namedtupledict
With three kinds of member access, it is easier to use than ever.
>>> def namedtupledict(*a, **kw):
... namedtuple = collections.namedtuple(*a, **kw)
... def getitem(self, key):
... if type(key) == str:
... return getattr(self, key)
... return tuple.__getitem__(self, key)
... namedtuple.__getitem__ = getitem
... return namedtuple
...
>>> t = namedtupledict('t', 'a b c')
>>> t1 = t(1,2,3)
>>> t1.a
1
>>> t1[0]
1
>>> t1['a']
1
>>> def namedtupledict(*a, **kw):
... namedtuple = collections.namedtuple(*a, **kw)
... def getitem(self, key):
... if type(key) == str:
... return getattr(self, key)
... return tuple.__getitem__(self, key)
... namedtuple.__getitem__ = getitem
... return namedtuple
...
>>> t = namedtupledict('t', 'a b c')
>>> t1 = t(1,2,3)
>>> t1.a
1
>>> t1[0]
1
>>> t1['a']
1
Thursday, September 29, 2011
Wednesday, September 21, 2011
I'm my own grandpa.
A fellow Pythonaut had a simple problem...
How to test code with dependencies on the date? Specifically, a Django project with models that have DateTimeFields with auto_now=True.
The chosen approach was to monkey-patch datetime.date.today() in order to return a constant value.
The first snag: datetime.date is a C class. This means it is not monkey-patchable.
This can be solved by monkey-patching the entire datetime.date class. The most straightforward thing to replace datetime.date with is a new subclass of datetime.date, whose only change is to override the today() function.
The second problem: there are now two kinds of datetime.date's floating around the system. Those by datetime.date.today(), and those created by every other function, which being C code will still return the same class.
Specifically, DateTimeField validates isinstance(data, datetime.date) before saving to the database.
A class which is simultaneously a super and subclass of datetime.date is required.
Override __subclasshook__ so that isinstance(super(datetime.date)(), datetime.date) is True.
>>> class DateProxy(datetime.date):
... __metaclass__ = abc.ABCMeta
... @classmethod
... def __subclasshook__(cls, C): return True
... @classmethod
... def today(cls): return datetime.date(2011,9,20)
...
>>> datetime.date = DateProxy
In other words, the superclass is also a subclass. The parent of the parent being the grandparent, this class is it's own grandpa.
How to test code with dependencies on the date? Specifically, a Django project with models that have DateTimeFields with auto_now=True.
The chosen approach was to monkey-patch datetime.date.today() in order to return a constant value.
The first snag: datetime.date is a C class. This means it is not monkey-patchable.
This can be solved by monkey-patching the entire datetime.date class. The most straightforward thing to replace datetime.date with is a new subclass of datetime.date, whose only change is to override the today() function.
The second problem: there are now two kinds of datetime.date's floating around the system. Those by datetime.date.today(), and those created by every other function, which being C code will still return the same class.
Specifically, DateTimeField validates isinstance(data, datetime.date) before saving to the database.
A class which is simultaneously a super and subclass of datetime.date is required.
Override __subclasshook__ so that isinstance(super(datetime.date)(), datetime.date) is True.
>>> class DateProxy(datetime.date):
... __metaclass__ = abc.ABCMeta
... @classmethod
... def __subclasshook__(cls, C): return True
... @classmethod
... def today(cls): return datetime.date(2011,9,20)
...
>>> datetime.date = DateProxy
In other words, the superclass is also a subclass. The parent of the parent being the grandparent, this class is it's own grandpa.
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 += 1You 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
If you simply must have numbers larger than
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
Subscribe to:
Posts (Atom)