Ho un paio di classi estendono datetime incorporato. *Override operatore + per rendere la data + tempo = datetime in Python
C'è un buon motivo per non sovraccaricare + (MyTime.__radd___
) in modo MyDate + MyTime restituisce un MyDateTime?
Ho un paio di classi estendono datetime incorporato. *Override operatore + per rendere la data + tempo = datetime in Python
C'è un buon motivo per non sovraccaricare + (MyTime.__radd___
) in modo MyDate + MyTime restituisce un MyDateTime?
Questo in genere sarebbe disapprovato perché si combina davvero piuttosto che aggiungere; questo è il motivo per cui la libreria datetime effettiva ha un metodo combine piuttosto che l'aggiunta in questo modo.
Non sono a conoscenza di altri casi in Python in cui <instance of TypeA> + <instance of TypeB>
produce <instance of TypeC>
. Pertanto, Principle of least astonishment suggerisce di fornire semplicemente un metodo combine
anziché l'aggiunta di sovraccarico.
Ci sono esempi di '
Questo è già implementata come un metodo di classe, 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
stampe
2010-12-05 10:22:15
sì, c'è almeno una buona ragione per non: l'istanza risultante è completamente diverso da quello due istanze di input. È importante? Io non la penso così - considera che date - date
produce timedelta
.
Il mio modo di vedere:
e per la sottrazione
Sviluppare sulla falsariga di ciò che ha senso:
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
Quindi, se mi fosse ed io stavamo progettando un data, ora, DateTime, quadro timedelta, mi avrebbe permesso:
date + time
date - date
time - time
datetime + timedelta
datetime - timedelta
e per questi:
date +/- timedelta
time +/- timedelta
avrei default retu lo stesso tipo se timedelta non aveva nessuno dell'altro tipo e sollevava un'eccezione se timedelta aveva qualche altro tipo, ma ci sarebbe stata un'impostazione che lo avrebbe controllato. L'altro comportamento possibile sarebbe quello di eliminare la parte non necessaria - quindi una data combinata con una timedelta che avrebbe avuto ore avrebbe lasciato cadere le ore e restituire una data.
Sono d'accordo con te su questo. – jsbueno
In alternativa: La sottrazione di due date ha senso: Sì La sottrazione due volte ha senso: Sì Sottrarre una data e un'ora ha un senso: Forse –
@MarkRibau: ottimo punto. Dovresti dare un po 'di carne e renderlo una risposta. –
Immagino che le cose più importanti siano la funzionalità e l'efficienza. Ovviamente usare un semplice operatore +
sarà più facile da usare, ma non sono sicuro della funzionalità.
Se lo paragoniamo a datetime.combine
, cosa combine
fare è:
dt = date(2011,01,01)
tm = time(20,00)
dtm = datetime.combine(dt, tm)
Per DTM
dt
è un oggetto di data e tm
è un oggetto di tempo, di data informazioni sono prese da dt
, tempo informazioni e tzinfo è tratta dalla tm
oggettodt
è un oggettodatetime, rispetto al suo tempo e tzinfo attributi verranno ignorati.Da questo punto di vista, lavorando con datetime
oggetti non sembrano essere oggetti semplici, ma strutture più Compex con attributi diffrent, come informazioni fuso orario.
Probabilmente questo è il motivo per cui gli oggetti datetime
dispongono di alcune funzioni aggiuntive utilizzate per la formattazione del tipo di oggetto e della struttura dati dell'oggetto.
Python hanno un motto (qualcosa di simile):
In Python, nulla è immutabile, se si sa cosa si sta facendo. In caso contrario, è meglio lasciare le funzioni della libreria così come sono ...
Quindi, a mio parere, è meglio utilizzare combine
che il sovraccarico +
operatore
causa l'esistenza degli operatori di data, ora e datetime tipo a croce di addizione e sottrazione, penserei che questo va bene, purché sia ben definito.
Attualmente (2.7.2):
date = date + timedelta
date = date - timedelta
timedelta = date - date
datetime = datetime + timedelta
datetime = datetime - timedelta
timedelta = datetime - datetime
Credo che la segue è anche ragionevole una proroga:
timedelta = time - time
datetime = date + time
Stavo per suggerire quanto segue pure, ma time
ha molto valori minimi e massimi specifici per hour
, minute
, second
e microsecond
, che richiedono quindi un avvolgimento silenzioso di valori o il ritorno di un tipo diverso:
time = time + timedelta
time = time - timedelta
Analogamente, date
non è in grado di gestire un timedelta
meno di un giorno aggiunto ad esso. Spesso mi è stato detto semplicemente: usa Duck Typing con Python, perché è questo l'intento. Se questo è vero, allora proporrei la seguente interfaccia completato:
[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
In cui, dato il caso che date
ha una perdita di precisione (per timedelta
's con giorni parziali), è promosso a datetime
. Allo stesso modo, dato che time
ha una perdita di precisione (per timedelta
che produce un risultato di più di un giorno o tempo negativo), viene promosso a timedelta
. Tuttavia,, non mi sento completamente a mio agio con [time|timedelta]
. Ha senso dato il resto dell'interfaccia dal parallelismo e dalle viste precise, ma penso che potrebbe essere più elegante avvolgere il tempo all'ora giusta, cambiando quindi tutti gli [time|timedelta]
in time
, ma sfortunatamente questo ci lascia con precisione persa.
A mio parere, gli usi più importanti dell'overloading dell'operatore sono situazioni in cui è possibile combinare molti valori di input. Faresti mai vuole affrontare:
concat(concat(concat("Hello", ", "), concat("World", "!")), '\n');
o
distance = sqrt(add(add(x*x, y*y), z*z));
Così abbiamo sovraccaricare simboli matematici per creare una sintassi più intuitiva. Un altro modo per affrontare questo problema sono le funzioni variadic, come +
in Scheme.
Con il vostro date + time = datetime
, che non ha senso aggiungere datetime + datetime
, datetime + time
o datetime + date
, così si potrebbe mai incontrare una situazione come quelli sopra.
A mio parere, ancora una volta, la cosa giusta è utilizzare un metodo di costruzione. In una lingua con una forte digitazione come C++, avresti DateTime(const Date &d, const Time &t)
. Con la digitazione dinamica di Python, immagino che abbiano dato alla funzione un nome, datetime.combine(date, time)
, per rendere il codice più chiaro quando i tipi delle variabili di input non sono visibili nel codice.
Il 'Numero' typeclass Haskell definisce operatori aritmetici come' (+) 'come' Numero a => a -> a -> a' (vale a dire accetta due argomenti con un tipo che è un'istanza di 'Numero' e restituisce esattamente quel tipo). A volte desidero che altre lingue con sovraccarico dell'operatore impongano tali restrizioni. In Python, '+' è o ** aggiunta ** o ** concatenazione **, nient'altro. Sovraccaricarlo in una questione completamente indipendente aiuta solo ... le persone overzealus che credono che il sovraccarico dell'operatore sia eeeevile. Cosa c'è di sbagliato nell'usare una funzione/metodo per questo?!? – delnan
@delnan: niente di sbagliato, la vera domanda era su cosa c'è di sbagliato nell'overloading e perché combinare una data + ora è un'operazione così distinta dall'aggiunta o dalla concatenazione. –
Si potrebbe aggiungere una proprietà o un metodo 'midnight' a' MyDate' (restituendo un 'MyDateTime'), e magari cambiare' MyTime' in 'MyTimeSpan', quindi definire' __add__' ha più senso ('mydatetime = mydate.midnight + mytimespan'). – adw