簡體   English   中英

根據構造函數簽名使用不同的類定義

[英]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)

我得到一個具有yearmonth屬性的類似元組的對象?

您可以在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM