mardi 2 octobre 2018

Clean pythonic composition with default parameters

Suppose I want to compose two objects and I'd like to be able to be able to define multiple constructors that respect the default arguments.

class A:
   def __init__(x,y=0):
       self.x = x
       self.y = y

class B:
    def __init__(w,objA, z=1):
         self.w = w
         self.objA = objA
         self.z = z

I'd like to have multiple constructors for B which allow me to either pass an object A or pass parameters and then construct A. Looking at What is a clean, pythonic way to have multiple constructors in Python? I can do:

class B:
    def __init__(w, objA, z=1):
         self.w = w
         self.objA = objA
         self.z=z

    @classmethod
    def from_values(cls,w,z,x,y):
        objA = A(x,y)
        return cls(w,objA,z)

The problem is that the default values are being overwritten and I'd like to keep them. The following of course does not work.

@classmethod
def from_values(cls,w,x,**kwargs):
    objA = A(x,**kwargs)
    return cls(w,objA,**kwargs)

So it seems I'm stuck with remembering the default values and calling them like this

@classmethod
def from_values(cls,w,x,z=1,y=0):
    objA = A(x,y)
    return cls(w,objA,z)

This is not what I want since I'd rather have the objects themselves handle the default values and not be forced remember the default values. I could do one better than the above and use:

 @classmethod
 def from_values(cls,w,x,z=1,**kwargs):
    objA = A(x,**kwargs)
    return cls(w,objA,z)

But in this case I still need to "remember" the default value for z. Is there a Pythonic solution to this? Is this a design problem? Can someone point me to a good design pattern or best practices? This problem compounds when composing with several objects...

class L:
    def __init__(objM,objN):
        self.objM = objM
        self.objN = objN

    @classmethod
    def from_values(cls, m1,m2,m3,n1,n2):
        objM = M(m1,m2,m3)
        objN = N(n1,n2)
        return cls(objM, objN)

Aucun commentaire:

Enregistrer un commentaire