python object pool with metaclasses class Pool(type):
    pool = dict()
    def __new__(clas, *a, **k):
        def __del__(self):
            Pool.pool[self.__class__] = Pool.pool.get(self.__class__, []) + [self]
        a[-1]['__del__'] = __del__
        return type.__new__(clas, *a, **k)

    def __call__(clas, *a, **k):
        if Pool.pool.get(clas):
            print('Pool.pool is not empty: return an already allocated instance')
            r = Pool.pool[clas][0]
            Pool.pool[clas] = Pool.pool[clas][1:]
            return r
        else:
            print('Pool.pool is empty, allocate new instance')
            return type.__call__(clas, *a, **k)

class Foo(metaclass=Pool):
    def __init__(self):
        print('Foo &gt; .', self)
    def foo(self):
        print('Foo &gt; foo:', self)

f1 = Foo()
f1.foo()

print('## now deleting f1')
del f1

print('## now create f2')
f2 = Foo()
f2.foo()

print('## now create f3')
f3 = Foo()
f3.foo()


what do you think about this piece of code?
class Pool(type):


The defaultdict class will automatically create my list when I access it

    pool = collection.defaultdict(list)


The python style guide suggests using the form class_ rather then clas
It is also not clear why you are capturing the incoming arguments as variable.
This being a metaclass it is going to have consistent parameters

    def __new__(class_, name, bases, classdict):
        def __del__(self):


Since pool now automatically creates the list, we can just append to it
                Pool.pool[self.class].append(self)

Getting rid of the variable arguments also makes this much clearer.                

        classdict['__del__'] = __del__
        return type.__new__(class_, name, bases, classdict)


args and kwargs are often used as the names for variable parameters. I recommend using them to make code clearer

    def __call__(class_, *args, **kwargs):


Thanks to the use of defaultdict above we can make this code quite a bit cleaner. Also, this code doesn't pretend its using a functional programming language. Your code created lists by adding them together, slicing, etc. That is not a really efficient or clear way to use python.

        instances = Pool.pool[class_]
        if instances:


There is a subtle and dangerous problem here. When you create a new instance, you pass along your parameters.
However, if an instance is already created, you return that ignoring what the parameters were doing.
This means that you might get an object back which was created using different parameters then you just passed.
I haven't done anything to fix that here

            print('Pool.pool is not empty: return an already allocated instance')
            return instances.pop()
        else:
            print('Pool.pool is empty, allocate new instance')
            return type.__call__(class_, *args, **kwargs)


Your technique is to install a __del__ method on the objects so that you can detect when they are no longer being used and keep them in your list for the next person who asks for them. the __del__ method is invoked when the object is about to be deleted. You prevent the deletion by storing a reference to the object in your list. This is allowed but the python documentation indicates that it is not recommended.

__del__ has a number of gotchas. If an exception is caused while running the __del__ method it will be ignored. Additionally, it will tend to cause objects in references cycles to not be collectable. If your code is ever run on Jython/IronPython then you can't be sure that __del__ will be called in a timely manner. For these reasons I generally avoid use of __del__. 

You are using a metaclass so the fact that the given object is pooled is hidden from the user. I don't really think this is a good idea. I think it is far better to be explict about something like pooling. You also lose flexibility doing it this way. You cannot create multiple pools, etc.

The interface that I would design for this would be:

pool = Pool(Foo, 1, 2, alpha = 5) # the pool gets the arguments that will be used to construct Foo
with pool.get() as f1:
    # as long as I'm in the with block, I have f1, it'll be returned when I exit the block
    f1.foo()
with pool.get() as f2:
    f2.foo()
    with pool.get() as f3:
        f3.foo()

f4 = pool.get()
f4.foo()
pool.repool(f4)