Search code examples
python-3.xooppython-dataclasses

How can I use a list[customClass] as type with @dataclass in Python 3.7.x


I have the following dataclasses.

@dataclass
class Package:
    '''Class for keeping track of one destination.'''
    _address: []

@dataclass
class Destination:
'''Class for keeping track of a destination.'''
_start: str
_end: str
_distance: float

def __init__(self, param):
    self._start = param[0]
    self._end = param[1]
    self._distance = param[2]

and the following dataclass that calls the above class.

@dataclass
class DestinationContainer:
    '''Class for keeping track of a package destination.
       and all the possible combinations of potential next destination '''
    _package: Package
    _destinations: List[Destination]

    def __init__(self):
        pass

    def addPkg(self,param):
        self._package = param

I get the following error when attempt run the program

TypeError: Parameters to generic types must be types.

I have also tried to call the _destinations member this way.

_destinations: List[Destination] = field(default_factory=list)

Then I get the following error

TypeError: Parameters to generic types must be types.

I have also tried to set the class member as

    _destinations: [] 

And upon inspection of the instance object, there is no list available inside the class.

I also tried.

_destinations: List = field(default_factory=lambda: [])

and I get the following error when attempted to add to the list

AttributeError: 'DestinationContainer' object has no attribute '_destinations'


Solution

  • As Patrick said in the comments, your main problem is that you define your own __init__ functions when using @dataclass. If you delete it and slightly restructure your code, it should work as expected:

    from dataclasses import dataclass
    from typing import List
    
    @dataclass
    class Package:
        _address: List[str]
    
    @dataclass
    class Destination:
        _start: str
        _end: str
        _distance: float
    
    @dataclass
    class DestinationContainer:
        _package: Package
        _destinations: List[Destination]
    
        def addPkg(self, param):
            # sure this shouldn't be "self._package.append(param)"? 
            self._package = param
    
    
    # works
    dc = DestinationContainer(
        Package(['some address']),
        [Destination('s', 'e', 1.0)]
    )
    # also works
    dc.addPkg(Package(['some other address']))