extend class: include factories functions inside constructor

A

aspineux

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
5

any idea ?

Alain
 
P

Peter Otten

aspineux said:
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

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...
 
A

aspineux

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__:

Exactly what I was looking for

The magic is in self.__dict__.update(obj.__dict__) :)

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

I don't want to replace 2 factories by one !
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)

Very nice, I wahad no solution for newer style class. Thanks
 
A

aspineux

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.
 

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