Heim  >  Artikel  >  Backend-Entwicklung  >  Duck-Typing und Monkey-Patching in Python

Duck-Typing und Monkey-Patching in Python

WBOY
WBOYnach vorne
2023-04-16 22:55:011327Durchsuche

Hallo zusammen, ich bin Lao Wang.

Python-Entwickler haben vielleicht von den Begriffen „Duck Typing“ und „Monkey Patching“ gehört. Auch wenn sie es nicht getan haben, haben sie wahrscheinlich verwandten Code geschrieben, aber sie verstehen einfach nicht die technischen Aspekte dahinter.

Als ich kürzlich Kandidaten interviewte, fragte ich auch nach diesen beiden Konzepten, und die Antworten vieler Leute waren nicht sehr gut. Aber nachdem ich es ihnen erklärt habe, wird ihnen meist plötzlich klar: „Oh, das ist es, ich habe es schon einmal benutzt.“

Also habe ich beschlossen, einen Artikel zu schreiben, um diese beiden Technologien zu diskutieren.

Duck-Typing

Zitat einer Erklärung aus Wikipedia:

Duck-Typing ist ein Stil des dynamischen Tippens in der Programmierung. Bei diesem Stil wird die effektive Semantik eines Objekts nicht durch das Erben von einer bestimmten Klasse oder die Implementierung einer bestimmten Schnittstelle bestimmt, sondern durch den „aktuellen Satz von Methoden und Eigenschaften“.

Um es populärer auszudrücken:

Wenn Sie einen Vogel sehen, der wie eine Ente läuft, wie eine Ente schwimmt und wie eine Ente schnattert, dann kann dieser Vogel eine Ente genannt werden.

Mit anderen Worten: Beim Duck-Typing liegt der Fokus auf dem Verhalten des Objekts und darauf, was es tun kann, und nicht auf dem Typ, zu dem das Objekt gehört.

Schauen wir uns ein Beispiel an, um es anschaulicher zu zeigen:

# 这是一个鸭子(Duck)类
class Duck:
def eat(self):
print("A duck is eating...")

def walk(self):
print("A duck is walking...")


# 这是一个狗(Dog)类
class Dog:
def eat(self):
print("A dog is eating...")

def walk(self):
print("A dog is walking...")


def animal(obj):
obj.eat()
obj.walk()


if __name__ == '__main__':
animal(Duck())
animal(Dog())

Programmausgabe:

A duck is eating...
A duck is walking...
A dog is eating...
A dog is walking...

Python ist eine dynamische Sprache und verfügt nicht über eine strenge Typprüfung. Solange Duck und Dog die Methoden eat und walk implementieren, können sie direkt aufgerufen werden.

Ein weiteres Beispiel ist die Methode list.extend(). Neben list können auch dict und tuple aufgerufen werden, sofern sie iterierbar sind.

Nachdem Sie das obige Beispiel gelesen haben, sollten Sie ein tieferes Verständnis von „Objektverhalten“ und „Objekttyp“ haben.

Um es etwas weiter auszudehnen: Duck-Typing ist eigentlich ziemlich ähnlich zu Schnittstellen, außer dass keine Schnittstelle explizit definiert ist.

Wenn Sie beispielsweise die Go-Sprache verwenden, um Duck-Typing zu implementieren, lautet der Code wie folgt:

package main

import "fmt"

// 定义接口,包含 Eat 方法
type Duck interface {
 Eat()
}

// 定义 Cat 结构体,并实现 Eat 方法
type Cat struct{}

func (c *Cat) Eat() {
 fmt.Println("cat eat")
}

// 定义 Dog 结构体,并实现 Eat 方法
type Dog struct{}

func (d *Dog) Eat() {
 fmt.Println("dog eat")
}

func main() {
 var c Duck = &Cat{}
 c.Eat()

 var d Duck = &Dog{}
 d.Eat()

 s := []Duck{
&Cat{},
&Dog{},
 }
 for _, n := range s {
n.Eat()
 }
}

Er wird implementiert, indem explizit eine Duck-Schnittstelle definiert wird und jede Struktur die Methoden in der Schnittstelle implementiert.

Monkey Patch

Monkey Patch hat einen schlechten Ruf, weil es ein Modul, eine Klasse oder eine Funktion zur Laufzeit dynamisch ändert, normalerweise um Funktionen hinzuzufügen oder Fehler zu beheben.

Monkey-Patching funktioniert im Speicher und verändert den Quellcode nicht, daher ist es nur für die aktuell laufende Programminstanz wirksam.

Aber wenn es missbraucht wird, wird es schwierig, das System zu verstehen und zu warten.

Es gibt zwei Hauptprobleme:

  • Patches unterbrechen die Kapselung, sind normalerweise eng an das Ziel gekoppelt und daher anfällig.
  • Zwei gepatchte Bibliotheken können ineinander verwickelt werden, da die zweite Bibliothek die ersten Patches rückgängig machen kann Bibliothek

Es handelt sich also um eine vorübergehende Problemumgehung und nicht um eine empfohlene Möglichkeit, den Code zu integrieren.

Wie üblich geben wir zur Veranschaulichung ein Beispiel:

# 定义一个Dog类
class Dog:
def eat(self):
print("A dog is eating ...")


# 在类的外部给 Dog 类添加猴子补丁
def walk(self):
print("A dog is walking ...")


Dog.walk = walk

# 调用方式与类的内部定义的属性和方法一样
dog = Dog()
dog.eat()
dog.walk()

Programmausgabe:

A dog is eating ...
A dog is walking ...

Dies entspricht dem Hinzufügen einer Walk-Methode zur Dog-Klasse außerhalb der Klasse, und die aufrufende Methode ist dieselbe wie die definierten Attribute und Methoden intern in der Klasse.

Nehmen wir ein weiteres praktisches Beispiel, beispielsweise unsere häufig verwendete JSON-Standardbibliothek. Wenn Sie stattdessen ujson mit höherer Leistung verwenden möchten, müssen Sie zwangsläufig jede Datei importieren:

import json

Wechseln Sie zu:

import ujson as json

Wenn die Kosten für Dies zu ändern wäre relativ hoch. Zu diesem Zeitpunkt können Sie die Verwendung von Monkey-Patches in Betracht ziehen. Sie müssen nur Folgendes hinzufügen:

import json
import ujson


def monkey_patch_json():
json.__name__ = 'ujson'
json.dumps = ujson.dumps
json.loads = ujson.loads


monkey_patch_json()

Auf diese Weise wird beim Aufrufen der Dump- und Load-Methoden in Zukunft das ujson-Paket aufgerufen. was immer noch sehr praktisch ist.

Aber Monkey Patch ist ein zweischneidiges Schwert. Das oben erwähnte Problem ist je nach Bedarf mit Vorsicht zu genießen.

Das obige ist der detaillierte Inhalt vonDuck-Typing und Monkey-Patching in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:51cto.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen