22

以下が機能しないのはなぜですか (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)

datetime.dateに似ているが、機能が異なるクラスを作成したかったの__init__です。どうやら私の関数は決して呼び出されません。代わりに、オリジナルdatetime.date.__init__が呼び出されて失敗します。これは、3 つの引数が必要であり、1 つを渡しているためです。

何が起きてる?そして、これは手がかりですか?

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

ありがとう!

4

6 に答える 6

39

他のいくつかの回答に関しては、これは C 自体で実装されている日付とは関係ありません。これらは不変オブジェクトであるため、__init__メソッドは何もしません。したがって、コンストラクター ( ) がすべての作業を行う必要があります。int、str などをサブクラス化しても同じ動作が見られます。__new__

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


>>> D(2008)
D(2008, 1, 1)
于 2008-12-30T15:36:32.373 に答える
11

特に特殊なメソッドについては、データ モデルの Python リファレンスを参照してください。__new__

そのページからの抜粋 (イタリック体):

__new__()主に、不変型 (int、str、または tuple など) のサブクラスがインスタンスの作成をカスタマイズできるようにすることを目的としています。また、クラスの作成をカスタマイズするために、カスタム メタクラスでオーバーライドされることもよくあります。

datetime.datetimeも不変型です。

PSあなたがそう思うなら:

  • C で実装されたオブジェクトをサブクラス化できない、または
  • __init__C で実装されたオブジェクトに対してのみ呼び出されません。__new__

それから試してください:

>>> 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
>>> 
于 2008-12-31T01:19:50.620 に答える
4

これが答えであり、可能な解決策です(サブクラス化の代わりに関数または strptime を使用してください)

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

于 2008-12-29T23:12:44.887 に答える
2

あなたの機能はバイパスされていません。Pythonは、それを呼び出すところまで到達することは決してありません. datetime は C で実装されているため、初期化はdatetime.__new__notで行いdatetime.__init__ます。これは、datetime が不変であるためです。__new__の代わりにオーバーライドすることで、おそらくこれを回避できます__init__。しかし、他の人が示唆しているように、最良の方法はおそらくdatetimeをまったくサブクラス化しないことです。

于 2008-12-30T02:50:29.800 に答える
0

それをラップして、ラッパーに拡張機能を追加できます。

次に例を示します。

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)

そして、これがどのように機能するかです:

>>> 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'
>>>

s 属性dir()をリストしないことに注意してください。datetime.date

于 2008-12-30T07:21:29.907 に答える
0

サブクラスを作成する代わりに、おそらくファクトリ関数を使用する必要があります。

def first_day_of_the_year(year):
  return datetime.date(year, 1, 1)
于 2008-12-29T23:22:00.983 に答える