2010-11-08 10 views
7

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?

+0

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

+1

@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. –

+1

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

risposta

12

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.

+5

Ci sono esempi di ' - ' produce ''. Ad esempio, prendi 'timedelta = datetime1 - datetime2'. –

16

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 
4

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:

  • Does aggiungendo due date insieme hanno senso? No.
  • L'aggiunta di due volte insieme ha senso? No.
  • L'aggiunta di una data e un'ora insieme ha senso? Sì!
  • L'aggiunta di una data e una togetora di timedelta hanno senso? Può essere.
  • L'aggiunta di un orario e di un timedelta insieme ha senso? Può essere.

e per la sottrazione

  • Does sottraendo due date hanno senso? Sì.
  • La sottrazione due volte ha senso? Sì.
  • Sottrarre un orario da una data ha senso? No.
  • La sottrazione di un timedelta da una data ha senso? Può essere.
  • La sottrazione di un timedelta da un orario ha senso? Può essere.

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.

+0

Sono d'accordo con te su questo. – jsbueno

+0

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 –

+0

@MarkRibau: ottimo punto. Dovresti dare un po 'di carne e renderlo una risposta. –

0

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

  • Se 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 oggetto
  • se dt è 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

1

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.

1

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.

Problemi correlati