There was recently a short discussion about some way to make certain initialization of instances easier (less typing). This was then followed by an expression of a desire for the automatic generation of the __slots__ attribute for classes (which is generally painful to do by hand for any nontrivial class). This recipe defines a metaclass and a function. The 'AutoSlots' metaclass automatically generates a __slots__ attribute during compilation, and the 'InitAttrs' function initializes instance variables during runtime.
A variant which only requires the metaclass would be convenient and would be graciously accepted.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | class AutoSlots(type):
def __new__(cls, name, bases, dct):
slots = dict.fromkeys(dct.get('__slots__', []))
if '__init__' in dct:
init = dct['__init__']
ifvn = init.func_code.co_varnames
for i in xrange(init.func_code.co_argcount):
x = ifvn[i]
if x[:1] == '_':
slots[x[1:]] = None
dct['__slots__'] = slots.keys()
return type.__new__(cls, name, bases, dct)
def InitAttrs(ob, args):
for k, v in args.iteritems():
if k[:1] == '_':
setattr(ob,k[1:],v)
'''
If you would like to automatically assign arguments to methods
to the attributes of an object, you can do so by prefixing those
local variable names with a a single leading underscore '_',
which will be stripped from the instance variable (_x becomes x).
class Foo(object):
def __init__(self, _x, _y, _z):
InitAttrs(self, locals())
#...
AutoSlots further allows you to automatically generate __slots__
for your classes, pulling the variables which need to be slots
from the arguments to the __init__ method on your class.
class Goo(object):
__metaclass__ = AutoSlots
def __init__(self, _x, _y, _z):
InitAttrs(self, locals())
#...
>>> x = Goo(1,2,3)
>>> [i for i in dir(x) if i[:1] != '_']
['x', 'y', 'z']
>>> x.a = 7
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'Goo' object has no attribute 'a'
>>>
'''
|
This is a fixed version of the AutoSlots metaclass that I originally posted on python-dev.
Using assignment statements to construct __slot__. Here is a variant of the idea which looks at the assignment statements in the __init__ function.
To use this metaclass, inherit from the class Autoslots.
Correction needed for previous comment. Oops. Accidentally changed the name of the class. One should replace name by something else in the loops, since name is already an input parameter.