2008-12-29 22 views
18

निम्नलिखित कार्य क्यों नहीं करता है (पायथन 2.5.2)?मैं datetime.date subclass क्यों नहीं कर सकता?

>>> 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 तर्कों की अपेक्षा करता है और मैं एक में गुजर रहा हूं।

यहां क्या हो रहा है? और यह एक सुराग है?

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

धन्यवाद!

+0

यह भी देखें http://stackoverflow.com/questions/309 12 9/क्यों-कैंट-आई-वारिस-टू-डॉट-एंड-अपवाद-इन-पायथन – hop

उत्तर

34

कई अन्य उत्तरों के संबंध में, सी से प्रति में लागू होने वाली तिथियों के साथ इसका कोई संबंध नहीं है। __init__ विधि कुछ भी नहीं है क्योंकि वे अपरिवर्तनीय ऑब्जेक्ट्स हैं, इसलिए कन्स्ट्रक्टर (__new__) सभी काम करना चाहिए। आप एक ही व्यवहार उपवर्गीकरण पूर्णांक, str, आदि

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


>>> D(2008) 
D(2008, 1, 1) 
+0

मुझे आशा है कि आपको थोड़ा जोर नहीं मिलेगा। – tzot

+0

ग्रेट उत्तर, मैं वास्तव में पहले इस पर अस्पष्ट था लेकिन अब यह सही समझ में आता है। – Kiv

4

यहाँ जवाब है, और एक संभव समाधान

http://www.mail-archive.com/[email protected]/msg192783.html

+0

धन्यवाद, समस्या का लिंक पैसे पर सही है, लेकिन कोई स्पष्टीकरण नहीं है __why__ यह काम नहीं करता है। समस्या की जड़ क्या है और इसे दूर किया जा सकता है? – Arkady

0

आप शायद एक उपवर्ग बनाने के बजाय एक कारखाने समारोह का उपयोग करना चाहिए (एक समारोह या उपवर्गीकरण के बजाय strptime का उपयोग करें):

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

हाँ, यह अच्छा है, लेकिन मुझे उत्सुकता है कि सबक्लासिंग क्यों काम नहीं करती है (यह एक विस्तार वर्ग कैसे अंतर करता है) और क्या इसे दूर किया जा सकता है ... – Arkady

2

आप कार्य कर रहे हैं नहीं जा रहा है; पायथन सिर्फ उस बिंदु पर नहीं जाता है जहां यह इसे कॉल करेगा। चूंकि डेटाटाइम सी में लागू किया गया है, इसलिए इसकी शुरुआत datetime.__new__datetime.__init__ में नहीं है। ऐसा इसलिए है क्योंकि डेटाटाइम अपरिवर्तनीय है। __init__ के बजाय आप शायद __new__ ओवरराइड करके इसे प्राप्त कर सकते हैं। लेकिन जैसा कि अन्य लोगों ने सुझाव दिया है, शायद सबसे अच्छा तरीका शायद समय-समय पर उप-वर्गीकरण नहीं कर रहा है।

+1

@ बेंजामिन: कृपया मेरा उत्तर जांचें, और सही करने पर विचार करें तुम्हारा, क्योंकि अब तक यह सबसे ज्यादा वोट दिया गया है; मूल रूप से, केवल आपकी अंतिम वाक्य को सहायक माना जा सकता है; दूसरों को गलत जानकारी दी गई है। साथ ही, कृपया अपने "यह" → "इसकी" और "(नहीं" → "(नोट" – tzot

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

ध्यान दें कि dir()datetime.date रों विशेषताओं की सूची नहीं है।

+0

@ ΤΖΩΤΖΙΟΥ: आप सही हैं। यह वास्तव में सबक्लासनीय है। मैं दस्तावेज़ों पर वापस जाऊंगा और पता लगाऊंगा कि मैंने कहां बनाया इस गलती। इस बीच मैं जवाब तय कर रहा हूं। धन्यवाद। – muhuk

10

कृपया Data model पर पायथन संदर्भ पढ़ा देखना होगा, विशेष रूप से के बारे में __new__special method। उस पृष्ठ से

अंश (मेरी इटैलिक):

__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

datetime.datetime भी अपरिवर्तनीय प्रकार है।

पी एस यदि आपको लगता है कि:

  • एक वस्तु सी में लागू subclassed नहीं किया जा सकता, या
  • __init__ सी के लिए बुलाया नहीं प्राप्त करता है कार्यान्वित वस्तुओं, केवल __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 
>>> 
+0

उपरोक्त, क्योंकि ऐसा प्रलेखन लिंक के साथ SO पर एकमात्र उत्तर लगता है। लेकिन आपका उदाहरण टूटा हुआ है। यह केवल इसलिए काम करता है क्योंकि प्रारंभकर्ता एक वैकल्पिक तर्क है। 'ए = ए (' सी ', [], 5,8)' – mkiever

+0

' >>> a = array.array ('c', [], 5, 8) ट्रेसबैक (सबसे हालिया कॉल अंतिम): फ़ाइल "", पंक्ति 1, टाइप एरर: सरणी() में अधिकतम 2 तर्क (4 दिए गए) >>> एक = एक ('सी', [], 5, 8) Traceback (सबसे हाल कॉल पिछले): में लेखन त्रुटि फ़ाइल "", लाइन 1,: सरणी() ज्यादा से ज्यादा 2 तर्क लेता है (4 दिया गया) ' गैर-टूटा हुआ उदाहरण क्या होगा? @mkiever – tzot

संबंधित मुद्दे