Monday, November 21, 2011

metaclass depth > call depth

How far deep can a metaclass tree go?
type(A) = B, type(B) = C, type(C) = D...?
Can it go further than the function call depth?

def tower(n=100, sofar=type):
   class next(sofar):
      __metaclass__ = sofar
   return tower(n-1, next)

>>> tower(997)
<class '__main__.sofar'>
>>> tower(998)
#...
  File "<stdin>", line 3, in tower
RuntimeError: maximum recursion depth exceeded while calling a Python object

Friday, October 21, 2011

Class is Set of Instances

This shows how to make a class also be a set of its own instances.
A conceptually simpler way of maintaining a global registry of instances.

>>> class SetMetaClass(type):
...    def __new__(cls, *a, **kw):
...       cls.all = set()
...       return type.__new__(cls, *a, **kw)
...    def __iter__(cls): return cls.all.__iter__()
...    def __len__(cls): return len(cls.all)
...    def __contains__(cls, e): return e in cls.all
...    def add(cls, e): cls.all.add(e)
...    def discard(cls, e): cls.all.discard(e)
...
>>> class InstanceSet(object):
...    __metaclass__ = SetMetaClass
...    def __init__(self, *a, **kw):
...       self.__class__.add(self)
...
>>> InstanceSet()
<__main__.InstanceSet object at 0x00DAB0F0>
>>> InstanceSet()
<__main__.InstanceSet object at 0x00D23610>
>>> [a for a in InstanceSet]
[<__main__.InstanceSet object at 0x00DAB0F0>, <__main__.InstanceSet object at 0x
00D23610>]
>>> len(InstanceSet)
2

Tuesday, October 11, 2011

Decoration? Instantiation? Decorstantiation

>>> class Decorstantiator(object):
...    def __init__(self, func): self.func = func
...    def __call__(self): print "foo"; func()
...
>>> @Decorstantiator
... def bar(): print "bar"
...
>>> bar()
foo
bar

Sunday, October 9, 2011

I can DoAnything

Sometimes you just want to test a piece of code that does deep calls into other objects in isolation.
For example:
def _change(self, op, val):
        self.parent.context.change(self.parent.model, self.attr, op, val)
How can we create an object to stand in for parent in the above code?
class DoAnything(object):
   def __call__(self, *a, **kw): return self
   __getattr__ = __add__ = __sub__ = __mul__ = __div__ = __call__
   #overload more operators to taste/requirements

>>> parent = DoAnything()
>>> parent.context.change(parent.model, "foo", "bar", "baz")
<__main__.DoAnything object at 0x02169B10>

Friday, September 30, 2011

__slots__ cannot be updated

>>> 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'

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

Thursday, September 29, 2011