[英]Python classmethod constructor inheritance with different signature
[英]Using a different class definition depending on the constructor signature
這是我的用例:我想定義一個類似元組的對象,但我可以通過屬性名訪問其元素,例如
mytupleobj = TupObj(2012,3)
mytupleobj.year = 2012
mytupleobj.month = 3
Pythons namedtuple
是這個的主要候選者,但問題是參數的數量是固定的。 因此,如果只需要具有年份的元組類對象,我要么必須實現
mytupleobj = TupObj(2012, None)
或者創建一個僅包含年份的名稱元組的新定義。 兩種解決方案看起來都很丑
有沒有辦法 - 使用namedtuple
或其他一些技術 - 以便在我實例化時
mytupleobj = TupObj(2012)
我得到一個類似於元組的對象,它只有屬性year
和我使用時
mytupleobj = TupObj(2012,2)
我得到一個具有year
和month
屬性的類似元組的對象?
您可以在namedtuple
上設置默認值
Python 2.7解決方案:
from collections import namedtuple
tupobj = namedtuple('tupobj', 'year month')
tupobj.__new__.__defaults__ = (None,) * len(tupobj._fields)
t1 = tupobj(2012)
print(t1)
# >> tupobj(year=2012, month=None)
print(t1.year)
# >> 2012
t2 = tupobj(year=2012)
print(t2)
# >> tupobj(year=2012, month=None)
print(t2.year)
# >> 2012
t3 = tupobj(month=1)
print(t3)
# >> tupobj(year=None, month=1)
print(t3.month)
# >> 1
t4 = tupobj(2012, 1)
print(t4)
# >> tupobj(year=2012, month=1)
print(t4.year)
# >> 2012
print(t4.month)
# >> 1
Python 3.7解決方案:
from collections import namedtuple
tupobj = namedtuple('tupobj', 'year month', defaults=(None,None))
t1 = tupobj(2012)
print(t1)
# >> tupobj(year=2012, month=None)
print(t1.year)
# >> 2012
t2 = tupobj(year=2012)
print(t2)
# >> tupobj(year=2012, month=None)
print(t2.year)
# >> 2012
t3 = tupobj(month=1)
print(t3)
# >> tupobj(year=None, month=1)
print(t3.month)
# >> 1
t4 = tupobj(2012, 1)
print(t4)
# >> tupobj(year=2012, month=1)
print(t4.year)
# >> 2012
print(t4.month)
# >> 1
您不需要不同的類定義。 如果沒有傳入month
值,您只想使用屬性的默認值使這些參數可選 。 namedtuple()
工廠函數不支持該用例。
但這不是創建命名元組的唯一方法。 您還可以子類化typing.NamedTuple
:
from typing import NamedTuple, Optional
class VagueTimePeriod(NamedTuple):
year: int
month: Optional[int] = None
這是一個命名元組的類定義,其中month
是可選的,如果你沒有指定一個月它將保留為默認值:
>>> VagueTimePeriod(2012)
VagueTimePeriod(year=2012, month=None)
>>> VagueTimePeriod(2012, 3)
VagueTimePeriod(year=2012, month=3)
但是,我懷疑你真正想要的是一個數據類 。 一個簡單的類,主要是持有一些數據。
Python 3.7有新的dataclasses
模塊 ,或者你可以安裝attrs
項目 。 數據類可以具有可選屬性(默認為您在定義時聲明的值):
from dataclasses import dataclass
from typing import Optional
@dataclass
class VagueTimePeriod:
year: int
month: Optional[int] = None
vtp1 = VagueTimePeriod(2012)
vtp2 = VagueTimePeriod(2012, 3)
數據類為您提供了極大簡化的語法來定義一個小類,它帶有表示,相等測試和可選的排序支持,散列和不變性。
數據類也完全支持繼承,而元組則沒有。
數據類不能自動迭代或不可變,但可以這樣做,請參閱我之前的答案 ,其中我定義了一個簡單的DataclassSequence
基類,它添加了序列行為。
快速演示:
>>> @dataclass(frozen=True)
... class VagueTimePeriod:
... year: int
... month: Optional[int] = None
...
>>> VagueTimePeriod(2012)
VagueTimePeriod(year=2012, month=None)
VagueTimePeriod(2012, 3)
VagueTimePeriod(year=2012, month=3)
如果你的目標是從OOP角度看一個易於理解的實現,你只需要處理條件並傳遞值的默認參數,在init期間檢查它們的條件值。 它可能看起來像這樣:
class mydatetimeclass():
def __init__(self, year, month=None, day=None):
self.year = year
if month is not None:
self.month = month
if day is not None:
self.day = day
obj1 = mydatetimeclass(2016)
obj1.year #2016
obj2 = mydatetimeclass(2017, 5)
obj2.year #2017
obj2.month #5
實現/維護方法的另一個清理方法是將默認值保存為None,這樣您就不必擔心每個對象中實際存在哪些屬性。
class mydatetimeclass():
def __init__(self, year, month=None, day=None):
self.year = year
self.month = month #sets to None by default
self.day = day
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.