Hacker News new | past | comments | ask | show | jobs | submit login
Dynamically create a type with Python (precheur.org)
51 points by henryprecheur on June 17, 2009 | hide | past | favorite | 7 comments



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


I'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/#meta... for details on metaclasses.


Metaclasses 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.


"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)


Oh, 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/fo... creation of the counter on individual fields

http://code.djangoproject.com/browser/django/trunk/django/fo... application of the counter upon field harvesting


Huh, I hadn't thought about that... I may be able to pull that off. Thanks for the suggestion.


If 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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: