Connecting Tech Pros Worldwide Forums | Help | Site Map

Factory for Struct-like classes

eliben
Guest
 
Posts: n/a
#1: Aug 13 '08
Hello,

I want to be able to do something like this:

Employee = Struct(name, salary)

And then:

john = Employee('john doe', 34000)
print john.salary

Basically, Employee = Struct(name, salary) should be equivalent to:

class Employee(object):
def __init__(self, name, salary):
self.name = name
self.salary = salary

Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?

Thanks in advance

P.S. I'm aware of this common "pattern":

class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)

Which allows:

john = Struct(name='john doe', salary=34000)
print john.salary

But what I'm asking for is somewhat more general.



Michele Simionato
Guest
 
Posts: n/a
#2: Aug 13 '08

re: Factory for Struct-like classes


On Aug 13, 6:43 pm, eliben <eli...@gmail.comwrote:
Quote:
Hello,
>
I want to be able to do something like this:
>
Employee = Struct(name, salary)
>
And then:
>
john = Employee('john doe', 34000)
print john.salary
>
Basically, Employee = Struct(name, salary) should be equivalent to:
>
class Employee(object):
def __init__(self, name, salary):
self.name = name
self.salary = salary
>
Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?
>
Thanks in advance
>
P.S. I'm aware of this common "pattern":
>
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
>
Which allows:
>
john = Struct(name='john doe', salary=34000)
print john.salary
>
But what I'm asking for is somewhat more general.

NamedTuples: http://code.activestate.com/recipes/303439/
Christian Heimes
Guest
 
Posts: n/a
#3: Aug 13 '08

re: Factory for Struct-like classes


eliben wrote:
Quote:
Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?

Try named tuple http://code.activestate.com/recipes/500261/

A named tuple implementation is part of Python 2.6 and 3.0. For older
versions of Python use the recipe from activestate.

Christian

eliben
Guest
 
Posts: n/a
#4: Aug 13 '08

re: Factory for Struct-like classes


On Aug 13, 7:30*pm, Christian Heimes <li...@cheimes.dewrote:
Quote:
eliben wrote:
Quote:
Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?
>
Try named tuplehttp://code.activestate.com/recipes/500261/
>
A named tuple implementation is part of Python 2.6 and 3.0. For older
versions of Python use the recipe from activestate.
>
Christian
Thanks Christian - this is exactly what I've been looking for.
Some thoughts...

1) I see this is done with exec anyway, so there's no more pythonic
way.

2) The definition of fields as a single string is weird. Why not use
**kwargs instead ?
Marc Christiansen
Guest
 
Posts: n/a
#5: Aug 13 '08

re: Factory for Struct-like classes


eliben <eliben@gmail.comwrote:
Quote:
Hello,
>
I want to be able to do something like this:
>
Employee = Struct(name, salary)
>
And then:
>
john = Employee('john doe', 34000)
print john.salary
>
Basically, Employee = Struct(name, salary) should be equivalent to:
>
class Employee(object):
def __init__(self, name, salary):
self.name = name
self.salary = salary
>
Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?
>
Thanks in advance
I have some old code laying around which should do what you want. It was
originally written by Kragen Sitaker in 2001-10-16 and is public domain.

def defstruct(*fields):
class Struct(object):
def __init__(self, *contents):
if len(contents) != len(self.structfields):
raise TypeError(
"wrong number of arguments: expected %d %s, got %d" %
(len(self.structfields),
repr(self.structfields),
len(contents)))
for field, content in zip(self.structfields, contents):
setattr(self, field, content)
Struct.structfields = fields
return Struct

Use:
Employee = defstruct("name", "salary")
john = Employee('john doe', 34000)
print john.salary

Marc
Larry Bates
Guest
 
Posts: n/a
#6: Aug 14 '08

re: Factory for Struct-like classes


eliben wrote:
Quote:
Hello,
>
I want to be able to do something like this:
>
Employee = Struct(name, salary)
>
And then:
>
john = Employee('john doe', 34000)
print john.salary
>
Basically, Employee = Struct(name, salary) should be equivalent to:
>
class Employee(object):
def __init__(self, name, salary):
self.name = name
self.salary = salary
>
Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?
>
Thanks in advance
>
P.S. I'm aware of this common "pattern":
>
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
>
Which allows:
>
john = Struct(name='john doe', salary=34000)
print john.salary
>
But what I'm asking for is somewhat more general.
>
>
That's about as "general" as it gets ;-). It works for any number/type of
attribute. I would probably make it a new-style class by subclassing object,
but for simulating a generic row container, this is quite good. You might
extend it with a __str__ method, __len__ method, make it an iterator, etc.
but that is quite easy.

-Larry

Matthew Wilson
Guest
 
Posts: n/a
#7: Aug 15 '08

re: Factory for Struct-like classes


On Thu 14 Aug 2008 11:19:06 AM EDT, Larry Bates wrote:
Quote:
eliben wrote:
Quote:
>Hello,
>>
>I want to be able to do something like this:
>>
>Employee = Struct(name, salary)
>>
>And then:
>>
>john = Employee('john doe', 34000)
>print john.salary
I find something like this useful, especially if any time I tried to
cram in an attribute that wasn't allowed, the class raises an exception.

One way to do it is to make a function that defines a class inside and
then returns it. See the code at the end of this post for an example.

I couldn't figure out how to do this part though:
Quote:
Quote:
>Employee = Struct(name, salary)
I have to do this instead (notice that the args are strings):
Quote:
Quote:
>Employee = Struct('name', 'salary')
Anyway, here's the code:

def struct_maker(*args):

class C(object):
arglist = args
def __init__(self, *different_args):

# Catch too few/too many args.
if len(self.arglist) != len(different_args):
raise ValueError("I need exactly %d args (%s)"
% (len(self.arglist), list(self.arglist)))

for a, b in zip(self.arglist, different_args):
setattr(self, a, b)

def __setattr__(self, k, v):
"Prevent any attributes except the first ones."
if k in self.arglist:
object.__setattr__(self, k, v)
else:
raise ValueError("%s ain't in %s"
% (k, list(self.arglist)))

return C

And here it is in action:

In [97]: Employee = struct_maker('name', 'salary')

In [98]: matt = Employee('Matt Wilson', 11000)

In [99]: matt.name, matt.salary

Out[99]: ('Matt Wilson', 11000)

In [100]: matt.invalid_attribute = 99
---------------------------------------------------------------------------
ValueError: invalid_attribute ain't in ['name', 'salary']


Matt
Gabriel Genellina
Guest
 
Posts: n/a
#8: Aug 18 '08

re: Factory for Struct-like classes


On 13 ago, 14:46, eliben <eli...@gmail.comwrote:
Quote:
On Aug 13, 7:30*pm, Christian Heimes <li...@cheimes.dewrote:
>
Quote:
eliben wrote:
Quote:
Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?
>
Quote:
Try named tuplehttp://code.activestate.com/recipes/500261/
>
1) I see this is done with exec anyway, so there's no more pythonic
way.
It doesn't *have* to be done with exec - I think there are other
variants using metaclasses instead.
Quote:
2) The definition of fields as a single string is weird. Why not use
**kwargs instead ?
Because the field ordering would be lost, which is important for a
named *tuple*.
(Anyway, I'd prefer a list of names instead of a single string...)

--
Gabriel Genellina
Dan Lenski
Guest
 
Posts: n/a
#9: Aug 18 '08

re: Factory for Struct-like classes


On Aug 13, 1:30*pm, Christian Heimes <li...@cheimes.dewrote:
Quote:
Trynamedtuplehttp://code.activestate.com/recipes/500261/
>
Anamedtupleimplementation is part of Python 2.6 and 3.0. For older
versions of Python use the recipe from activestate.
>
Christian
This named tuple recipe is pretty cool... I think there may be a
slight bug in the Python docs, though. The ActiveState page explains
that it avoids the overhead of a per-instance __dict__ by using the
__slots__ variable. However, according to the most-recent Python
docs, __slots__ does *NOT* work with subclasses of list, str, or
tuple.

From http://docs.python.org/ref/slots.html#l2h-222:

# __slots__ do not work for classes derived from ``variable-length''
built-in types such as long, str and tuple.

On the other hand, nametuple does appear to work as advertised.
Quote:
Quote:
Quote:
>>Person=namedtuple.namedtuple('Person', ('name', 'age', 'height'))
>>p=Person('Bob', 24, 1.86)
>>p.name
'Bob'
Quote:
Quote:
Quote:
>>p.shoe_size
AttributeError: 'Person' object has no attribute 'shoe_size'
Quote:
Quote:
Quote:
>>p.__dict__
AttributeError: 'Person' object has no attribute '__dict__'

So is there a bug in the Python docs? Does __slots__ in fact work
with subclasses of tuple?

Dan
eliben
Guest
 
Posts: n/a
#10: Aug 19 '08

re: Factory for Struct-like classes


On Aug 18, 11:16*am, Gabriel Genellina <gagsl-...@yahoo.com.arwrote:
Quote:
On 13 ago, 14:46, eliben <eli...@gmail.comwrote:
>
Quote:
On Aug 13, 7:30*pm, Christian Heimes <li...@cheimes.dewrote:
>
Quote:
Quote:
eliben wrote:
Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?
>
Quote:
Quote:
Try named tuplehttp://code.activestate.com/recipes/500261/
>
Quote:
1) I see this is done with exec anyway, so there's no more pythonic
way.
>
It doesn't *have* to be done with exec - I think there are other
variants using metaclasses instead.
>
Can you suggest an alternative, without exec ?

Eli


Dan Lenski
Guest
 
Posts: n/a
#11: Aug 20 '08

re: Factory for Struct-like classes


On Mon, 18 Aug 2008 08:28:53 -0700, Dan Lenski wrote:
Quote:
So is there a bug in the Python docs? Does __slots__ in fact work with
subclasses of tuple?
>
Dan
Anybody think that this may actually be a mistake in the Python docs? Who
would I contact about getting them corrected?

Dan

Dave Benjamin
Guest
 
Posts: n/a
#12: Aug 21 '08

re: Factory for Struct-like classes


Christian Heimes wrote:
Quote:
eliben wrote:
Quote:
>Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
>does this. I suppose it can be done with 'exec', but is there a more
>Pythonic way ?
>
Try named tuple http://code.activestate.com/recipes/500261/
>
A named tuple implementation is part of Python 2.6 and 3.0. For older
versions of Python use the recipe from activestate.
Whaaa? Named tuples are being added to Python? Neat! Is there any
documentation on this? I can't seem to find anything on the web...

Thanks,
Dave
eliben
Guest
 
Posts: n/a
#13: Aug 21 '08

re: Factory for Struct-like classes


On Aug 21, 4:51*am, Dave Benjamin <ra...@lackingtalent.comwrote:
Quote:
Christian Heimes wrote:
Quote:
eliben wrote:
Quote:
Ruby's 'Scruct' class (http://ruby-doc.org/core/classes/Struct.html)
does this. I suppose it can be done with 'exec', but is there a more
Pythonic way ?
>
Quote:
Try named tuplehttp://code.activestate.com/recipes/500261/
>
Quote:
A named tuple implementation is part of Python 2.6 and 3.0. For older
versions of Python use the recipe from activestate.
>
Whaaa? Named tuples are being added to Python? Neat! Is there any
documentation on this? I can't seem to find anything on the web...
>
It's not easy to find unless you recall where you've seen it:
http://docs.python.org/dev/3.0/libra...ons.namedtuple

Dave Benjamin
Guest
 
Posts: n/a
#14: Aug 21 '08

re: Factory for Struct-like classes


eliben wrote:
Quote:
Quote:
>Whaaa? Named tuples are being added to Python? Neat! Is there any
>documentation on this? I can't seem to find anything on the web...
>
It's not easy to find unless you recall where you've seen it:
http://docs.python.org/dev/3.0/libra...ons.namedtuple
Thanks!
Gabriel Genellina
Guest
 
Posts: n/a
#15: Aug 21 '08

re: Factory for Struct-like classes


En Tue, 19 Aug 2008 12:43:27 -0300, eliben <eliben@gmail.comescribió:
Quote:
On Aug 18, 11:16*am, Gabriel Genellina <gagsl-...@yahoo.com.arwrote:
Quote:
>On 13 ago, 14:46, eliben <eli...@gmail.comwrote:
>>
Quote:
On Aug 13, 7:30*pm, Christian Heimes <li...@cheimes.dewrote:
Try named tuplehttp://code.activestate.com/recipes/500261/
>>
Quote:
1) I see this is done with exec anyway, so there's no more pythonic
way.
>>
>It doesn't *have* to be done with exec - I think there are other
>variants using metaclasses instead.
>Can you suggest an alternative, without exec ?
See these recipes: http://code.activestate.com/recipes/303439/ and 303770
and 303481; read the comments section too.

--
Gabriel Genellina

Closed Thread