Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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'

like image 624
RandomNumberFun Avatar asked Jan 11 '19 05:01

RandomNumberFun


People also ask

What does @dataclass do in python?

Python introduced the dataclass in version 3.7 (PEP 557). The dataclass allows you to define classes with less code and more functionality out of the box.

Can python Dataclasses have methods?

A dataclass can very well have regular instance and class methods. Dataclasses were introduced from Python version 3.7. For Python versions below 3.7, it has to be installed as a library.

What is __ Post_init __ python?

Modifying fields after initialization with __post_init__ The __post_init__ method is called just after initialization. In other words, it is called after the object receives values for its fields, such as name , continent , population , and official_lang .


1 Answers

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']))
like image 184
Arne Avatar answered Sep 23 '22 03:09

Arne