2011-11-30 9 views
9

मैं सिर्फ देखा आप अजगर में ऐसा है कि कर सकते हैं:क्या पाइथन में वर्गीकृत विधियां कुछ भी उपयोगी हैं?

def f(self): 
    print self.name 

class A: 
    z=f 
    name="A" 

class B: 
    z=f 
    name = "B" 

...

print a.z() 

>>> A 

दूसरे शब्दों में, f() बर्ताव करता है एक विधि है कि किसी भी वर्ग पर परिभाषित नहीं है की तरह है, लेकिन करने के लिए जोड़ा जा सकता है एक। और निश्चित रूप से यह एक रनटाइम त्रुटि उत्पन्न करेगा यदि यह उस ऑब्जेक्ट पर विधियों या फ़ील्ड की अपेक्षा करता है जो उससे जुड़ा हुआ है, जो मौजूद नहीं है।

मेरा प्रश्न: क्या यह उपयोगी है? क्या यह एक उद्देश्य प्रदान करता है? क्या ऐसी परिस्थितियां हैं जहां यह समस्या हल करती है? शायद यह इंटरफेस को परिभाषित करने का एक तरीका है?

उत्तर

6

से विस्तार पढ़ हाँ, यह उपयोगी है और प्रस्तुत करते है एक उद्देश्य है, लेकिन ऐसा करना भी दुर्लभ है। यदि आपको लगता है कि आपको परिभाषित किए जाने के बाद कक्षाओं को पैच करने की आवश्यकता है तो आपको हमेशा रोकना चाहिए और विचार करना चाहिए कि यह वास्तव में सबसे अच्छा तरीका है या नहीं।

एक स्थिति बंदर-पैचिंग है।मैं एक बड़ी प्लोन प्रणाली जहां कुछ तरीकों मामूली बदलाव की जरूरत है लेकिन वहाँ तो बस किसी भी आसान तरीका सामान्य रूप से व्यवहार को ओवरराइड करने के लिए नहीं था में यह कर दिया है। उस स्थिति में जहां आपके पास जटिल पुस्तकालय है, यह मूल पुस्तकालय को बदलने के बिना नए या संशोधित व्यवहार को इंजेक्ट करने का एक आसान तरीका प्रदान करता है।

अन्य स्थिति यह है कि मन में स्प्रिंग्स है जब आप तरीकों कि स्वचालित रूप से उत्पन्न किया जा सकता है की एक बहुत कुछ करना चाहते हैं। जैसे डेटा संचालित परीक्षण।

def createTest(testcase, somedata, index): 
    def test(self): 
     "Do something with somedata and assert a result" 
    test_name = "test_%d" % index 
    setattr(testcase, test_name, test) 

for index, somedata in enumerate(somebigtable): 
    createTest(MyTestCase, somedata, index) 

जब MyTestCase एक unittest.TestCase है आप एक परीक्षण है कि डेटा के सभी के माध्यम से चला जाता है हो सकता है, लेकिन यह पहली असफलता पर बंद हो जाता है और आप की तुलना में जो डेटा की लाइन में विफल रहा है यह पता लगाने की कोशिश करने के लिए है। गतिशील रूप से विधियों को बनाकर सभी परीक्षण अलग-अलग चलते हैं और परीक्षण का नाम आपको बताता है कि कौन सा विफल रहा है (ऊपर दिए गए कोड का मूल वास्तव में कुछ डेटा और साथ ही इंडेक्स से अधिक अर्थपूर्ण नाम भी बनाया गया है)।

आप कोई रास्ता नहीं या तो कक्षा या उसके शब्दकोश संदर्भित करने के लिए इससे पहले कि परिभाषा पूरा हो गया है, क्योंकि वर्ग के शरीर के अंदर ऐसा नहीं कर सकते। आप फिर भी एक metaclass है कि आप कक्षा में ही बनाने से पहले वर्ग dict को संशोधित करने और कभी कभी उस चीज़ का एक ही तरह करने का एक क्लीनर तरीका है की सुविधा देता है के रूप में के साथ इसी तरह कुछ कर सकते हैं।

नोट करने के लिए दूसरी बात यह है कि स्थितियों में, जहां इस काम नहीं करेगा देखते हैं है। के बाद वर्ग बना दिया गया है कुछ __xxx__ विशेष तरीकों ओवरराइड नहीं किया जा सकता है: मूल परिभाषा आंतरिक रूप से वर्ग के __dict__ तो कोई भी परिवर्तन आप बाद में बनाने अनदेखी हो सकती है के अलावा कहीं अन्य सहेजा गया है। अगर मेटाक्लास के साथ काम करना भी कभी-कभी अतिरिक्त कार्यों को मेटाक्लास क्लास परिभाषा के हिस्से के रूप में विशेषताओं को जो भी उपचार देता है, वह नहीं मिलेगा।

+0

दिलचस्प! यह भी संकेत देता है कि एक और मूल्य उन तरीकों की परिभाषा को आगे बढ़ा सकता है जो कक्षा के लिए कहीं भी केंद्रीय नहीं हैं। जाहिर है विशेष परिस्थितियों के लिए। –

2

रोचक तथ्य: अजगर में

  1. समारोह एक प्रकार है:

    type(f) # prints <type: function> 
    
  2. तो, समारोह एक प्रतिदेय उदाहरण है, इसलिए इसे कहीं भी खामियों को दूर किया जा सकता है।

  3. इसका उपयोग पोर्टेबल बनाने और प्लग और प्ले कार्यक्षमता अनुकरण करने के लिए किया जा सकता है। विभिन्न लॉजिक्स आज़माने के लिए (विभिन्न कार्यों में प्लग इन करके)

  4. यह तर्क से अधिक अमूर्त प्रदान करता है के बाद से हम आयातित कार्यों के साथ वर्ग के तरीकों की जगह ले सकता -

  5. इस विकास के दौरान वास्तव में काम हो सकता है।

हालांकि, मुझे संदेह है कि आप इंटरफेसिंग अनुकरण करने के लिए इसका उपयोग कैसे करेंगे!

3

क्योंकि फ़ंक्शन ऑब्जेक्ट्स में __get __ (...) विधि है, यह एक गैर-डेटा वर्णनकर्ता है।

जब आप कक्षा एक में एक विधि को परिभाषित है, यह एक .__ dict__ में सिर्फ एक समारोह वस्तु है:

In [78]: class A(object): 
    ....:  def f1(self): 
    ....:   pass 
    ....: 

In [79]: A.__dict__["f1"] 
Out[79]: <function f1 at 0x0D39A070> 

लेकिन जब आप विशेषता के आधार पर उदाहरण या वर्ग से इस समारोह मिलता है, आप विधि या अनबाउंड विधि बाध्य हो ।

In [80]: A.f1 
Out[80]: <unbound method A.f1> 

In [81]: A().f1 
Out[81]: <bound method A.f1 of <__main__.A object at 0x0D2F1CD0>> 

इस तरह विधि विधि काम करती है। तो, आप विधि बाद में जोड़ सकते हैं:

In [82]: A.f2 = lambda self: id(self) 

In [83]: A().f2() 
Out[83]: 221189392 

तो अपने कोड लगभग एक ही है के रूप में:

class A: 
    def z(self): 
     print self.name 
    name="A" 

कृपया http://docs.python.org/howto/descriptor.html

+0

हां, लेकिन क्या यह मुहावरे कुछ भी उपयोगी है? –

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