Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python: Elegant way to adopt class parameters?

Tags:

python

Assume I have many expression similar to

class X:
    def __init__(self, a,b,c,d,e,f):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e
        self.f = f

Is there an elegant way to rewrite this?

Thanks!

like image 412
varantir Avatar asked Apr 20 '26 19:04

varantir


2 Answers

Starting from Python 3.7, It could be done using data classes

@dataclass
class X:
    a: int
    b: str
    c: float
    # etc...

The dataclass decorator automatically generates the suitable __init__ method.


As @Lie Ryan commented, you could also use namedtuple:

>>> X = namedtuple('X', ('a', 'b', 'c'))
>>> x = X(1, 2, 3)
>>> x
X(a=1, b=2, c=3)
>>> x.a
1

It can even be inherited to add or overload methods:

>>> class X(namedtuple('XSuper', ('a', 'b', 'c'))):
...     def __repr__(self):
...         return 'pouet'
...     
>>> x = X(1, 2, 3)
>>> x
pouet
>>> x.a
1

The answer from fountainhead is also a nice version-agnostic trick.

like image 142
Tryph Avatar answered Apr 22 '26 10:04

Tryph


class X:
    def __init__(self, a,b,c,d,e,f):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e
        self.f = f

class X:
    def __init__(self, *args):
        arglist = ['a', 'b', 'c', 'd']
        for i in range(0, len(arglist):
            try:
                setattr(self, arglist[i], args[i])
            except IndexError:
                raise Exception('Arg {} needs to be given a value'.format(arglist[i]))

Does not look like the most elegant thing everbut the longer the list the more simplified, also you only need to modify arglist and it will be reflected. Bad thing, you lose the signature (any non runtime checks you could make are lost, e.g. your IDE will freak out

Other suggestions include enumerate (cleaner way to work with indices).

Or you could just use zip, and do the check at the begginign:

class X:
    def __init__(self, *args):
        arglist = ['a', 'b', 'c', 'd']
        if len(arglist) != len(args):
           raise CustomExceptino('Too few/many arguments...')
        for keyval_tuple in zip(arglist, args):
            setattr(self, keyval_tuple[0], keyval_tuple[1])

Note that you can still add arguments that don't behave this way:

    class X:
        def __init__(self, special_arg, *args):
            self.special_consequence = self.do_sth_with_special_arg(special_arg)
            arglist = ['a', 'b', 'c', 'd']
            if len(arglist) != len(args):
               raise CustomExceptino('Too few/many arguments...')
            for keyval_tuple in zip(arglist, args):
                setattr(self, keyval_tuple[0], keyval_tuple[1])
like image 44
E.Serra Avatar answered Apr 22 '26 10:04

E.Serra