Domanda

Perché non i seguenti lavori (Python 2.5.2)?

>>> import datetime
>>> class D(datetime.date):
        def __init__(self, year):
            datetime.date.__init__(self, year, 1, 1)
>>> D(2008)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: function takes exactly 3 arguments (1 given)

Ho voluto creare una classe che era proprio come datetime.date, ma con una funzione __init__ diversa. A quanto pare la mia funzione non viene mai chiamato. Invece il datetime.date.__init__ originale si chiama e non riesce perché si aspetta 3 argomenti e sto passando in uno.

Che cosa sta succedendo qui? Ed è questo un indizio?

>>> datetime.date.__init__
<slot wrapper '__init__' of 'object' objects>

Grazie!

È stato utile?

Soluzione

Per quanto riguarda diverse altre risposte, questo non ha nulla a che fare con date in corso di attuazione in C per sé. Il metodo __init__ non fa nulla perché sono immutabili oggetti, quindi, il costruttore (__new__) dovrebbe fare tutto il lavoro. Si potrebbe vedere lo stesso comportamento int sottoclassi, str, ecc.

>>> import datetime
>>> class D(datetime.date):
        def __new__(cls, year):
            return datetime.date.__new__(cls, year, 1, 1)


>>> D(2008)
D(2008, 1, 1)

Altri suggerimenti

Si prega di leggere il riferimento di Python su Modello di dati , in particolare circa la __new__ speciale metodo .

Estratto da quella pagina (il corsivo è mio):

  

__new__() destinato principalmente a consentire sottoclassi di immutabile tipo (come int, str o tupla) a personalizzare creazione dell'istanza . E 'anche comunemente ignorata in metaclassi personalizzati in modo da personalizzare la creazione di classe.

datetime.datetime è anche un tipo immutabile.

PS Se si pensa che:

  • un oggetto implementato in C non può essere derivata o
  • __init__ non viene chiamato per C implementato oggetti, solo __new__

quindi si prega di provare:

>>> import array
>>> array
<module 'array' (built-in)>
>>> class A(array.array):
    def __init__(self, *args):
        super(array.array, self).__init__(*args)
        print "init is fine for objects implemented in C"

>>> a=A('c')
init is fine for objects implemented in C
>>> 

Ecco la risposta, e una possibile soluzione (utilizzare una funzione o strptime invece di subclassing)

http://www.mail-archive.com /python-list@python.org/msg192783.html

Non Sei funzione non viene bypassato; Python ottiene appena mai al punto in cui sarebbe chiamarlo. Poiché datetime è implementato in C, fa il suo inizializzazione datetime.__new__ non datetime.__init__. Questo perché datetime è immutabile. Si potrebbe presumibilmente aggirare questo sovrascrivendo __new__ invece di __init__. Ma, come altre persone hanno suggerito, il modo migliore è probabilmente non sottoclasse datetime a tutti.

Probabilmente è meglio usare una funzione di fabbrica invece di creare una sottoclasse:

def first_day_of_the_year(year):
  return datetime.date(year, 1, 1)

È possibile avvolgere e aggiungere funzionalità estesa al vostro involucro.

Ecco un esempio:

class D2(object):
    def __init__(self, *args, **kwargs):
        self.date_object = datetime.date(*args, **kwargs)

    def __getattr__(self, name):
        return getattr(self.date_object, name)

Ed ecco come funziona:

>>> d = D2(2005, 10, 20)
>>> d.weekday()
3
>>> dir(d)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattr__',
 '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
 '__weakref__', 'date_object']
>>> d.strftime('%d.%m.%Y')
'20.10.2005'
>>>

Si noti che dir() non elenca gli attributi datetime.dates.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top