मैं पायथन में विधि अधिभार का उपयोग कैसे करूं?


169

मैं पायथन में विधि अधिभार को लागू करने की कोशिश कर रहा हूं:

class A:
    def stackoverflow(self):    
        print 'first method'
    def stackoverflow(self, i):
        print 'second method', i

ob=A()
ob.stackoverflow(2)

लेकिन आउटपुट है second method 2; इसी तरह:

class A:
    def stackoverflow(self):    
        print 'first method'
    def stackoverflow(self, i):
        print 'second method', i

ob=A()
ob.stackoverflow()

देता है

Traceback (most recent call last):
  File "my.py", line 9, in <module>
    ob.stackoverflow()
TypeError: stackoverflow() takes exactly 2 arguments (1 given)

मैं यह काम कैसे पूरा कर सकता हूं?


39
पायथन में, " विशेषताओं " के एक विशेष सेट के रूप में तरीकों के बारे में सोचें , और किसी वस्तु के लिए दिए गए नाम का केवल एक " विशेषता " (और इस प्रकार एक विधि) हो सकता है। अंतिम विधि किसी भी पिछले तरीकों को अधिलेखित कर देती है । जावा में, विधियाँ प्रथम श्रेणी के नागरिक नहीं हैं (वे "वस्तुओं के गुण" नहीं हैं), बल्कि "संदेश भेजने" द्वारा आह्वान किए जाते हैं जो कि निकटतम प्रकार के आधार पर सांख्यिकीय रूप से हल किए जाते हैं (जो कि ओवरलोडिंग में आता है)।

2
इसके अलावा stackoverflow.com/questions/733264/…
agf


6
इस प्रश्न का कोई भी उत्तर अभी तक क्यों स्वीकार नहीं किया गया है? अपने पसंदीदा उत्तर के बाईं ओर दिए गए चेक मार्क पर क्लिक करें ...
glglgl

जवाबों:


150

यह तरीका है ओवरलोडिंग का तरीका ओवरराइडिंग का नहीं । और अजगर में, आप यह सब एक ही कार्य में करते हैं:

class A:

    def stackoverflow(self, i='some_default_value'):    
        print 'only method'

ob=A()
ob.stackoverflow(2)
ob.stackoverflow()

आपके पास पायथन में एक ही नाम के दो तरीके नहीं हो सकते हैं - और आपको इसकी आवश्यकता नहीं है।

पायथन ट्यूटोरियल का डिफ़ॉल्ट तर्क मान अनुभाग देखें । बचने के लिए एक सामान्य गलती के लिए "कम से कम विस्मय" और म्यूटेबल डिफ़ॉल्ट तर्क देखें ।

संपादित करें : Python 3.4 में नए एकल प्रेषण सामान्य कार्यों के बारे में जानकारी के लिए PEP 443 देखें ।


119
और आपको इसकी आवश्यकता नहीं है - IMHO कुछ समय के लिए यह तरीका बहुत आसान होगा जैसे कि C ++ में जैसे कि ओवरलोडिंग। ठीक है, यह इस अर्थ में 'आवश्यक' नहीं है कि यह अन्य निर्माणों का उपयोग करके नहीं किया जा सकता है - लेकिन यह कुछ चीजों को आसान और सरल बना देगा।
एंड्रियास फ्लोरथ

7
@AndreasFlorath मैं असहमत हूं। बतख टाइपिंग से प्यार करना सीखें और प्रत्येक विधि लिखें, ताकि यह केवल एक ही काम करे, और विधि को ओवरलोड करने की कोई आवश्यकता नहीं है।
एएफएफ

4
+1 करने से पहले मुझे पकड़े जाने से पहले "आम गलती से बचने" के बारे में पढ़ने के लिए
mdup

43
मैं थोड़ा असहमत होना चाहूंगा;) ... ओवरलोडिंग अक्सर कोड क्लीनर बनाते हैं, क्योंकि आप विभिन्न मामलों को संभालने के लिए बहुत सारे if-else स्टेटमेंट के साथ विधि पैक नहीं करते हैं। एक अर्थ में कार्यात्मक भाषाओं का संपूर्ण सरगम ​​समान विचार अर्थात तर्क-पैटर्न-मिलान का उपयोग करता है। जिसका मतलब है कि आपके पास विशाल अपठनीय के बजाय छोटे और अधिक क्लीनर तरीके होंगे।
स्टेन

2
@ user1019129 यह पायथन 3.4 में जोड़े गए एकल प्रेषण जेनेरिक कार्यों का उद्देश्य है, और मेरे उत्तर में जुड़ा हुआ है।
एजीएफ़

62

तुम भी pythonlangutil का उपयोग कर सकते हैं :

from pythonlangutil.overload import Overload, signature

class A:
    @Overload
    @signature()
    def stackoverflow(self):    
        print 'first method'

    @stackoverflow.overload
    @signature("int")
    def stackoverflow(self, i):
        print 'second method', i

6
मुझे लगता है कि यह सवाल का एकमात्र वैध जवाब है। अगर मैं कर सकता तो मैं दोगुना-बढ़ा देता।
माइकल

3
यह अच्छा है, लेकिन यह कच्चे कार्यों पर काम नहीं करता है, बस एक वर्ग के भीतर तरीके।
लेगिट स्टैक

1
@LegitStack वह कार्यक्षमता भी जोड़ी जा सकती है। यह असंभव नहीं है।
एहसान केशवार्ज़ियन

3
@LegitStack I ने GitHub पर कोड अपडेट किया, अब यह फ़ंक्शन के साथ भी काम करता है।
एहसान केशवार्जियन

1
@PaulPrice यह सही है। मैंने अपना उत्तर अपडेट किया और आधिकारिक सहायता अनुभाग को हटा दिया। आप अभी भी मेरे कोड का उपयोग ओवरलोड को भेजने के लिए कर सकते हैं। यह अब दोनों तरीकों और कार्यों के साथ काम करता है। GitHub से कोड को पकड़ो। मैंने अभी तक PyPi को अपडेट नहीं किया है।
एहसान केशवार्जियन

48

पायथन में, आप इस तरह से चीजें नहीं करते हैं। जब लोग जावा जैसी भाषाओं में ऐसा करते हैं, तो वे आम तौर पर एक डिफ़ॉल्ट मान चाहते हैं (यदि वे नहीं करते हैं, तो वे आम तौर पर एक अलग नाम के साथ एक विधि चाहते हैं)। तो, पायथन में, आपके पास डिफ़ॉल्ट मान हो सकते हैं

class A(object):  # Remember the ``object`` bit when working in Python 2.x

    def stackoverflow(self, i=None):
        if i is None:
            print 'first form'
        else:
            print 'second form'

जैसा कि आप देख सकते हैं, आप इसका उपयोग केवल डिफ़ॉल्ट मान रखने के बजाय अलग व्यवहार को ट्रिगर करने के लिए कर सकते हैं।

>>> ob = A()
>>> ob.stackoverflow()
first form
>>> ob.stackoverflow(2)
second form

2
Noneजब आप एक उत्परिवर्ती डिफ़ॉल्ट मान चाहते हैं तो अधिकतर उपयोगी होता है। अलग-अलग व्यवहार अलग-अलग कार्यों में होना चाहिए।
एएफएफ

@agf: Noneवास्तविक डिफ़ॉल्ट मान के रूप में भी उपयोगी हो सकता है।
क्रिस मॉर्गन

हां, लेकिन मैं इसे एक प्रहरी मूल्य के रूप में उपयोग करने की बात कर रहा था, जिसका उपयोग आप अपने उत्तर में करते हैं, और जैसा कि मुझे लगता है कि मेरी टिप्पणी स्पष्ट है।
एएफएफ

आप कहते हैं "आम तौर पर"? क्या आप हमेशा से ऐसा नहीं कर रहे हैं?
जोएल

24

तुम नहीं कर सकते, कभी नहीं की जरूरत है और वास्तव में नहीं करना चाहते हैं।

अजगर में, सब कुछ एक वस्तु है। कक्षाएं चीजें हैं, इसलिए वे वस्तुएं हैं। तो तरीके हैं।

एक ऑब्जेक्ट है जिसे Aएक वर्ग कहा जाता है। इसकी एक विशेषता है stackoverflow। इसकी एक ही विशेषता हो सकती है।

जब आप लिखते हैं def stackoverflow(...): ..., तो क्या होता है कि आप एक वस्तु बनाते हैं जो विधि है, और इसे stackoverflowविशेषता को असाइन करें A। यदि आप दो परिभाषाएँ लिखते हैं, तो दूसरा पहले की जगह ले लेता है, उसी तरह जो असाइनमेंट हमेशा व्यवहार करता है।

इसके अलावा आप उन कोड को लिखना नहीं चाहते हैं, जो उन चीजों के प्रकार का जंगल करता है जो कभी-कभी ओवरलोडिंग के लिए उपयोग किए जाते हैं। यही नहीं भाषा कैसे काम करती है।

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

आप न केवल एक टपल बनाम एक सूची को संभालने के लिए एक अलग से लिख सकते हैं, बल्कि यह भी नहीं चाहते या आवश्यकता नहीं है

आप सभी इस तथ्य का लाभ उठाते हैं कि वे दोनों हैं, उदाहरण के लिए, चलने योग्य (यानी आप लिख सकते हैं for element in container:)। (तथ्य यह है कि वे विरासत से सीधे संबंधित नहीं हैं अप्रासंगिक हैं।)


6
टीबीएच, मैं "कभी ज़रूरत नहीं" के साथ अधिक सावधान रहूंगा। यह एक ऐसी चीज है जिसे किसी भी वास्तविक दुनिया की हर सुविधा पर टैग किया जा सकता है और संपूर्ण प्रोग्रामिंग भाषा को ट्यूरिंग किया जा सकता है, और इसलिए यह एक वैध तर्क नहीं है। जनरेटर की जरूरत किसे है ? कक्षाओं की जरूरत किसे है ? प्रोग्रामिंग भाषाएं कुछ अधिक ठोस चीज़ों के लिए सिंटैक्टिक चीनी हैं।
सेबेस्टियन मच

6
पूरी तरह से असहमत। यह हो सकता है कि आपको "कभी भी" या "कभी नहीं चाहता था" की आवश्यकता हो, लेकिन ऐसे पर्याप्त अनुप्रयोग हैं जहां आप वांछनीय रूप से चाहते हैं। उदाहरण के लिए, एक प्रोग्राम लिखने की कोशिश करें, जो पायथन और सुपीरियर एरेज़ को आपके प्रोग्राम के बिना अपने प्रोग्राम को पूरा करने के इनायत से संभालता हो ...
Elmar Zander

1
मासी के जवाब के आधार पर, मैं कहूंगा कि "आप नहीं कर सकते" अब गलत और अप्रचलित है। @overloadडेकोरेटर के अस्तित्व के आधार पर , मैं कहूंगा कि "वास्तव में नहीं करना चाहता" यकीनन अच्छा है। PEP-3124 से, "... यह वर्तमान में प्राप्त तर्कों के प्रकारों का निरीक्षण करने के लिए पायथन कोड के लिए एक सामान्य विरोधी पैटर्न है ... ऐसा करने का 'स्पष्ट तरीका' प्रकार निरीक्षण द्वारा है, लेकिन यह भंगुर और बंद है विस्तार ... "तो ऐसा लगता है जैसे पर्याप्त लोग चाहते थे, कि यह पायथन का हिस्सा बने।
माइक एस

@ माइक, मानक @overloadकेवल टाइपिंग के लिए है।
नरफानर

@ नरफानर मुझे नहीं पता कि आपकी प्रतिक्रिया मेरी टिप्पणी पर कैसे लागू होती है। क्या आप समझाएँगे?
माइक एस

16

@Agf साथ अभी अतीत में जवाब के साथ था पीईपी-3124 हम अपने वाक्य रचना चीनी मिला है। डेकोरेटर पर विवरण के लिए टाइपिंग प्रलेखन देखें , @overloadलेकिन ध्यान दें कि यह वास्तव में सिंटैक्स चीनी और IMHO है यह सभी लोग कभी भी बहस कर रहे हैं। व्यक्तिगत तौर पर मैं इस बात से सहमत है कि विभिन्न हस्ताक्षर के साथ कई कार्यों होने इसे और अधिक पठनीय तो 20+ तर्क एक डिफ़ॉल्ट मान लिए पूरी तरह तैयार (के साथ एक एकल समारोह होने बनाता है Noneसमय के सबसे अधिक है) और फिर अनंत का उपयोग कर बेला के आसपास होने if, elif, elseचेन पता लगाने के लिए क्या कॉलर वास्तव में चाहता है कि हमारा कार्य तर्कों के प्रदान किए गए सेट के साथ करे। पायथन ज़ेन के बाद यह लंबे समय से अतिदेय था

सुंदर बदसूरत से बेहतर है।

और यकीनन

सरल जटिल से बेहतर है।

ऊपर दिए गए आधिकारिक पायथन प्रलेखन से सीधे:

from typing import overload
@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> Tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    <actual implementation>

वास्तव में मैं क्या देख रहा था, अपने खुद के अतिभार सज्जाकार को परिभाषित करने की तुलना में
बकवास

2
btw: किसी के लिए भी यह सोचते हुए कि यह काम क्यों नहीं कर रहा है, मैं सुझाव देता हूं कि मैं चर्चा में आने के लिए stackoverflow.com/questions/52034771/… पर विचार करूंगा - @overloadकिसी भी वास्तविक कार्यान्वयन के लिए एड फ़ंक्शंस का अनुमान नहीं है। यह पायथन प्रलेखन में उदाहरण से स्पष्ट नहीं है।
मासी

15

मैं अपना जवाब पायथन 3.2.1 में लिखता हूं।

def overload(*functions):
    return lambda *args, **kwargs: functions[len(args)](*args, **kwargs)

यह काम किस प्रकार करता है:

  1. overloadकॉलबल्स की किसी भी राशि को लेता है और उन्हें ट्यूपल में संग्रहीत करता है functions, फिर लैम्ब्डा लौटाता है।
  2. लैम्ब्डा किसी भी प्रकार की बहस करता है, फिर कॉलिंग फ़ंक्शन के रिटर्न functions[number_of_unnamed_args_passed]को लॉम्बडा को दिए गए तर्कों के साथ संग्रहीत किया जाता है।

उपयोग:

class A:
    stackoverflow=overload(                    \
        None, \ 
        #there is always a self argument, so this should never get called
        lambda self: print('First method'),      \
        lambda self, i: print('Second method', i) \
    )

14

मुझे लगता है कि आप जिस शब्द की तलाश कर रहे हैं, वह "ओवरलोडिंग" है। अजगर में ओवरलोडिंग का कोई तरीका नहीं है। हालाँकि, आप डिफ़ॉल्ट तर्कों का उपयोग इस प्रकार कर सकते हैं।

def stackoverflow(self, i=None):
    if i != None:     
        print 'second method', i
    else:
        print 'first method'

जब आप इसे एक तर्क देते हैं तो यह पहली शर्त के तर्क का पालन करेगा और पहले प्रिंट स्टेटमेंट को निष्पादित करेगा। जब आप इसे बिना किसी तर्क के पास कर देंगे, तो यह elseस्थिति में चला जाएगा और दूसरे प्रिंट स्टेटमेंट को निष्पादित करेगा।


13

मैं अपना जवाब पायथन 2.7 में लिखता हूं:

पायथन में, विधि अधिभार संभव नहीं है; यदि आप वास्तव में एक ही फ़ंक्शन को विभिन्न विशेषताओं के साथ एक्सेस करना चाहते हैं, तो मैं आपको विधि ओवरराइडिंग के लिए जाने का सुझाव देता हूं।

class Base(): # Base class
    '''def add(self,a,b):
        s=a+b
        print s'''

    def add(self,a,b,c):
        self.a=a
        self.b=b
        self.c=c

        sum =a+b+c
        print sum

class Derived(Base): # Derived class
    def add(self,a,b): # overriding method
        sum=a+b
        print sum



add_fun_1=Base() #instance creation for Base class
add_fun_2=Derived()#instance creation for Derived class

add_fun_1.add(4,2,5) # function with 3 arguments
add_fun_2.add(4,2)   # function with 2 arguments

9

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

class A:
   def __init__(self, arg)
      # Get the Argument's class type as a String
      argClass = arg.__class__.__name__

      if argClass == 'foo':
         print 'Arg is of type "foo"'
         ...
      elif argClass == 'bar':
         print 'Arg is of type "bar"'
         ...
      else
         print 'Arg is of a different type'
         ...

इस अवधारणा को आवश्यकतानुसार विभिन्न तरीकों से कई अलग-अलग परिदृश्यों पर लागू किया जा सकता है।


7

पायथन में, आप इसे डिफ़ॉल्ट तर्क के साथ करेंगे।

class A:

    def stackoverflow(self, i=None):    
        if i == None:
            print 'first method'
        else:
            print 'second method',i

5

बस इस https://github.com/bintoro/overloading.py के सामने आया किसी को भी दिलचस्पी हो सकती है, उसके लिए ।

लिंक्ड रिपॉजिटरी के रीडमे से:

ओवरलोडिंग एक मॉड्यूल है जो रनटाइम तर्कों के प्रकार और संख्या के आधार पर फ़ंक्शन प्रेषण प्रदान करता है।

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

विशेषताएं

पंजीकरण और विस्तृत रिज़ॉल्यूशन नियमों पर फ़ंक्शन सत्यापन रनटाइम पर एक अद्वितीय, अच्छी तरह से परिभाषित परिणाम की गारंटी देता है। शानदार प्रदर्शन के लिए इम्प्लीमेंटेशन फंक्शन रिज़ॉल्यूशन कैशिंग। फ़ंक्शन हस्ताक्षरों में वैकल्पिक पैरामीटर (डिफ़ॉल्ट मान) का समर्थन करता है। सर्वश्रेष्ठ मैच को हल करते समय स्थिति और कीवर्ड दोनों तर्क का मूल्यांकन करता है। फालबैक फ़ंक्शंस और साझा कोड के निष्पादन का समर्थन करता है। तर्क बहुरूपता का समर्थन करता है। वर्ग और वंशानुक्रम का समर्थन करता है, जिसमें वर्गमठ और स्थैतिक शामिल हैं।


3

अजगर जावा या C ++ की तरह ओवरलोडिंग की विधि का समर्थन नहीं करता है। हम तरीकों को ओवरलोड कर सकते हैं लेकिन केवल नवीनतम परिभाषित विधि का उपयोग कर सकते हैं।

# First sum method.
# Takes two argument and print their sum
def sum(a, b):
    s = a + b
    print(s)

# Second sum method
# Takes three argument and print their sum
def sum(a, b, c):
    s = a + b + c
    print(s)

# Uncommenting the below line shows an error    
# sum(4, 5)

# This line will call the second sum method
sum(4, 5, 5)

हमें कॉल करने पर अलग-अलग संख्या में आर्ग प्रदान करने के लिए वैकल्पिक तर्क या * आर्ग प्रदान करने की आवश्यकता है।

Https://www.geeksforgeeks.org/python-method-overloading/ से सौजन्य


यह ओवरलोडिंग नहीं है। इसे ओवर राइटिंग कहा जाता है। बाद में एक पायथन द्वारा समर्थित है। पहले सज्जाकारों के साथ लागू किया जा सकता है।
पैबेल्स

2

पायथन 3.x में मानक टाइपिंग लाइब्रेरी शामिल है जो @overload डेकोरेटर के उपयोग के साथ विधि अधिभार की अनुमति देती है। दुर्भाग्य से, यह कोड को अधिक पठनीय बनाना है, क्योंकि @overload सजाया तरीकों को गैर-सजाया पद्धति द्वारा पालन करना होगा जो विभिन्न तर्कों को संभालता है। अधिक यहाँ पाया जा सकता है लेकिन आपके उदाहरण के लिए:

from typing import overload
from typing import Any, Optional
class A(object):
    @overload
    def stackoverflow(self) -> None:    
        print('first method')
    @overload
    def stackoverflow(self, i: Any) -> None:
        print('second method', i)
    def stackoverflow(self, i: Optional[Any] = None) -> None:
        if not i:
            print('first method')
        else:
            print('second method', i)

ob=A()
ob.stackoverflow(2)

1
आपके उत्तर के अंत में "द" मुझे लगता है कि आपने अपना उत्तर लिखना समाप्त नहीं किया है। कृपया इसे पूरा करने के लिए अपने उत्तर को संपादित करें।
आर्टजोम बी।

0

MathMethod.py फ़ाइल में

from multipledispatch import dispatch
@dispatch(int,int)
def Add(a,b):
   return a+b 
@dispatch(int,int,int)  
def Add(a,b,c):
   return a+b+c 
@dispatch(int,int,int,int)    
def Add(a,b,c,d):
   return a+b+c+d

मेनडोम फाइल में

import MathMethod as MM 
print(MM.Add(200,1000,1000,200))

हम गुणक का उपयोग करके विधि को अधिभारित कर सकते हैं


इसके लिए मल्टीप्लाइस्पेड पैकेज ( pypi.org/project/multipledispatch ) के उपयोग की आवश्यकता होती है , जो कि अजगर कोर का हिस्सा नहीं है।
एंटनी

0

अजगर ने PEP-3124 के साथ @overload डेकोरेटर को जोड़ा को टाइप इंस्पेक्शन के माध्यम से ओवरलोडिंग के लिए सिंटैक्टिक शुगर प्रदान करने के लिए - इसके बजाय केवल ओवरराइटिंग के साथ काम करना।

PEP-3124 से @overload के माध्यम से ओवरलोडिंग पर कोड उदाहरण

from overloading import overload
from collections import Iterable

def flatten(ob):
    """Flatten an object to its component iterables"""
    yield ob

@overload
def flatten(ob: Iterable):
    for o in ob:
        for ob in flatten(o):
            yield ob

@overload
def flatten(ob: basestring):
    yield ob

@ अधिभार-सज्जाकार द्वारा इसमें रूपांतरित किया जाता है:

def flatten(ob):
    if isinstance(ob, basestring) or not isinstance(ob, Iterable):
        yield ob
    else:
        for o in ob:
            for ob in flatten(o):
                yield ob
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.