2

I have a class that looks like this:

class Product(BaseModel):
    code: str = ...
    discription_one: str = ...
    famille: FamilleProduct
    sou_famille: SouFamileProduct
    parent: ParentProduct
    sou_parent: SouParentProduct
    group: GroupProduct
    sou_group: SouGroupProduct
    reference: Optional[str] = ''
    oem: Optional[str] = ''
    other_code: Optional[str] = ''
    discription_two: Optional[str] = ''
    discription_three: Optional[str] = ''
    remarque: Optional[str] = ''
    marque: Marque
    origine: Country
    unite: UniteProduct
    code_sh: ShCode
    numbre_serie: NumbreSerie
    qr_code: QrProduct
    status: StatusProduct
    product_visible: bool = True
    product_loocked: bool = False
    product_hided: bool = False
    location: LocationProduct
    last_prix_achat: float = 0.00
    pmp_achat: float = 0.00
    prix_achat_devise: List[PrixAchat]
    prix_vente: List[PrixVente]
    tva: TvaProduct
    tax: TaxProduct
    qtt_achat: float = 0.00
    qtt_actuel: float = 0.00
    qtt_vente: float = 0.00
    qtt_min: float = 0.00
    qtt_max: float = 0.00
    qtt_arrivage: float = 0.00
    qtt_cmdfr: float = 0.00
    qtt_cmdcl: float = 0.00
    date_fab: datetime = None
    date_exp: datetime = None
    created_at: datetime = None
    updated_at: datetime = None
    images: List[ImageProduct] = None

When I try to write a function to create this model, I find myself dealing with a function with too many parameters:

def creat_product(self,a: str, b: str, c: None, d: None, e: None, f: None, g: None, h: None, i: str
                    j: str, k: str, l: str, m: str, n: str) -> Product:
    return Product(
        code=a,
        discription_one=b,
        famille=c,
        sou_famille=d,
        parent=e,
        sou_parent=f,
        group=g,
        sou_group=h,
        reference=i,
        oem=j,
        other_code=k,
        discription_two=l,
        discription_three=m,
        remarque=n,...# and other paramaters)

For all the paramaters with None values, is it possible to add them when calling creat_product or keep them None? Is there any other way to do this?

Gino Mempin
  • 25,369
  • 29
  • 96
  • 135
hamza chenni
  • 146
  • 2
  • 18
  • 1
    Related: [Is passing too many arguments to the constructor considered an anti-pattern?](https://stackoverflow.com/q/30599478/2745495) – Gino Mempin Feb 06 '21 at 10:54

1 Answers1

6

You can use **kwargs in order to specify that your function can accept an arbitrary number of arguments. Although this means that you will be able to call the function by providing less arguments than what the Product requires - however any issue will be reported directly from the constructor.

def creat_product(self, **kwargs) -> Product:
   return Product(**kwargs)

And you should be able to call it exactly as before:

self.create_product(a='a', b='b', ...)

Note that in this way, you would be able to call the function by providing a dictionary as an argument. For instance,

my_args = {'a': 'val1', 'b': 'val2', ...}
create_product(**my_args)

As a side note, I guess that create_product is an alternative constructor and thus it makes more sense to change it into a class method:

@classmethod
def creat_product(cls, **kwargs):
    return cls(**kwargs)
Giorgos Myrianthous
  • 36,235
  • 20
  • 134
  • 156
  • 1
    "Note that in this way, you would be able to call the function by providing a dictionary as an argument." - using `**` in the definition isn't actually necessary for that. You can use `**` unpacking at the call site for regular arguments, even if the function definition doesn't use `**`. – user2357112 Feb 06 '21 at 10:57