Чистая питоническая композиция с параметрами по умолчанию - PullRequest
0 голосов
/ 02 октября 2018

Предположим, я хочу составить два объекта и хотел бы иметь возможность определять несколько конструкторов, которые соответствуют аргументам по умолчанию.

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

Я хотел бы иметь несколько конструкторов для B, которые позволяют мне либо передать объект A, либо передать параметры, а затем построить A.Глядя на Что такое чистый, pythonic способ иметь несколько конструкторов в Python? Я могу сделать:

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)

Проблема в том, что значения по умолчанию перезаписываются, и яхотелось бы сохранить их. Следующее, конечно, не работает.

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

Так что, похоже, я застрял с запоминанием значений по умолчанию и вызовом их так

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

Это не то, что я хочу, так как я бы предпочел, чтобы объекты сами обрабатывали значения по умолчанию и не были вынуждены запоминать значения по умолчанию.Я мог бы сделать лучше, чем выше, и использовать:

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

Но в этом случае мне все еще нужно «запомнить» значение по умолчанию для z.Есть ли Pythonic решение для этого?Это проблема дизайна?Может кто-нибудь указать мне на хороший шаблон дизайна или лучшие практики?Эта проблема усугубляется при создании нескольких объектов ...

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)

1 Ответ

0 голосов
/ 02 октября 2018

Сначала я бы сказал, что это не то, что вы хотите сделать.По мере увеличения масштабов попытка вызвать ваш конструктор будет утомительной и подверженной ошибкам.

Вы можете решить обе наши проблемы с помощью явного словаря.

class A:
    def __init__(self, config):
        self.x = config.get('x')
        assert self.x  # if you need it
        self.y = config.get('y', 0)

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

    @classmethod
    def from_values(cls,b_config,a_config):
        return cls(b_config, A(a_config))

B.from_values({'w':1, 'z':2}, {'x': 3, 'y': 4})

Возможно, он не такой умныйили аккуратный как то, что вы ищете, но он позволяет вам строить из A, если он у вас уже есть, или передавать настраиваемый набор параметров более структурированным способом.

...