I want to initialize a dataclass dictionary with type hint(key should be string, the value should be another dataclass's instances) called usr_orders
that does NOT require user init upon initializing instances. Based on my understanding Optional
is the union(.., None)
, so I went with:
@dataclass
class User:
usr_orders: Optional[Dict[str, BookOrder]] = Dict
But when I try to modify it using key-value I got the following error: TypeError: '_GenericAlias' object does not support item assignment
def update_usr_orders(self, book_order:BookOrder):
self.usr_orders[book_order.order_id] = book_order # book_order: BookOrder is a dataclass instance
This error seems to be caused by the optional Dict definition. But I don't know how to solve this. Does anyone know why I cannot update the usr_orders
? Thanks!
Just to add on to the accepted answer, a note that in Python 3.7+, you can also declare the dataclass using new-style annotations available via a __future__
import. This should allow you to do away with typing
imports in this case.
from __future__ import annotations # This can be removed in Python 3.10+
from dataclasses import dataclass, field
@dataclass
class BookOrder:
id: str
@dataclass
class User:
usr_orders: dict[str, BookOrder] | None = field(default_factory=dict)
def update_usr_orders(self, book_order: BookOrder):
self.usr_orders[book_order.id] = book_order
a = BookOrder('1')
u = User()
u.update_usr_orders(a)
print(u.usr_orders)
You'll need to import a field and use a default_factory
:
from dataclasses import dataclass, field
from typing import Optional, Dict
@dataclass
class BookOrder():
id: str
@dataclass
class User:
usr_orders: Optional[Dict[str, BookOrder]] = field(default_factory=dict)
def update_usr_orders(self, book_order:BookOrder):
self.usr_orders[book_order.id] = book_order
a = BookOrder('1')
u = User()
u.update_usr_orders(a)
print(u.usr_orders)
Part of the issue is that you were using Dict
as a default field for the data class. Dict
is a type hint; I think you were meaning to use dict()
or {}
- however, this would not work. Try it and see for yourself! You'll end up with this error: ValueError: mutable default <class 'dict'> for field usr_orders is not allowed: use default_factory
. This is a dataclass thing where it prevents you from using 1 dictionary for multiple instances.
Further reading
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With