extend class: include factories functions inside constructor

aspineux aspineux at gmail.com
Thu Aug 18 17:09:43 CEST 2011


On Aug 18, 4:45 pm, Peter Otten <__pete... at web.de> wrote:
> aspineux wrote:
> > Hi
> > I have a closed class and 2 factories function
>
> > class Data:
> >   def __init__(self):
> >     self.payload=None
>
> > def data_from_string(payload):
> >   data=Data()
> >   data.payload=payload
> >   return data
>
> > def data_from_file(f):
> >   data=Data()
> >   data.payload=f.read()
> >   return data
>
> > And I want to extend the class, by first including the factories
> > function inside the constructor,
> > second add some method to the class.
>
> > class MyData(Data):
>
> >   def __init__(self, arg):
> >     # I know this coke is not working, this is to show you
> >     # what I expect
> >     if isinstance(arg, file):
> >         self=data_from_file(arg)
> >     else:
> >         self=data_from_string(arg)
> >     return self
>
> >   def len(self):
> >     return len(self.payload)
>
> > And how I want to use it
>
> >>>> m=MyData('hello')
> >>>> print m.len()
> > 5
>
> > any idea ?
>
> Assuming that Data is an oldstyle class you can either copy the Data
> instance's state
>
> class MyData(Data):
>     def __init__(self, arg):
>         if hasattr(arg, "read"):
>             factory = data_from_file
>         else:
>             factory = data_from_string
>         obj = factory(arg)
>         self.__dict__.update(obj.__dict__)
>
>     def __len__(self):
>         return len(self.payload)
>
> or use another factory function and manually set the __class__:
>
> class MyData(Data):
>     def __len__(self):
>         return len(self.payload)
>
> def make_mydata(arg):
>     if hasattr(arg, "read"):
>         factory = data_from_file
>     else:
>         factory = data_from_string
>     obj = factory(arg)
>     obj.__class__ = MyData
>     return obj
>
> If Data were a newstyle class you could move the hand-made polymorphism into
> the __new__() method:
>
> class MyData(Data):
>     def __new__(class_, arg):
>         if hasattr(arg, "read"):
>             factory = data_from_file
>         else:
>             factory = data_from_string
>         obj = factory(arg)
>         obj.__class__ = class_
>         return obj
>     def __init__(self, arg):
>         pass
>     def __len__(self):
>         return len(self.payload)
>
> if __name__ == "__main__":
>     m = MyData("hello")
>     print len(m)
>
> Nothing of the above strikes me as pretty. Perhaps we could come up with a
> neater solution if you tell us more about your use-case...

Ops, I clicked send before to finish my post.

Thanks for your quick and very valuable answer.



More information about the Python-list mailing list