__Init__ এবং __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 বিন্যাস করতে ইতিমধ্যে instantiated বর্গ কল করার জন্য একটি টেমপ্লেট: \ Def __call __ (স্ব, zzz) তারপর, myfoo (12) ক্লাসকে কল করে যে সেই ক্লাসটি কি করে।
ব্যবহারকারী 1270710

1
কেবলমাত্র একটি নোট: যেহেতু সাধারণভাবে ফাংশনগুলি কলযোগ্য হয় তাই তারা সর্বদা পদ্ধতি কলকে সমর্থন করে । সুতরাং আপনি এইভাবে ফাংশনটিও কল করতে পারেন: মাইফুন __ কল __ (আর্গ)
অরিন্দম রায়চৌধুরী

8
ব্যবহারিক ব্যবহার কি __call__?
mrgloom

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__ঠিক তখন সিনট্যাকটিক্স চিনি?
অ্যালেক্স পোভেল 19

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 টি পদ 1 টি। যেমন: 1, 1, 2, 3, 5, 8, 13 ....

আপনি চান যে ফাইবোনাচি সংখ্যাযুক্ত তালিকাটি কেবল একবার আরম্ভ করা হবে এবং তারপরে এটি আপডেট হওয়া উচিত। এখন আমরা __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
আপনি কি দয়া করে আউটপুটটিকে পাঠ্য হিসাবে অনুলিপি করতে পারেন?
সলোমন উকো

এই পদ্ধতির মূল বিষয় কী? আপনি এটি একটি ভিন্ন পদ্ধতির সাথে বিপরীতে করতে পারেন?
নীলাম্যাকবি

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
@ রেদোয়ান দেলোয়ার ধন্যবাদ ব্রহ
আইয়ামুন হোসেন আশিক

4

__init__পাইথন ক্লাসগুলির একটি বিশেষ পদ্ধতি, এটি কোনও শ্রেণীর জন্য কনস্ট্রাক্টর পদ্ধতি। যখনই শ্রেণীর কোনও অবজেক্ট তৈরি করা হয় বা আমরা এটি বলতে পারি এটি কোনও নতুন অবজেক্টের সূচনা করে। উদাহরণ:

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

আমরা যদি () ব্যবহার, এটি একটি ত্রুটির দেব 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

এখানে যদি আমরা বি () ব্যবহার করি তবে এটি ঠিকঠাক হয় কারণ এটির __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 ফলাফল ফলাফলের ক্ষেত্রে একই বলে মনে হচ্ছে। কিন্তু scenario1, আমরা আবার একটি নতুন দৃষ্টান্ত তৈরি instance1 । দৃশ্যে 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")  
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.