Dynamically create a class (or class instance) and its attributes?

R

Robert Oschler

Hello,

I am a Python newbie (by experience, not chronologically :) ), so if any of
this doesn't make sense my apologies in advance.

I am reading the chapter in The Python Cookbook on databases and the MySQLdb
module. In it they show an example of a recipe that lets you access fields
in a MySQL row by name rather than by column number. For example, given a
MySQL row object from a fetchone() call:

employee_name = sqlrow[field_dict['empname']]

To make the syntax easier and clearer, I would like to create a Python class
instance that would allow me to access the fields in the MySQL row as
attributes of a class created dynamically from the row structure. For
example:

employee_name = ez_sqlrow.empname

What would be the best way to create such a class or class instance? Any
code examples you have would be welcome.

Thanks
 
J

Jean Brouwers

This may work.

<pre>

class Dyn:
'''Dynamic class.
'''
def __init__(self, **kwds):
self.set(**kwds)

def set(self, **kwds):
for a, v in kwds.iteritems():
setattr(self, a, v)


# all attr defined at creation
# time with an initial value
c = Dyn(a1=1, a2=2, a3=3)

# more attr can be added
c.set(a4=4, a5=5)

# attr can be changed
c.a1=10
c.set(a1=20)

</pre>

/Jean Brouwers
 
P

Peter Otten

Robert said:
To make the syntax easier and clearer, I would like to create a Python
class instance that would allow me to access the fields in the MySQL row
as attributes of a class created dynamically from the row structure. For
example:

employee_name = ez_sqlrow.empname

Here is one way:

import itertools

class Record:
def __init__(self, row):
assert len(row) == len(self.names)
self._row = row
def __getitem__(self, index):
return self._row[index]
def __setitem__(self, index, value):
self._row[index] = value
def __iter__(self):
return itertools.izip(self.names, self._row)
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__,
", ".join(["%s=%r" % nv for nv in self]))

def makeProperty(index):
def get(self):
return self[index]
def set(self, value):
self[index] = value
return property(get, set)

def makeClass(classname, fieldnames, Base=Record):
class Record(Base):
names = fieldnames
Record.__name__ = classname

for index, name in enumerate(fieldnames):
setattr(Record, name, makeProperty(index))
return Record

if __name__ == "__main__":
Person = makeClass("Person", ["firstname", "lastname", "email"])
r = Person(["Robert", "Oschler", "not provided"])
print r.firstname
r.email = "(e-mail address removed)"
print r.email
print "%s %s" % tuple(r[:2])
print r

which is actually a variant of something I posted a few days ago. Or you go
with SQLObject.(Am I repeating myself? Am I repeating myself :)

Peter
 
C

Christopher T King

For example, given a MySQL row object from a fetchone() call:

employee_name = sqlrow[field_dict['empname']]

To make the syntax easier and clearer, I would like to create a Python class
instance that would allow me to access the fields in the MySQL row as
attributes of a class created dynamically from the row structure. For
example:

employee_name = ez_sqlrow.empname

What would be the best way to create such a class or class instance? Any
code examples you have would be welcome.

The other respondents have recommended using setattr(), but here's a way
that will work completely dynamically:

class ez_sql(object):

def __init__(self,sqlrow):
self._sqlrow = sqlrow

def __getattr__(self,a):
try:
return self._sqlrow[fielddict[a]]
except (IndexError,KeyError),e:
raise AttributeError,e

def __setattr__(self,a,v):
try:
self._sqlrow[fielddict[a]] = v
except KeyError:
self.__dict__[a] = v

This is a bit slower than using setattr(), but might save a good deal of
memory (especially if you keep the SQL rows around in another form).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top