Dynamic Class Creation
Jack Diederich
jackdied at gmail.com
Tue Mar 16 12:49:59 EDT 2010
On Tue, Mar 16, 2010 at 2:18 AM, Chris Rebert <clp2 at rebertia.com> wrote:
> On Mon, Mar 15, 2010 at 11:01 PM, Josh English
> <joshua.r.english at gmail.com> wrote:
>> I have a large program with lots of data stored in XML. I'm upgrading
>> my GUI to use ObjectListView, but with my data in XML, I don't have
>> regular objects to interact with the OLV. I do have an XML validator
>> that defines the structure of the XML elements, and I'm trying to
>> dynamically create a class to wrap the XML element.
>>
>> So, an element like:
>>
>> <market code="WotF">
>> <title>Writers of the Future</title>
>> </market>
>>
>> I want to create a class like:
>>
>> class Market(object):
>> def __init__(self, elem):
>> self._elem = elem
>>
>> def get_code(self):
>> return self._elem.get('code')
>>
>> def set_code(self, value):
>> self._elem.set('code', value)
>>
>> def get_title(self):
>> return self._elem.find('title').text
>>
>> def set_title(self, value):
>> node = self._elem.find('title')
>> node.text = value
>>
>> Naturally, I don't want to hand code this for every interface but
>> would like to create them dynamically. (The laziness of programming, I
>> guess.)
>>
>> What's the best way to create these helper methods?
You can either define a catch-all __getattr__ method to look them up
dynamically, or as Chris kinda-suggested write descriptors for the
individual elements.
class Market():
def __init__(self, elem):
self._elem = elem
def __getattr__(self, name):
try:
# I'm assuming this raises a KeyError when not found
return self._elem.get(name)
except KeyError:
return self._elem.find(name)
def __setitem__(self, name, value):
# like __getitem__ but for setting
Chris' property maker function is almost like a descriptor class (how
properties are implemented under the hood), here's a refactoring
[untested]
class ElemGetProperty():
def __init__(self, name):
self.name = name
def __get__(self, ob, cls):
return ob._elem.get(self.name)
def __set__(self, ob, val):
ob._elem.set(self.name, val)
You could write one property class for each kind of element (get/find)
and then put them in your class like this
class Market():
code = ElemGetProperty('code')
title = ElemFindProeprty('title')
The getattr/setattr method is easier to understand and will handle
arbitrary elements; for the descriptors version you'll have to define
one for each tag that might be used on the class.
-Jack
More information about the Python-list
mailing list