Suppose I have the following code that is used to handle links between individuals and countries:
from dataclasses import dataclass
@dataclass
class Country:
iso2 : str
iso3 : str
name : str
countries = [ Country('AW','ABW','Aruba'),
Country('AF','AFG','Afghanistan'),
Country('AO','AGO','Angola')]
countries_by_iso2 = {c.iso2 : c for c in countries}
countries_by_iso3 = {c.iso3 : c for c in countries}
@dataclass
class CountryLink:
person_id : int
country : Country
country_links = [ CountryLink(123, countries_by_iso2['AW']),
CountryLink(456, countries_by_iso3['AFG']),
CountryLink(789, countries_by_iso2['AO'])]
print(country_links[0].country.name)
This is all working fine, but I decide that I want to make it a bit less clunky to be able to handle the different forms of input. I also want to use __new__
to make sure that we are getting a valid ISO code each time, and I want to object to fail to be created in that case. I therefore add a couple new classes that inherit from this:
@dataclass
class CountryLinkFromISO2(CountryLink):
def __new__(cls, person_id : int, iso2 : str):
if iso2 not in countries_by_iso2:
return None
new_obj = super().__new__(cls)
new_obj.country = countries_by_iso2[iso2]
return new_obj
@dataclass
class CountryLinkFromISO3(CountryLink):
def __new__(cls, person_id : int, iso3 : str):
if iso3 not in countries_by_iso3:
return None
new_obj = super().__new__(cls)
new_obj.country = countries_by_iso3[iso3]
return new_obj
country_links = [ CountryLinkFromISO2(123, 'AW'),
CountryLinkFromISO3(456, 'AFG'),
CountryLinkFromISO2(789, 'AO')]
This appears to work at first glance, but then I run into a problem:
a = CountryLinkFromISO2(123, 'AW')
print(type(a))
print(a.country)
print(type(a.country))
returns:
<class '__main__.CountryLinkFromISO2'>
AW
<class 'str'>
The inherited object has the right type, but its attribute country
is just a string instead of the Country
type that I expect. I have put in print statements in the __new__
that check the type of new_obj.country
, and it is correct before the return
line.
What I want to achieve is to have a
be an object of the type CountryLinkFromISO2
that will inherit changes I make to CountryLink
and for it to have an attribute country
that is taken from the dictionary countries_by_iso2
. How can I achieve this?