2016-02-03 3 views
5

Ich habe mindestens drei Arten in Bezug auf Funktionen in Python 3 beobachtet:Was ist der Unterschied zwischen einer 'Funktion', 'Methode' und 'gebundenen Methode' in Python 3?

>>> class A(): 
... def f(): pass 
... 
>>> A.f 
<function A.f at 0x7fcaef304268> 
>>> A().f 
<bound method A.f of <__main__.A object at 0x7fcaef2fae80 
>>> set.union 
<method 'union' of 'set' objects> 

Ich frage mich, was ist der Unterschied zwischen ‚Funktion‘, ‚Methode‘ und ‚gebunden Methode‘? Ist "Methode" ein Typ, der in Python 2 der Methode "ungebunden" entspricht?

Antwort

5

Ist 'Methode' ein Typ, der in Python 2 der 'ungebundenen Methode' entspricht?

Art-a-sort-a. Aber nicht wirklich. Es ist ein method_descriptor Objekt in C-Code definiert. Es ist eine ungebundene Methode, aber nicht die Art, die Sie in Python 2 gefunden haben.

Für Python-Typen geschrieben C, alle "Methoden" sind wirklich C-Funktionen. Das Objekt <method 'name' of 'type' objects>, das Sie gefunden haben, ist ein spezielles Objekt, das Sie zum Aufrufen dieser Funktion bei einer Instanz und weiteren Argumenten verwenden können, genau wie das Objekt function für benutzerdefinierte Python-Klassen. Das Objekt ist in C in PyMethodDescr_Type structure definiert. Es implementiert die descriptor protocol, genau wie Funktionen tun.

Python definiert mehrere andere solche Deskriptortypen; Wenn Sie verwenden, ist jedes Attribut ein dscriptor vom Typ member_descriptor (siehe PyMemberDescr_Type structure), während , property und staticmethod vielleicht besser bekannte Deskriptorobjekte sind.

In Python 2, gebundene und ungebundene Methoden sind wirklich nur ein Typ, instancemethod (definiert durch die PyMethod_Type structure); Es wird als gebunden gemeldet, wenn das Attribut __self__ (im_self) festgelegt ist. In Python 3 erzeugt eine Funktion als Deskriptor einfach keine Methodenobjekte ohne __self__ set; Stattdessen ruft function.__get__() ohne Instanz nur die Funktion erneut auf.

Der einzige Grund, warum Python 2 ungebundene Methoden zurückgibt, besteht darin, eine Typüberprüfung durchzusetzen; Das erste Argument muss eine Instanz der Klasse (oder einer Unterklasse davon) sein. Das hat für Python-Code, der Duck-Typing unterstützt, nicht viel Sinn gemacht, daher wurde in Python 3 die Einschränkung entfernt. Mit C-Code können Sie jedoch keine Duck-Typisierung verwenden, Sie müssen den Typ immer noch einschränken, und deshalb geben C-types immer noch ein method_descriptor Objekt zurück, das diese Einschränkung erzwingt.

Verwandte Themen