我有延長內置日期時間一對夫婦類。*覆蓋運營商+,使日期+時間=日期時間在Python
有沒有什麼好的理由不超載+(MyTime.__radd___
),所以指明MyDate +數值指明MyTime返回MyDateTime?
我有延長內置日期時間一對夫婦類。*覆蓋運營商+,使日期+時間=日期時間在Python
有沒有什麼好的理由不超載+(MyTime.__radd___
),所以指明MyDate +數值指明MyTime返回MyDateTime?
這通常會令人不悅,因爲你真的是合併而不是添加;這就是爲什麼實際的日期時間庫有一個combine方法,而不是以這種方式使用添加。
我不知道Python中的任何其他情況,其中<instance of TypeA> + <instance of TypeB>
產生<instance of TypeC>
。因此,Principle of least astonishment建議您應該簡單地提供一個combine
方法而不是超載加法。
有
這是已經實現爲一個類的方法,datetime.datetime.combine
:
import datetime
d = datetime.date(2010, 12, 5)
t = datetime.time(10, 22, 15)
dt = datetime.datetime.combine(d, t)
print dt
打印
2010-12-05 10:22:15
是的,至少有一個很好的理由不來:結果實例是完全不同的兩個輸入實例。這很重要嗎?我不這麼認爲 - 認爲date - date
產量爲timedelta
。
我看到它的方式:
和減法
沿着情理之中的事情了線發展:
date + time => datetime
date + timedelta => date | datetime or exception or silently drop time portion
time + date => datetime
time + timedelta => time | wrap-around or exception
date - date => timedelta
date - timedelta => date | datetime or exception or silently drop time portion
time - time => timedelta
time - timedelta => time | wrap-around or exception
datetime + timedelta => datetime
datetime - timedelta => datetime
所以,如果是我的話,我設計一個日期,時間,日期時間,TimeDelta框架,我會允許:
date + time
date - date
time - time
datetime + timedelta
datetime - timedelta
,併爲這些:
date +/- timedelta
time +/- timedelta
我將默認爲換貨政...如果timedelta沒有其他類型,則會生成相同的類型,如果timedelta確實有其他類型的異常,則會引發異常,但會有一個設置來控制該類型。另一種可能的行爲是放棄不需要的部分 - 所以一個日期加上一個有幾小時的timedelta會減少時間並返回一個日期。
我同意你的意見。 – jsbueno 2012-01-10 21:32:38
或者: 減去兩個日期是有道理的:是的 減去兩次是有意義的:是的 減去日期和時間是有意義的:也許 – 2012-01-11 21:12:00
@MarkRibau:非常好的一點。你應該充實一點,並將其作爲答案。 – 2012-01-11 21:17:52
我想最重要的是功能和效率。當然,使用簡單的+
運算符將更易於使用,但我不確定功能。
如果我們把它比作datetime.combine
,什麼combine
做的是:
dt = date(2011,01,01)
tm = time(20,00)
dtm = datetime.combine(dt, tm)
對於DTM
dt
是一個Date對象,並tm
是一個時間對象,比日期信息取自dt
,時間信息和tzinfo從tm
對象dt
是日期時間對象,比其時間和tzinfo屬性將被忽略。從這個角度來看,與datetime
對象的工作似乎並不簡單對象,但更COMPEX結構與不同勢的屬性,如時區信息。
可能這就是爲什麼datetime
對象有一些額外的功能,用於格式化對象的對象類型和數據結構。
的Python有一個座右銘(類似的東西):
在Python中,沒有什麼是unchangable,如果你知道自己在做什麼。如果沒有,最好留下圖書館功能,因爲它們是...
所以,在我看來,最好是使用combine
是超載+
操作
由於日期,時間和日期時間十字型加法和減法運算符的存在,我認爲這很好,只要它有明確的定義。
目前(2.7.2):
date = date + timedelta
date = date - timedelta
timedelta = date - date
datetime = datetime + timedelta
datetime = datetime - timedelta
timedelta = datetime - datetime
我相信下面的內容也是合理的延期:
timedelta = time - time
datetime = date + time
我會建議以下爲好,但time
具有非常hour
,minute
,second
和microsecond
的特定最小值和最大值,因此需要對數值進行靜態迴繞或返回不同類型:
time = time + timedelta
time = time - timedelta
類似地,date
不能處理添加到它的不到一天的timedelta
。我經常被告知只需使用Duck Typing與Python,因爲這是意圖。 如果是真的,那麼我將提出以下幾點建議完成接口:
[date|datetime] = date + timedelta
[date|datetime] = date - timedelta
timedelta = date - date
[time|timedelta] = time + timedelta
[time|timedelta] = time - timedelta
timedelta = time - time
datetime = datetime + timedelta
datetime = datetime - timedelta
datetime = date + time
datetime = date - time
timedelta = datetime - datetime
timedelta = datetime - date
timedelta = timedelta + timedelta
timedelta = timedelta - timedelta
在其中,因爲date
具有精度損失(爲timedelta
的與部分天)的情況下,被晉升爲datetime
。同樣,如果time
有精確損失(對於產生超過一天結果或負面時間的timedelta
),則將其提升爲timedelta
。 但是,我不太滿意[time|timedelta]
。考慮到並行性和精確視圖的其他接口是有道理的,但我認爲它可能會更優雅,只是將時間環繞到適當的時間,從而將所有[time|timedelta]
的更改爲簡單time
,但不幸的是,這留下了我們失去了精確度。
在我看來,運算符重載最有價值的用途是許多輸入值可以組合的情況。你永遠要處理:
concat(concat(concat("Hello", ", "), concat("World", "!")), '\n');
或
distance = sqrt(add(add(x*x, y*y), z*z));
所以我們重載數學符號創造一個更加直觀的語法。處理這個問題的另一種方法是可變參數函數,如Scheme中的+
。
隨着您的date + time = datetime
,添加datetime + datetime
,datetime + time
或datetime + date
沒有任何意義,所以你永遠不會遇到上述情況。
在我看來,再一次,正確的做法是使用構造函數方法。在像C++這樣具有強大類型的語言中,您將擁有DateTime(const Date &d, const Time &t)
。對於Python的動態類型,我想他們給函數一個名字datetime.combine(date, time)
,以便在代碼中不可見輸入變量的類型時使代碼更清晰。
Haskell typeclass'Number'將'(+)'的算術運算符定義爲'Number a => a - > a - > a'(即接受兩個參數,類型是Number的一個實例並返回該類型)。有時候我希望有其他語言的操作符重載會施加這樣的限制。在Python中,'+'是**加**或**連接**,沒有別的。以完全不相關的方式超載它只會幫助......過度認爲操作員超載的人是eeeevil。爲此使用函數/方法有什麼問題?!? – delnan 2010-11-08 20:43:32
@delnan:沒有錯,這個問題真的是關於重載有什麼問題,以及爲什麼組合日期+時間與添加或並置相比是如此不同的操作。 – 2010-11-08 20:54:59
你可以在'MyDate'中添加'midnight'屬性或方法(返回一個'MyDateTime'),也許可以將MyTime改爲MyTimeSpan,然後再定義'__add__'會更有意義('mydatetime = mydate.midnight + mytimespan')。 – adw 2010-11-08 21:05:45