5 ms·
Dynamically create a type with Python
- daeken 17y agoGood little introduction in terms of general use, but I think a solid example is in order, as it's a very useful technique. A while back, I created a Struct class, which allows the creation of C-like structs, but you had to create a subclass of Struct, specify the endianness as a class attribute, and create a __format__ method that built the struct members. A little while ago, I had the thought to wrap it into a decorator, defStruct/defStructLE/defStructBE, that automagickly calls 'type' to build the appropriate Struct class for you, given a method. So what once was: class Foo(Struct): __endian__ = Struct.LE def __format__(self): self.foo = Struct.uint32 self.bar = Struct.string(self.foo) Became: @defStructLE def Foo(self): self.foo = Struct.uint32 self.bar = Struct.string(self.foo) Much, much cleaner, all thanks to the magic of 'type'.
- lehmannro 17y agoI'd rather utilize a metaclass in this special case. This would retain the notion of Foo being a type much better than transmogrifying a function into a class. (Granted, there's not that big a difference technically but you're tricking other programmers into believing Foo cannot be used for eg. isinstance.) class Foo(Struct): __endian__ = Struct.LE foo = Struct.uint32 bar = Struct.string(foo) If you don't like specifying the endianness as a class attribute you could still inherit from Struct.LE/BE rather than Struct itself. Quick technical howto: make Struct have a __metaclass__ class attribute, populate the __metaclass__ class with a __new__ or __init__ method performing the desired transformations. See http://www.python.org/download/releases/2.2/descrintro/#metaclasses http://www.python.org/download/releases/2.2/descrintro/#meta... for details on metaclasses.
- daeken 17y agoMetaclasses won't fly in this case, since the order of struct members has to be kept. Tried a bunch of things to make it work, but in the end nothing came out cleaner.
- jbox 17y ago"Metaclasses won't fly in this case, since the order of struct members has to be kept." Couldn't you use a creation counter in a metaclasses and assign order to the attributes as they are added? (like Django's forms use to keep track of field order)
- daeken 17y agoHuh, I hadn't thought about that... I may be able to pull that off. Thanks for the suggestion.
- lehmannro 17y agoOh, I didn't think about the order. Django's approach to this issue is really simple and only requires that all your Struct fields are instances of some common base class. http://code.djangoproject.com/browser/django/trunk/django/forms/fields.py#L97 http://code.djangoproject.com/browser/django/trunk/django/fo... creation of the counter on individual fields http://code.djangoproject.com/browser/django/trunk/django/forms/forms.py#L37 http://code.djangoproject.com/browser/django/trunk/django/fo... application of the counter upon field harvesting
- mortenoffline 17y agoIf he wanted to persist the classes offered by the server you could actually write the python code to a module, reload module and import the class proper. Did that a while ago so I didn't have to restart a daemon all the time.