__In__ और __call__ में क्या अंतर है?


553

मैं __init__और के बीच का अंतर जानना चाहता हूं__call__ तरीकों के ।

उदाहरण के लिए:

class test:

  def __init__(self):
    self.a = 10

  def __call__(self): 
    b = 20

जवाबों:


754

पहले नव निर्मित वस्तु को इनिशियलाइज़ करने के लिए प्रयोग किया जाता है, और ऐसा करने के लिए उपयोग किए गए तर्क प्राप्त करते हैं:

class Foo:
    def __init__(self, a, b, c):
        # ...

x = Foo(1, 2, 3) # __init__

दूसरा इम्प्लीमेंट फ़ंक्शन कॉल ऑपरेटर।

class Foo:
    def __call__(self, a, b, c):
        # ...

x = Foo()
x(1, 2, 3) # __call__

432
इसलिए, __init__विधि का उपयोग तब किया जाता है जब वर्ग को उदाहरण को इनिशियलाइज़ करने के लिए कहा जाता है, जबकि __call__विधि को कॉल किया जाता है जब इंस्टेंस कहा जाता है
pratikm

1
यह सही लगता है, स्पष्ट रूप से उदाहरण चर को एक उदाहरण के जीवन के दौरान संशोधित किया जा सकता है जो कुछ मामलों में फायदेमंद हो सकता है।
मर्फी

5
वर्ग को इंस्टेंट करते समय init को कहा जाता है: myfoo = Foo (1,4,7.8) कॉल एक टेम्पलेट है जो पहले से ही तत्काल वर्ग को कॉल करने के लिए कुछ करने के लिए कहता है कि कक्षा Foo: \ def __call __ (स्वयं, zzz) फिर, myfoo (12) कक्षा को वह करने के लिए कहता है जो वह वर्ग करता है।
23:12 पर user1270710

1
बस एक ध्यान दें: चूंकि सामान्य रूप से फ़ंक्शन कॉलबेल हैं, वे हमेशा विधि कॉल का समर्थन करते हैं । तो आप फंक्शन को इस तरह भी कह सकते हैं: myFun .__ call __ (arg)
अरिंदम रॉयचौधरी

8
का व्यावहारिक उपयोग क्या है __call__?
मृग्लोम

262

__call__()मेटा-क्लास में एक कस्टम विधि को परिभाषित करने से क्लास के इंस्टेंस को एक फ़ंक्शन के रूप में बुलाया जा सकता है, न कि हमेशा इंस्टेंस को ही संशोधित करना।

In [1]: class A:
   ...:     def __init__(self):
   ...:         print "init"
   ...:         
   ...:     def __call__(self):
   ...:         print "call"
   ...:         
   ...:         

In [2]: a = A()
init

In [3]: a()
call

2
__call__न केवल एक उदाहरण को एक फ़ंक्शन के रूप में उपयोग करने की अनुमति देता है ... यह फ़ंक्शन बॉडी को परिभाषित करता है जिसे एक फ़ंक्शन के रूप में उपयोग किए जाने पर निष्पादित किया जाता है।
आर्थर

85

पायथन में, फ़ंक्शन प्रथम श्रेणी की वस्तुएं हैं, इसका मतलब है: फ़ंक्शन संदर्भों को अन्य कार्यों और / या विधियों के इनपुट में पारित किया जा सकता है, और उनके अंदर से निष्पादित किया जा सकता है।

वर्गों (उर्फ ऑब्जेक्ट्स) के उदाहरणों को माना जा सकता है जैसे कि वे फ़ंक्शन थे: उन्हें अन्य तरीकों / कार्यों के लिए पास करें और उन्हें कॉल करें। इसे प्राप्त करने के लिए,__call__ वर्ग समारोह को विशेष बनाना होगा।

def __call__(self, [args ...]) यह एक इनपुट के रूप में तर्कों की एक चर संख्या लेता है। xकक्षा का एक उदाहरण माना जा रहा है X, x.__call__(1, 2)कॉल करने के लिएx(1,2) या एक समारोह के रूप में उदाहरण के अनुरूप है ।

पायथन में, __init__()क्लास कंस्ट्रक्टर के रूप में ठीक से परिभाषित किया गया है (साथ ही साथ __del__()क्लास डिस्ट्रक्टर)। इसलिए, जो शुद्ध अंतर है __init__()और __call__(): फर्स्ट क्लास अप का एक उदाहरण बनाता है, दूसरी ऐसी उदाहरण बनाता प्रतिदेय के रूप में एक समारोह वस्तु के ही जीवन चक्र को प्रभावित किए बिना किया जाएगा (यानी__call__ निर्माण / विनाश जीवन चक्र को प्रभावित नहीं करता है), लेकिन यह अपनी आंतरिक स्थिति को संशोधित कर सकता है (जैसा कि नीचे दिखाया गया है)।

उदाहरण।

class Stuff(object):

    def __init__(self, x, y, range):
        super(Stuff, self).__init__()
        self.x = x
        self.y = y
        self.range = range

    def __call__(self, x, y):
        self.x = x
        self.y = y
        print '__call__ with (%d,%d)' % (self.x, self.y)

    def __del__(self):
        del self.x
        del self.y
        del self.range

>>> s = Stuff(1, 2, 3)
>>> s.x
1
>>> s(7, 8)
__call__ with (7,8)
>>> s.x
7

2
मैं अवधारणा को समझता हूं, लेकिन इसकी आंतरिक स्थिति को संशोधित करने की विशेष विशेषता नहीं है । यदि हम उपरोक्त कोड को def __call__बस के साथ प्रतिस्थापित करते हैं def update, तो हम कक्षा को एक ऐसा updateतरीका देते हैं जो समान कार्य करता है। अब यह आंतरिक स्थिति को भी संशोधित कर सकता है, यदि नीचे के रूप में कहा जाता है s.update(7, 8)। तो, __call__सिंटैक्टिक्स चीनी तो है?
एलेक्स पोवेल

27

__call__एक वर्ग के उदाहरण को कॉल करने योग्य बनाता है। इसकी आवश्यकता क्यों होगी?

जब ऑब्जेक्ट बनाया __init__जाता है तो तकनीकी रूप से एक बार कॉल किया जाता __new__है, ताकि इसे इनिशियलाइज़ किया जा सके।

लेकिन ऐसे कई परिदृश्य हैं जहां आप अपनी वस्तु को फिर से परिभाषित करना चाहते हैं, कह सकते हैं कि आप अपनी वस्तु के साथ कर रहे हैं, और आपको एक नई वस्तु की आवश्यकता हो सकती है। __call__आप के साथ उसी वस्तु को फिर से परिभाषित कर सकते हैं जैसे कि यह नया था।

यह सिर्फ एक मामला है, कई और भी हो सकते हैं।


9
इस विशिष्ट मामले के लिए, क्या हमें एक नया उदाहरण नहीं बनाना चाहिए? क्या यह एक ही उदाहरण को संशोधित करने और उपयोग करने के लिए किसी तरह से कुशल है।
मर्फी

19
>>> class A:
...     def __init__(self):
...         print "From init ... "
... 
>>> a = A()
From init ... 
>>> a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: A instance has no __call__ method
>>> 
>>> class B:
...     def __init__(self):
...         print "From init ... "
...     def __call__(self):
...         print "From call ... "
... 
>>> b = B()
From init ... 
>>> b()
From call ... 
>>> 

मुझे लगता है कि यह स्वीकृत उत्तर होना चाहिए। यह ठीक उत्तर देता है।
प्रसाद राघवेंद्र

18

__init__को कंस्ट्रक्टर के रूप में माना जाएगा, जहां __call__किसी भी संख्या में वस्तुओं के साथ तरीकों को बुलाया जा सकता है। दोनों __init__और __call__फ़ंक्शन डिफ़ॉल्ट तर्क लेते हैं।


1
__init__एक कंस्ट्रक्टर फ़ंक्शन नहीं __new__है, लेकिन है। __init__के बाद सही कहा जाता है__new__
dallonsi

मुझे लगता __new__है कि वर्ग उदाहरण बनाता है और तर्क के रूप में एक वर्ग प्राप्त करता है, जबकि __init__उदाहरण निर्माता है जो इसे प्राप्त करता है self। यह देखने का एक आसान तरीका कॉल a = Foo(1,2,3)फ़ंक्शन में है जो निर्माण तर्क प्राप्त करेगा __init__
कॉफी_फैन

13

मैं एक उदाहरण का उपयोग करके यह समझाने की कोशिश करूंगा, मान लीजिए कि आप निश्चित श्रृंखला की शर्तों की एक निश्चित संख्या प्रिंट करना चाहते थे। याद रखें कि फंक्शंस श्रृंखला के पहले 2 शब्द 1s हैं। जैसे: १, १, २, ३, ५,,, १३…।

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

उदाहरण के लिए:

class Recorder:
    def __init__(self):
        self._weights = []
        for i in range(0, 2):
            self._weights.append(1)
        print self._weights[-1]
        print self._weights[-2]
        print "no. above is from __init__"

    def __call__(self, t):
        self._weights = [self._weights[-1], self._weights[-1] + self._weights[-2]]
        print self._weights[-1]
        print "no. above is from __call__"

weight_recorder = Recorder()
for i in range(0, 10):
    weight_recorder(i)

आउटपुट है:

1
1
no. above is from __init__
2
no. above is from __call__
3
no. above is from __call__
5
no. above is from __call__
8
no. above is from __call__
13
no. above is from __call__
21
no. above is from __call__
34
no. above is from __call__
55
no. above is from __call__
89
no. above is from __call__
144
no. above is from __call__

यदि आप निरीक्षण करते हैं कि आउटपुट __init__को केवल एक बार कॉल किया गया था, जब पहली बार क्लास को इंस्टेंट किया गया था, बाद में ऑब्जेक्ट पर फिर से इनिशियल किए बिना कॉल किया जा रहा था।


7

आप सज्जाकारों__call__ को लागू करने के पक्ष में विधि का उपयोग भी कर सकते हैं ।

यह उदाहरण पायथन 3 पैटर्न, व्यंजनों और मुहावरों से लिया गया है

class decorator_without_arguments(object):
    def __init__(self, f):
        """
        If there are no decorator arguments, the function
        to be decorated is passed to the constructor.
        """
        print("Inside __init__()")
        self.f = f

    def __call__(self, *args):
        """
        The __call__ method is not called until the
        decorated function is called.
        """
        print("Inside __call__()")
        self.f(*args)
        print("After self.f( * args)")


@decorator_without_arguments
def sayHello(a1, a2, a3, a4):
    print('sayHello arguments:', a1, a2, a3, a4)


print("After decoration")
print("Preparing to call sayHello()")
sayHello("say", "hello", "argument", "list")
print("After first sayHello() call")
sayHello("a", "different", "set of", "arguments")
print("After second sayHello() call")

आउटपुट :

यहाँ छवि विवरण दर्ज करें


4
क्या आप कृपया टेक्स्ट के रूप में आउटपुट कॉपी कर सकते हैं?
सोलोमन उक्यो

इस दृष्टिकोण का क्या मतलब है? आप एक अलग दृष्टिकोण के साथ इसके विपरीत कर सकते हैं?
nealmcb

7

इसलिए, __init__ तब कहा जाता है जब आप किसी भी वर्ग का उदाहरण बना रहे हों और उदाहरण चर को भी आरंभ कर रहे हों।

उदाहरण:

class User:

    def __init__(self,first_n,last_n,age):
        self.first_n = first_n
        self.last_n = last_n
        self.age = age

user1 = User("Jhone","Wrick","40")

तथा __call__ कहा जाता है जब आप किसी अन्य फ़ंक्शन की तरह ऑब्जेक्ट को कॉल करते हैं।

उदाहरण:

class USER:
    def __call__(self,arg):
        "todo here"
         print(f"I am in __call__ with arg : {arg} ")


user1=USER()
user1("One") #calling the object user1 and that's gonna call __call__ dunder functions

1
@Redowan Delowar धन्यवाद ब्रो
आयमुन हुसैन आशिक

4

__init__पायथन वर्गों में एक विशेष विधि है, यह एक वर्ग के लिए निर्माण विधि है। जब भी कक्षा की किसी वस्तु का निर्माण किया जाता है, तो इसे कहा जाता है या हम कह सकते हैं कि यह एक नई वस्तु है। उदाहरण:

    In [4]: class A:
   ...:     def __init__(self, a):
   ...:         print(a)
   ...:
   ...: a = A(10) # An argument is necessary
10

यदि हम A () का उपयोग करते हैं, तो यह एक त्रुटि देगा TypeError: __init__() missing 1 required positional argument: 'a'क्योंकि इसके लिए 1 तर्क की आवश्यकता होती aहै __init__

........

__call__ जब क्लास में लागू किया जाता है, तो हमें फंक्शन कॉल के रूप में क्लास उदाहरण को लागू करने में मदद करता है।

उदाहरण:

In [6]: class B:
   ...:     def __call__(self,b):
   ...:         print(b)
   ...:
   ...: b = B() # Note we didn't pass any arguments here
   ...: b(20)   # Argument passed when the object is called
   ...:
20

यहाँ अगर हम B () का उपयोग करते हैं, तो यह ठीक चलता है क्योंकि इसका __init__यहाँ कोई फ़ंक्शन नहीं है ।


किसी ऑब्जेक्ट को इनिशियलाइज्ड क्लास ऑब्जेक्ट में पास करना। तो एक कॉल करने योग्य वस्तु?
काइस्टो पाइर्ज़

3

__call__मनमाना मूल्यों को वापस करने की अनुमति देता है, जबकि __init__एक निर्माता वर्ग की आवृत्ति को स्पष्ट रूप से वापस करता है। जैसा कि अन्य उत्तरों में ठीक से बताया गया है, __init__केवल एक बार कहा जाता है, जबकि __call__कई बार कॉल करना संभव है , यदि प्रारंभिक उदाहरण मध्यवर्ती चर को सौंपा गया है।

>>> class Test:
...     def __init__(self):
...         return 'Hello'
... 
>>> Test()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: __init__() should return None, not 'str'
>>> class Test2:
...     def __call__(self):
...         return 'Hello'
... 
>>> Test2()()
'Hello'
>>> 
>>> Test2()()
'Hello'
>>> 

3

छोटे और मीठे उत्तर पहले से ही ऊपर दिए गए हैं। मैं जावा के साथ तुलना में कुछ व्यावहारिक कार्यान्वयन प्रदान करना चाहता हूं।

 class test(object):
        def __init__(self, a, b, c):
            self.a = a
            self.b = b
            self.c = c
        def __call__(self, a, b, c):
            self.a = a
            self.b = b
            self.c = c


    instance1 = test(1, 2, 3)
    print(instance1.a) #prints 1

    #scenario 1
    #creating new instance instance1
    #instance1 = test(13, 3, 4)
    #print(instance1.a) #prints 13


    #scenario 2
    #modifying the already created instance **instance1**
    instance1(13,3,4)
    print(instance1.a)#prints 13

नोट : परिदृश्य 1 और परिदृश्य 2 परिणाम आउटपुट के संदर्भ में समान है। लेकिन परिदृश्य 1 में, हम फिर से एक और नया उदाहरण Inst1 बनाते हैं । परिदृश्य 2 में, हम बस पहले से ही निर्मित आवृत्ति 1 को संशोधित करते हैं । __call__यहाँ लाभदायक है क्योंकि सिस्टम को नया उदाहरण बनाने की आवश्यकता नहीं है।

जावा में बराबर

public class Test {

    public static void main(String[] args) {
        Test.TestInnerClass testInnerClass = new Test(). new TestInnerClass(1, 2, 3);
        System.out.println(testInnerClass.a);

        //creating new instance **testInnerClass**
        testInnerClass = new Test().new TestInnerClass(13, 3, 4);
        System.out.println(testInnerClass.a);

        //modifying already created instance **testInnerClass**
        testInnerClass.a = 5;
        testInnerClass.b = 14;
        testInnerClass.c = 23;

        //in python, above three lines is done by testInnerClass(5, 14, 23). For this, we must define __call__ method

    }

    class TestInnerClass /* non-static inner class */{

        private int a, b,c;

        TestInnerClass(int a, int b, int c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    }
}

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

2

हम अन्य विधि के रूप में स्थैतिक विधियों का उपयोग करने के लिए कॉल विधि का उपयोग कर सकते हैं ।

class _Callable:
    def __init__(self, anycallable):
        self.__call__ = anycallable

class Model:

    def get_instance(conn, table_name):

        """ do something"""

    get_instance = _Callable(get_instance)

provs_fac = Model.get_instance(connection, "users")  
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.