目錄
鴨子類型
猴子補丁
首頁 後端開發 Python教學 Python 中的鴨子類型和猴子補丁

Python 中的鴨子類型和猴子補丁

Apr 16, 2023 pm 10:55 PM
python 鴨子類型 猴子補丁

大家好,我是老王。

Python 開發者可能都聽說過鴨子類型和猴子補丁這兩個詞,即使沒聽過,也大概率寫過相關的代碼,只不過並不了解其背後的技術要點是這兩個字而已。

我最近在面試候選人的時候,也會問這兩個概念,很多人答的也不是很好。但是當我向他們解釋完之後,普遍都會恍然大悟:「哦,是這個啊,我用過」。

所以,我決定來寫一篇文章,探討一下這兩種技巧。

鴨子類型

引用維基百科中的一段解釋:

鴨子類型(duck typing)在程式設計中是動態類型的風格。在這種風格中,一個物件有效的語義,不是由繼承自特定的類別或實作特定的接口,而是由"當前方法和屬性的集合"決定。

更通俗一點的說:

當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。

也就是說,在鴨子類型中,關注點在於物件的行為,能作什麼;而不是專注於物件所屬的類型。

我們看一個例子,更形像地展示一下:

# 这是一个鸭子(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())
登入後複製

程式輸出:

A duck is eating...
A duck is walking...
A dog is eating...
A dog is walking...
登入後複製

Python 是一門動態語言,沒有嚴格的類型檢查。只要 Duck 和 Dog 分別實作了 eat 和 walk 方法就可以直接呼叫。

再例如 list.extend() 方法,除了 list 之外,dict 和 tuple 也可以調用,只要它是可迭代的就都可以調用。

看過上例之後,應該對「物件的行為」和「物件所屬的類型」有更深的體會了吧。

再擴展一點,其實鴨子類型和介面挺像的,只不過沒有明確定義任何介面。

例如用 Go 語言來實現鴨子類型,程式碼是這樣的:

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()
 }
}
登入後複製

透過明確定義一個 Duck 接口,每個結構體實現接口中的方法來實現。

猴子補丁

猴子補丁(Monkey Patch)的名聲不太好,因為它會在運行時動態修改模組、類別或函數,通常是新增功能或修正缺陷。

猴子補丁在記憶體中發揮作用,不會修改原始碼,因此只對目前運行的程式實例有效。

但如果濫用的話,會導致系統難以理解和維護。

主要有兩個問題:

  • 補丁會破壞封裝,通常與目標緊密耦合,因此很脆弱
  • 打了補丁的兩個函式庫可能相互牽絆,因為第二個庫可能會撤銷第一個庫的補丁

所以,它被視為臨時的變通方案,不是集成代碼的推薦方式。

按照慣例,還是舉個例子來說明:

# 定义一个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()
登入後複製

程式輸出:

A dog is eating ...
A dog is walking ...
登入後複製

這裡相當於在類別的外部為Dog 類別增加了一個walk 方法,而呼叫方式與類別的內部定義的屬性和方法一樣。

再舉一個比較實用的例子,例如我們常用的json 標準函式庫,如果說想用效能更高的ujson 取代的話,勢必需要將每個檔案的引入:

import json
登入後複製

改成:

import ujson as json
登入後複製

如果這樣改起來成本就比較高了。這個時候就可以考慮使用猴子補丁,只需要在程式入口加上:

import json
import ujson


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


monkey_patch_json()
登入後複製

這樣在以後呼叫 dumps 和 loads 方法的時候就是呼叫的 ujson 包,還是很方便的。

但猴子補丁就是一把雙面刃,問題也在上文提到了,看需,謹慎使用吧。

以上是Python 中的鴨子類型和猴子補丁的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

sublime怎麼運行代碼python sublime怎麼運行代碼python Apr 16, 2025 am 08:48 AM

在 Sublime Text 中運行 Python 代碼,需先安裝 Python 插件,再創建 .py 文件並編寫代碼,最後按 Ctrl B 運行代碼,輸出會在控制台中顯示。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Golang vs. Python:性能和可伸縮性 Golang vs. Python:性能和可伸縮性 Apr 19, 2025 am 12:18 AM

Golang在性能和可擴展性方面優於Python。 1)Golang的編譯型特性和高效並發模型使其在高並發場景下表現出色。 2)Python作為解釋型語言,執行速度較慢,但通過工具如Cython可優化性能。

vscode在哪寫代碼 vscode在哪寫代碼 Apr 15, 2025 pm 09:54 PM

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

See all articles