“ callable” คืออะไร?


310

ตอนนี้มันชัดเจนว่า metaclass คืออะไรมีแนวคิดที่เกี่ยวข้องที่ฉันใช้ตลอดเวลาโดยไม่ทราบว่ามันหมายถึงอะไรจริงๆ

ฉันคิดว่าทุกคนทำผิดพลาดกับวงเล็บส่งผลให้เกิดข้อยกเว้น "วัตถุไม่สามารถเรียกได้" มีอะไรเพิ่มเติมให้ใช้__init__และ__new__นำไปสู่การสงสัยว่า__call__สามารถใช้เลือดนี้เพื่ออะไรได้บ้าง

คุณช่วยอธิบายให้ฉันหน่อยได้ไหมรวมถึงตัวอย่างด้วยวิธีเวทย์มนตร์?


คำตอบ:


308

callable คือสิ่งที่สามารถเรียกได้

ในตัวcallable (PyCallable_Check ใน objects.c)ตรวจสอบว่าอาร์กิวเมนต์เป็นอย่างใดอย่างหนึ่ง

  • ตัวอย่างของคลาสที่มี__call__เมธอดหรือ
  • เป็นประเภทที่มีสมาชิกที่ไม่ใช่ null tp_call (c struct) ซึ่งบ่งชี้ความสามารถในการโทรได้ (เช่นในฟังก์ชันวิธีการ ฯลฯ )

วิธีการตั้งชื่อ__call__คือ ( ตามเอกสาร )

เรียกว่าเมื่ออินสแตนซ์คือ '' เรียกว่า '' เป็นฟังก์ชั่น

ตัวอย่าง

class Foo:
  def __call__(self):
    print 'called'

foo_instance = Foo()
foo_instance() #this is calling the __call__ method

6
โปรดทราบว่า callin ในตัวจะถูกลบออกใน Python 3.0 เพื่อตรวจสอบการโทร
Eli Courtwright

13
@Eli: อืมมดูเหมือนว่าท่าจะแย่มาก callableจริง ๆ แล้วบอกคุณว่าสิ่งที่ callable หรือไม่ในขณะที่การตรวจสอบเพื่อ__call__บอกอะไรคุณ; ถ้าวัตถุoให้__getattribute__หรือ__getattr__, hasattr(o, '__call__')อาจจะกลับมาทรู แต่oจะยังคงไม่เป็น callable เพราะงูหลามข้าม__getattribute__และ__getattr__สำหรับการโทร เหลือวิธีเดียวที่แท้จริงในการตรวจสอบว่ามีสิ่งใดที่เรียกได้ว่าเป็น EAFP
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

49
@ Longpoke: สำหรับบันทึกเท่านั้นโปรดดูเอกสารประกอบcallable()ใน Python 3.x : " ฟังก์ชั่นนี้ถูกลบครั้งแรกใน Python 3.0 แล้วนำกลับมาใช้ใน Python 3.2 "
Tadeck

ดูเหมือนว่าใน python 3.8 เท่านั้นที่มีการtp_callตรวจสอบ ดูการใช้งานPyCallable_Checkมันคือ 3 บรรทัด
Michele Piccolini

84

จากแหล่งที่มาของ Python object.c :

/* Test whether an object can be called */

int
PyCallable_Check(PyObject *x)
{
    if (x == NULL)
        return 0;
    if (PyInstance_Check(x)) {
        PyObject *call = PyObject_GetAttrString(x, "__call__");
        if (call == NULL) {
            PyErr_Clear();
            return 0;
        }
        /* Could test recursively but don't, for fear of endless
           recursion if some joker sets self.__call__ = self */
        Py_DECREF(call);
        return 1;
    }
    else {
        return x->ob_type->tp_call != NULL;
    }
}

มันบอกว่า:

  1. ถ้าวัตถุเป็นอินสแตนซ์ของบางคลาสมันจะเรียกว่าiffมันมี__call__คุณสมบัติ
  2. มิฉะนั้นวัตถุxนั้นจะเรียกว่าiff x->ob_type->tp_call != NULL

ประเภทกิจกรรมของtp_callข้อมูล :

ternaryfunc tp_callตัวชี้เพิ่มเติมของฟังก์ชันที่ใช้เรียกวัตถุ นี่ควรเป็นค่า NULL ถ้าวัตถุนั้นไม่สามารถเรียกได้ ลายเซ็นเหมือนกันกับ PyObject_Call () ฟิลด์นี้สืบทอดโดยชนิดย่อย

คุณสามารถใช้callableฟังก์ชันในตัวเพื่อกำหนดว่าวัตถุที่กำหนดนั้นสามารถเรียกได้หรือไม่ หรือดีกว่าเพียงแค่โทรหาและจับในTypeErrorภายหลัง callableจะถูกลบออกในหลาม 3.0 และ 3.1 ใช้หรือcallable = lambda o: hasattr(o, '__call__')isinstance(o, collections.Callable)

ตัวอย่างการใช้แคชอย่างง่าย:

class Cached:
    def __init__(self, function):
        self.function = function
        self.cache = {}

    def __call__(self, *args):
        try: return self.cache[args]
        except KeyError:
            ret = self.cache[args] = self.function(*args)
            return ret    

การใช้งาน:

@Cached
def ack(x, y):
    return ack(x-1, ack(x, y-1)) if x*y else (x + y + 1) 

ตัวอย่างจากไลบรารีมาตรฐานไฟล์site.pyคำจำกัดความของบิวด์อินexit()และquit()ฟังก์ชัน:

class Quitter(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return 'Use %s() or %s to exit' % (self.name, eof)
    def __call__(self, code=None):
        # Shells like IDLE catch the SystemExit, but listen when their
        # stdin wrapper is closed.
        try:
            sys.stdin.close()
        except:
            pass
        raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')

10
ฉันพบตัวอย่างสำหรับวิธีการโทรอย่างสูงเพราะมันผสมกับสูตรสำหรับการแคชและมัณฑนากรซึ่งเพิ่มอะไรให้กับความเข้าใจในการโทร
Florian Bösch

3
เจ. เจ. เซบาสเตียนยังยกตัวอย่างเพิ่มเติมที่คุณคัดลอกและวางจากที่อื่นที่ไม่น้อยไม่ได้ช่วยอะไร
Florian Bösch

20
@JF Sebastian: เป็น BS ที่มีตัวอย่างที่เหมือนชีวิตมากขึ้นจะดีกว่า ฉันสามารถแสดงรหัสเหมือนชีวิตที่จะทำให้คุณร้องไห้เป็นตัวอย่าง ตัวอย่างง่าย ๆ ก็ใช้ได้เช่นกันและพวกเขาก็ทำงานได้ดีขึ้นเพื่อแสดงบางสิ่งบางอย่างเพราะพวกเขาไม่เบี่ยงเบนความสนใจ
Florian Bösch

5
คุณกำลังอธิบายสิ่งที่เรียกได้ แต่คุณยกตัวอย่างวิธีใช้วัตถุที่เรียกได้เพื่อกำหนดตัวตกแต่ง ฉันรู้ว่ามันเป็นเรื่องปกติของการใช้งานcallableแต่อาจสร้างความสับสนให้ผู้อ่านที่ต้องการเพียงแค่รู้ว่าอะไรคือ callable และวิธีการใช้callable ฉันต้องการคำตอบของ @Florian Bösch
KFL

2
@Kay: ฉันชอบคำตอบของ @Florian Bösch (ในรูปแบบปัจจุบัน) btw มัณฑนากรไม่ใช่การใช้ "callable" โดยทั่วไป ส่วนใหญ่ปกติ "callables" ฟังก์ชั่น / วิธีการเช่นdef f(): ...และระดับชั้นวัตถุเช่นclass C: ...IE, f, ''.strip, lenและCทั้งหมดเป็น callable อินสแตนซ์ที่มี__call__()วิธีการในชั้นเรียนของพวกเขาค่อนข้างหายาก
jfs

37

callable เป็นวัตถุที่อนุญาตให้คุณใช้เครื่องหมายวงเล็บกลม () และในที่สุดก็ผ่านพารามิเตอร์บางอย่างเช่นเดียวกับฟังก์ชั่น

ทุกครั้งที่คุณกำหนดฟังก์ชั่นหลามจะสร้างวัตถุที่เรียกได้ ตัวอย่างเช่นคุณสามารถกำหนดฟังก์ชั่นfuncด้วยวิธีเหล่านี้ (เหมือนกัน):

class a(object):
    def __call__(self, *args):
        print 'Hello'

func = a()

# or ... 
def func(*args):
    print 'Hello'

คุณสามารถใช้วิธีนี้แทนวิธีเช่นdoitหรือrunฉันคิดว่ามันชัดเจนกว่าที่จะเห็น obj () มากกว่า obj.doit ()


37

ให้ฉันอธิบายย้อนหลัง:

พิจารณาสิ่งนี้...

foo()

... เป็นน้ำตาลประโยคสำหรับ:

foo.__call__()

ไหนfooสามารถเป็นวัตถุใด ๆ __call__ที่ตอบสนองต่อ เมื่อฉันพูดวัตถุใด ๆ ฉันหมายถึงมัน: ชนิดในตัว, คลาสของคุณเองและอินสแตนซ์ของมัน

ในกรณีที่มีชนิดในตัวเมื่อคุณเขียน:

int('10')
unicode(10)

คุณกำลังทำ:

int.__call__('10')
unicode.__call__(10)

นั่นเป็นเหตุผลที่คุณไม่ได้มีfoo = new intในหลาม: __call__คุณเพียงแค่ทำให้วัตถุชั้นกลับตัวอย่างของมันใน วิธีการที่หลามแก้ปัญหานี้ได้อย่างสวยงาม


คุณกำลังทำหลักและtype(int).__call__(int, '10') type(unicode).__call__(unicode, '10')Dunders มักจะถูกเรียกในชั้นเรียนของพวกเขาไม่ใช่ผ่านอินสแตนซ์ และพวกเขาก็ไม่เคยผ่าน metaclass เช่นกัน สำหรับกรณีส่วนใหญ่นั่นเป็นเพียง nitpick แต่บางครั้งก็สำคัญ
นักฟิสิกส์บ้า

11

Callable เป็นวัตถุที่มี__call__วิธีการ วิธีนี้คุณสามารถฟังก์ชั่น callable ปลอมหรือทำสิ่งที่เรียบร้อยเช่นการประยุกต์ใช้ฟังก์ชั่นบางส่วนที่คุณใช้ฟังก์ชั่นและเพิ่มบางสิ่งบางอย่างที่ช่วยเพิ่มหรือเติมในบางส่วนของพารามิเตอร์กลับสิ่งที่สามารถเรียกได้ว่าในทางกลับกัน (ที่รู้จักกันดีความชอบในการทำงานในแวดวงการเขียนโปรแกรม )

ข้อผิดพลาดบางอย่างเกี่ยวกับการพิมพ์จะมีล่ามพยายามโทรหาสิ่งที่คุณไม่ได้ตั้งใจเช่นสตริง (ตัวอย่าง) สิ่งนี้สามารถสร้างข้อผิดพลาดเมื่อล่ามพยายามเรียกใช้แอปพลิเคชันที่ไม่สามารถเรียกได้ คุณสามารถเห็นสิ่งนี้เกิดขึ้นในล่ามไพ ธ อนโดยทำบางอย่างเช่นการถอดเสียงด้านล่าง

[nigel@k9 ~]$ python
Python 2.5 (r25:51908, Nov  6 2007, 15:55:44) 
[GCC 4.1.2 20070925 (Red Hat 4.1.2-27)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 'aaa'()    # <== Here we attempt to call a string.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> 

9

__call__ ทำให้วัตถุใด ๆ ที่เรียกว่าเป็นฟังก์ชันได้

ตัวอย่างนี้จะแสดงผล 8:

class Adder(object):
  def __init__(self, val):
    self.val = val

  def __call__(self, val):
    return self.val + val

func = Adder(5)
print func(3)

7

ค่อนข้างง่าย "callable" เป็นสิ่งที่สามารถเรียกได้ว่าเป็นวิธีการ ฟังก์ชันในตัว "callable ()" จะบอกคุณว่ามีบางสิ่งที่ดูเหมือนจะเรียกได้หรือไม่เช่นเดียวกับการตรวจสอบคุณสมบัติการโทร ฟังก์ชั่นเป็น callable เช่นเดียวกับชั้นเรียนอินสแตนซ์ชั้นสามารถเรียก ดูข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ที่นี่และที่นี่


5

ใน Python callable เป็นวัตถุชนิดที่มี__call__วิธีการ:

>>> class Foo:
...  pass
... 
>>> class Bar(object):
...  pass
... 
>>> type(Foo).__call__(Foo)
<__main__.Foo instance at 0x711440>
>>> type(Bar).__call__(Bar)
<__main__.Bar object at 0x712110>
>>> def foo(bar):
...  return bar
... 
>>> type(foo).__call__(foo, 42)
42

ง่ายเหมือนที่ :)

หลักสูตรนี้สามารถโอเวอร์โหลดได้:

>>> class Foo(object):
...  def __call__(self):
...   return 42
... 
>>> f = Foo()
>>> f()
42

3

ในการตรวจสอบฟังก์ชั่นหรือวิธีการเรียนสามารถเรียกใช้ได้หรือไม่นั้นหมายความว่าเราสามารถเรียกใช้ฟังก์ชันนั้นได้

Class A:
    def __init__(self,val):
        self.val = val
    def bar(self):
        print "bar"

obj = A()      
callable(obj.bar)
True
callable(obj.__init___)
False
def foo(): return "s"
callable(foo)
True
callable(foo())
False

1
คุณแน่ใจหรือว่าcallable(obj.__init___)ไม่มีขีดล่างพิเศษ (เช่นเดียวกับใน AttributeError)? หากไม่เป็นเช่นนั้นคุณแน่ใจหรือไม่ว่าคำตอบนั้นไม่ใช่คำตอบTrueนั้น?
นักฟิสิกส์บ้า

2

มันเป็นสิ่งที่คุณสามารถใส่ "(args)" หลังจากและคาดหวังว่ามันจะทำงาน callable มักจะเป็นวิธีการหรือชั้นเรียน วิธีการได้รับการเรียกชั้นเรียนได้รับการยกตัวอย่าง


2

callables ใช้__call__วิธีพิเศษเพื่อให้วัตถุใด ๆ ที่มีวิธีการดังกล่าว callable


อินสแตนซ์ที่คุณกำหนด__call__จะไม่สามารถเรียกใช้ได้ถ้าคลาสไม่ได้กำหนดวิธีดังกล่าว
นักฟิสิกส์บ้า

2

Callable เป็นประเภทหรือคลาสของ "Build-in function หรือ Method" พร้อมการเรียกใช้เมธอด

>>> type(callable)
<class 'builtin_function_or_method'>
>>>

ตัวอย่าง: การ พิมพ์เป็นวัตถุที่เรียกได้ ด้วยฟังก์ชัน build-in __call__ เมื่อคุณเรียกใช้ฟังก์ชันการพิมพ์ Python จะสร้างอ็อบเจกต์ของ print typeและเรียกใช้เมธอด__call__ผ่านพารามิเตอร์หากมี

>>> type(print)
<class 'builtin_function_or_method'>
>>> print.__call__(10)
10
>>> print(10)
10
>>>

ขอบคุณ. ขอแสดงความนับถือมาริส


1
ข้อมูลบางส่วนที่นี่ผิดพลาด เช่น "เมื่อคุณเรียกใช้printฟังก์ชัน Python จะสร้างอ็อบเจกต์ประเภท print และเรียกใช้เมธอดของมัน__call__" Python ไม่ได้สร้างวัตถุพิมพ์ type(print).__call__(print, *args, **kwargs)มันก็เรียกสิ่งที่เทียบเท่ากับ และประโยคแรกนั้นไม่สมเหตุสมผลนัก คุณดูเหมือนจะสับสนวัตถุที่เรียกได้และ "callable" ฟังก์ชั่น
นักฟิสิกส์บ้า
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.