假设我有以下代码用于处理个人和国家之间的链接:
继承的对象具有正确的类型,但是它的属性
我想要实现的是让
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)
这一切正常运作,但我决定让它更加流畅,以处理不同形式的输入。我还想使用__new__
来确保每次都获得有效的ISO代码,并且希望在这种情况下对象创建失败。因此,我添加了几个继承自此类的新类:
@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')]
这看起来乍一看是可以的,但是我遇到了一个问题:
a = CountryLinkFromISO2(123, 'AW')
print(type(a))
print(a.country)
print(type(a.country))
返回:
<class '__main__.CountryLinkFromISO2'>
AW
<class 'str'>
继承的对象具有正确的类型,但是它的属性
country
只是一个字符串,而不是我所期望的Country
类型。在__new__
中,我放置了打印语句来检查new_obj.country
的类型,在return
行之前是正确的。我想要实现的是让
a
成为CountryLinkFromISO2
类型的对象,继承我对CountryLink
所做的更改,并且它具有从字典countries_by_iso2
中获取的属性country
。我该如何实现这一点?
__new__
而不是__init__
吗?你也可以考虑使用像attrs这样的库。 - Nathaniel Ford__init__
将始终返回类的实例,这不是我想要发生的。我可以有一个引发异常的__init__
,但这意味着每次尝试调用我的代码时都必须将其放入 try/except 块中,这很笨拙并可能导致性能问题。 - EdG