Factory for Struct-like classes

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • eliben

    Factory for Struct-like classes

    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__.u pdate(entries)

    Which allows:

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

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


  • Michele Simionato

    #2
    Re: Factory for Struct-like classes

    On Aug 13, 6:43 pm, eliben <eli...@gmail.c omwrote:
    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__.u pdate(entries)
    >
    Which allows:
    >
    john = Struct(name='jo hn doe', salary=34000)
    print john.salary
    >
    But what I'm asking for is somewhat more general.

    NamedTuples: http://code.activestate.com/recipes/303439/

    Comment

    • Christian Heimes

      #3
      Re: Factory for Struct-like classes

      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 ?

      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

      Comment

      • eliben

        #4
        Re: Factory for Struct-like classes

        On Aug 13, 7:30 pm, Christian Heimes <li...@cheimes. dewrote:
        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 ?
        >
        Try named tuplehttp://code.activestat e.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 ?

        Comment

        • Marc Christiansen

          #5
          Re: Factory for Struct-like classes

          eliben <eliben@gmail.c omwrote:
          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(*fiel ds):
          class Struct(object):
          def __init__(self, *contents):
          if len(contents) != len(self.struct fields):
          raise TypeError(
          "wrong number of arguments: expected %d %s, got %d" %
          (len(self.struc tfields),
          repr(self.struc tfields),
          len(contents)))
          for field, content in zip(self.struct fields, contents):
          setattr(self, field, content)
          Struct.structfi elds = fields
          return Struct

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

          Marc

          Comment

          • Larry Bates

            #6
            Re: Factory for Struct-like classes

            eliben wrote:
            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__.u pdate(entries)
            >
            Which allows:
            >
            john = Struct(name='jo hn 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

            Comment

            • Matthew Wilson

              #7
              Re: Factory for Struct-like classes

              On Thu 14 Aug 2008 11:19:06 AM EDT, Larry Bates wrote:
              eliben wrote:
              >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:
              >Employee = Struct(name, salary)
              I have to do this instead (notice that the args are strings):
              >Employee = Struct('name', 'salary')
              Anyway, here's the code:

              def struct_maker(*a rgs):

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

              # Catch too few/too many args.
              if len(self.arglis t) != len(different_a rgs):
              raise ValueError("I need exactly %d args (%s)"
              % (len(self.argli st), list(self.argli st)))

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

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

              return C

              And here it is in action:

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

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

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

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

              In [100]: matt.invalid_at tribute = 99
              ---------------------------------------------------------------------------
              ValueError: invalid_attribu te ain't in ['name', 'salary']


              Matt

              Comment

              • Gabriel Genellina

                #8
                Re: Factory for Struct-like classes

                On 13 ago, 14:46, eliben <eli...@gmail.c omwrote:
                On Aug 13, 7:30 pm, Christian Heimes <li...@cheimes. dewrote:
                >
                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 ?
                >
                Try named tuplehttp://code.activestat e.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.
                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

                Comment

                • Dan Lenski

                  #9
                  Re: Factory for Struct-like classes

                  On Aug 13, 1:30 pm, Christian Heimes <li...@cheimes. dewrote:
                  Trynamedtupleht tp://code.activestat e.com/recipes/500261/
                  >
                  Anamedtupleimpl ementation 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.
                  >>Person=namedt uple.namedtuple ('Person', ('name', 'age', 'height'))
                  >>p=Person('Bob ', 24, 1.86)
                  >>p.name
                  'Bob'
                  >>p.shoe_size
                  AttributeError: 'Person' object has no attribute 'shoe_size'
                  >>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

                  Comment

                  • eliben

                    #10
                    Re: Factory for Struct-like classes

                    On Aug 18, 11:16 am, Gabriel Genellina <gagsl-...@yahoo.com.a rwrote:
                    On 13 ago, 14:46, eliben <eli...@gmail.c omwrote:
                    >
                    On Aug 13, 7:30 pm, Christian Heimes <li...@cheimes. dewrote:
                    >
                    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 ?
                    >
                    Try named tuplehttp://code.activestat e.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.
                    >
                    Can you suggest an alternative, without exec ?

                    Eli


                    Comment

                    • Dan Lenski

                      #11
                      Re: Factory for Struct-like classes

                      On Mon, 18 Aug 2008 08:28:53 -0700, Dan Lenski wrote:
                      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

                      Comment

                      • Dave Benjamin

                        #12
                        Re: Factory for Struct-like classes

                        Christian Heimes wrote:
                        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 ?
                        >
                        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

                        Comment

                        • eliben

                          #13
                          Re: Factory for Struct-like classes

                          On Aug 21, 4:51 am, Dave Benjamin <ra...@lackingt alent.comwrote:
                          Christian Heimes wrote:
                          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 ?
                          >
                          Try named tuplehttp://code.activestat e.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...
                          >
                          It's not easy to find unless you recall where you've seen it:


                          Comment

                          • Dave Benjamin

                            #14
                            Re: Factory for Struct-like classes

                            eliben wrote:
                            >Whaaa? Named tuples are being added to Python? Neat! Is there any
                            >documentatio n 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!

                            Comment

                            • Gabriel Genellina

                              #15
                              Re: Factory for Struct-like classes

                              En Tue, 19 Aug 2008 12:43:27 -0300, eliben <eliben@gmail.c omescribió:
                              On Aug 18, 11:16 am, Gabriel Genellina <gagsl-...@yahoo.com.a rwrote:
                              >On 13 ago, 14:46, eliben <eli...@gmail.c omwrote:
                              >>
                              On Aug 13, 7:30 pm, Christian Heimes <li...@cheimes. dewrote:
                              Try named tuplehttp://code.activestat e.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.
                              >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

                              Comment

                              Working...