1. 程式人生 > >Python 魔術方法(Magic Method)

Python 魔術方法(Magic Method)

介紹

在Python中,所有以“__”雙下劃線包起來的方法,都統稱為“Magic Method”,例如類的初始化方法 __init__,Python中所有的魔術方法均在官方文件中有相應描述,但是對於官方的描述比較混亂而且組織比較鬆散。很難找到有一個例子。

構造和初始化

每個Pythoner都知道一個最基本的魔術方法, __init__ 。通過此方法我們可以定義一個物件的初始操作。然而,當呼叫 x = SomeClass() 的時候, __init__ 並不是第一個被呼叫的方法。實際上,還有一個叫做__new__ 的方法,兩個共同構成了“建構函式”。

__new__是用來建立類並返回這個類的例項, 而__init__只是將傳入的引數來初始化該例項。

在物件生命週期呼叫結束時,__del__ 方法會被呼叫,可以將__del__理解為“構析函式”。下面通過程式碼的看一看這三個方法:

fromos.pathimportjoin

classFileObject:

'''給檔案物件進行包裝從而確認在刪除時檔案流關閉'''

def__init__(self,filepath='~',filename='sample.txt'):

#讀寫模式開啟一個檔案

self.file = open(join(filepath,filename),'r+')

def__del__(self):

self.file.close()

delself.file

控制屬性訪問

許多從其他語言轉到Python的人會抱怨它缺乏類的真正封裝。(沒有辦法定義私有變數,然後定義公共的getter和setter)。Python其實可以通過魔術方法來完成封裝。我們來看一下:

__getattr__(self, name)

定義當用戶試圖獲取一個不存在的屬性時的行為。這適用於對普通拼寫錯誤的獲取和重定向,對獲取一些不建議的屬性時候給出警告(如果你願意你也可以計算並且給出一個值)或者處理一個 AttributeError 。只有當呼叫不存在的屬性的時候會被返回。

__setattr__(self, name, value)

與__getattr__(self, name)不同,__setattr__ 是一個封裝的解決方案。無論屬性是否存在,它都允許你定義對對屬性的賦值行為,以為這你可以對屬性的值進行個性定製。實現__setattr__時要避免”無限遞迴”的錯誤。

__delattr__

與 __setattr__ 相同,但是功能是刪除一個屬性而不是設定他們。實現時也要防止無限遞迴現象發生。

__getattribute__(self, name)

__getattribute__定義了你的屬性被訪問時的行為,相比較,__getattr__只有該屬性不存在時才會起作用。因此,在支援__getattribute__的Python版本,呼叫__getattr__前必定會呼叫 __getattribute__。__getattribute__同樣要避免”無限遞迴”的錯誤。需要提醒的是,最好不要嘗試去實現__getattribute__,因為很少見到這種做法,而且很容易出bug。

在進行屬性訪問控制定義的時候很可能會很容易引起“無限遞迴”。如下面程式碼:

#  錯誤用法

def__setattr__(self,name,value):

self.name = value

# 每當屬性被賦值的時候(如self.name = value), ``__setattr__()`` 會被呼叫,這樣就造成了遞迴呼叫。

# 這意味這會呼叫 ``self.__setattr__('name', value)`` ,每次方法會呼叫自己。這樣會造成程式崩潰。

#  正確用法

def__setattr__(self,name,value):

self.__dict__[name] = value# 給類中的屬性名分配值

# 定製特有屬性

Python的魔術方法很強大,但是用時卻需要慎之又慎,瞭解正確的使用方法非常重要。

建立自定義容器

有很多方法可以讓你的Python類行為向內建容器型別一樣,比如我們常用的list、dict、tuple、string等等。Python的容器型別分為可變型別(如list、dict)和不可變型別(如string、tuple),可變容器和不可變容器的區別在於,不可變容器一旦賦值後,不可對其中的某個元素進行修改。   在講建立自定義容器之前,應該先了解下協議。這裡的協議跟其他語言中所謂的”介面”概念很像,它給你很多你必須定義的方法。然而在Python中的協議是很不正式的,不需要明確宣告實現。事實上,他們更像一種指南。

自定義容器的magic method

下面細緻瞭解下定義容器可能用到的魔術方法。首先,實現不可變容器的話,你只能定義 __len__ 和 __getitem__ (下面會講更多)。可變容器協議則需要所有不可變容器的所有,另外還需要 __setitem__ 和 __delitem__。如果你希望你的物件是可迭代的話,你需要定義 __iter__ 會返回一個迭代器。迭代器必須遵循迭代器協議,需要有 __iter__(返回它本身) 和 next。

__len__(self)

返回容器的長度。對於可變和不可變容器的協議,這都是其中的一部分。

__getitem__(self, key)

定義當某一項被訪問時,使用self[key]所產生的行為。這也是不可變容器和可變容器協議的一部分。如果鍵的型別錯誤將產生TypeError;如果key沒有合適的值則產生KeyError。

__setitem__(self, key, value)

當你執行self[key] = value時,呼叫的是該方法。

__delitem__(self, key)

定義當一個專案被刪除時的行為(比如 del self[key])。這只是可變容器協議中的一部分。當使用一個無效的鍵時應該丟擲適當的異常。

__iter__(self)

返回一個容器迭代器,很多情況下會返回迭代器,尤其是當內建的iter()方法被呼叫的時候,以及當使用for x in container:方式迴圈的時候。迭代器是它們本身的物件,它們必須定義返回self的__iter__方法。

__reversed__(self)

實現當reversed()被呼叫時的行為。應該返回序列反轉後的版本。僅當序列可以是有序的時候實現它,例如對於列表或者元組。

__contains__(self, item)

定義了呼叫in和not in來測試成員是否存在的時候所產生的行為。你可能會問為什麼這個不是序列協議的一部分?因為當__contains__沒有被定義的時候,如果沒有定義,那麼Python會迭代容器中的元素來一個一個比較,從而決定返回True或者False。

__missing__(self, key)

dict字典型別會有該方法,它定義了key如果在容器中找不到時觸發的行為。比如d = {‘a’: 1}, 當你執行d[notexist]時,d.__missing__[‘notexist’]就會被呼叫。

一個例子

下面是書中的例子,用魔術方法來實現Haskell語言中的一個數據結構。

# -*- coding: utf-8 -*-

classFunctionalList:

''' 實現了內建型別list的功能,並豐富了一些其他方法: head, tail, init, last, drop, take'''

def__init__(self,values=None):

ifvalues isNone:

self.values = []

else:

self.values = values

def__len__(self):

returnlen(self.values)

def__getitem__(self,key):

returnself.values[key]

def__setitem__(self,key,value):

self.values[key] = value

def__delitem__(self,key):

delself.values[key]

def__iter__(self):

returniter(self.values)

def__reversed__(self):

returnFunctionalList(reversed(self.values))

defappend(self,value):

self.values.append(value)

defhead(self):

# 獲取第一個元素

returnself.values[0]

deftail(self):

# 獲取第一個元素之後的所有元素

returnself.values[1:]

definit(self):

# 獲取最後一個元素之前的所有元素

returnself.values[:-1]

deflast(self):

# 獲取最後一個元素

returnself.values[-1]

defdrop(self

相關推薦

Python 魔術方法Magic Method

介紹在Python中,所有以“__”雙下劃線包起來的方法,都統稱為“Magic Method”,例如類的初始化方法 __init__,Python中所有的魔術方法均在官方文件中有相應描述,但是對於官方的描述比較混亂而且組織比較鬆散。很難找到有一個例子。構造和初始化每個Pyth

Python 開發者不得不知的魔術方法Magic Method

介紹 在Python中,所有以“__”雙下劃線包起來的方法,都統稱為“Magic Method”,例如類的初始化方法 __init__,Python中所有的魔術方法均在官方文件中有相應描述,但是對於官方的描述比較混亂而且組織比較鬆散。很難找到有一個例子。 構造和初始化

幾種歸一化方法Normalization Methodpython實現

資料歸一化問題是資料探勘中特徵向量表達時的重要問題,當不同的特徵成列在一起的時候,由於特徵本身表達方式的原因而導致在絕對數值上的小資料被大資料“吃掉”的情況,這個時候我們需要做的就是對抽取出來的features vector進行歸一化處理,以保證每個特徵被分類器平等對待。

python魔術方法

contex height con text 例如 數據庫連接 test eba 網絡 上下文管理: 文件IO操作可以對文件對象使用上下文管理,使用with...as語法 with open(‘test‘) as f: pass 當一個對象同時實現了__enter__()和

設計模式的征途—17.模板方法Template Method模式

opened res ati 相同 rom 配置 version factor creat 在現實生活中,很多事情都需要經過幾個步驟才能完成,例如請客吃飯,無論吃什麽,一般都包含:點單、吃東西、買單等幾個步驟,通常情況下這幾個步驟的次序是:點單=>吃東西=>買單

Pandas學習筆記,字符串方法string method

api long top method hand capi borde tle row 一般語法格式Series.str.method()。具體方法見http://pandas.pydata.org/pandas-docs/stable/api.html#string-ha

設計模式-工廠方法Factory Method

log face inf str ace 對象實例 method tee 就是 2018-1-20 by Atlas 應用場景 Template Method Pattern是在父類建立處理邏輯的大綱骨架,而在子類補充具體的處理內容。把Template Method

設計模式2——建立型——工廠相關:簡單工廠Simple factory,工廠方法Factory method,抽象工廠Abstract factory

概要 這裡試圖描述23個設計模式中的兩個工廠(Factory)相關的設計模式:工廠方法(Factorymethod),抽象工廠(Abstract factory)。 注意點: 這兩個都屬於建立型設計模式。 由於這兩個設計模式都

泛型擦除type erasure和橋接方法bridge method

無界萬用字元會被編譯為Object,有邊界的萬用字元會被編譯為相應的邊界   正常類的繼承是不會產生這個橋接方法的。 橋接方法,一個類、介面繼承或實現某個類、介面時,會在子類中出現一個橋接方法。 這個方法不能被子類呼叫,即mn不能呼叫到這個橋接方法,但是n可以呼

【java設計模式】之 模板方法Template Method模式

1. 模板方法的一個例項         這一節主要來學習一下設計模式中的模板方法模式。我們先來看一個例子:假如現在老闆讓你做一個汽車的模型,要求只要完成基本功能即可,不考慮擴充套件性,那你會怎麼做呢?我們首先會根據經驗設計一個類圖:        由這個類圖可知,非

【設計模式】之模板方法Template Method

模板方法的定義為:再一個操作中定義一個演算法的骨架,將演算法中的一些步驟延遲到子類去實現。模板方法允許子類在不該變演算法結構的情況下重新定義演算法的某些步驟。 Define the skeleton of an algorithm in an operation, defe

小菜學習設計模式—工廠方法Factory Method模式

前言 設計模式目錄: 本篇目錄:   其實大家都知道,在工廠方法(Factory Method)模式之前有個簡單工廠模式,也就是靜態工廠方法(Static Factory Method)模式,在簡單工廠模式之前有個我們都熟悉的三層架構模式,那我們就上到下一層一層的來了解下。 三層架構   三

設計模式的征途—3.工廠方法Factory Method模式

上一篇的簡單工廠模式雖然簡單,但是存在一個很嚴重的問題:當系統中需要引入新產品時,由於靜態工廠方法通過所傳入引數的不同來建立不同的產品,這必定要修改工廠類的原始碼,將違背開閉原則。如何實現新增新產品而不影響已有程式碼?工廠方法模式為此應運而生。 工廠方法模式(Factory Method) 學

模版方法Template Method

“元件協作”模式: 現代軟體專業分工之後的第一個結果是“框架與應用程式的劃分”,“元件協作”模式通過晚期繫結,來實現框架與應用程式之間的鬆耦合,使二者之間協作時常用的模式。 典型模式 Template Method Strategy Observer / Eve

Java 橋接方法Bridge Method

什麼是「橋接方法」,下面來從兩個例子中體會一下。 重寫方法的返回型別是其父類返回型別的子型別 public class Merchant { public Number actionPrice(double price) { retur

【為什麼學習模板方法Template Method模式和模板方法Template Method模式主要解決的問題】

轉載 https://blog.csdn.net/eson_15/article/details/51323902 1. 模板方法的一個例項         這一節主要來學習一下設計模式中的模板方法模式。我們先來看一個例子:假如現在老闆讓你做一個汽車的模型,要求只要完成基

Jupyter 魔術命令magic commands

span 禁用 ole atp inf spa foo 標記 inline 自動重新加載更改的模塊 命令參數如下所示: %autoreload: 自動重載%aimport排除的模塊之外的所有模塊。 %autoreload 0: 禁用自動重載 %autorelo

設計模式之工廠方法Factory Method

一 目的    定義一個建立物件的介面,但是讓他的子類去決定初始化哪種型別。工廠方法使得一個類能夠推遲到他的子類去初始化。二 動機    框架運用抽象類來定義和維護物件之間的關係。一個框架經常負責這些物件的建立。考慮一些這麼一個情況:一個能夠展現多個文件的應用程式的框架。在這

C++設計模式——模板方法Template Method

模板方法(template method)設計模式用於定義一個包含許多步驟的演算法框架,允許子類重寫(覆蓋)演算法的某一個步驟而不改變演算法整體的流程和框架。 模板方法提供的流程是骨架,子類無須覆蓋模板方法本身,只需繼承即可,即模板方法無須是 virtu

.NET設計模式-模版方法Template Method

摘要:Template Method模式是比較簡單的設計模式之一,但它卻是程式碼複用的一項基本的技術,在類庫中尤其重要。主要內容1.概述2.Template Method解說3..NET中的Template Method模式4.適用性及實現要點概述變化一直以來都是軟體設計的永恆話題,在XP程式設計中提倡擁抱變