python 直譯器是如何工作的呢

2021-09-24 11:58:56 字數 3974 閱讀 5242

python 直譯器是如何工作的呢?

不管在哪種框架下寫程式,都會花費大量時間去實現那些會被框架本身呼叫的方法, python 也不例外。python 直譯器碰到特殊的句法時,會使用特殊方法去啟用一些基本的對 象操作,這些特殊方法的名字以兩個下劃線開頭,以兩個下劃線結尾

比如 obj[key] 的背後就是__getitem__方法,

import collections

from random import choice

import pysnooper

card = collections.namedtuple('card', ['rank', 'suit'])

class frenchdeck:

ranks = [str(n) for n in range(2, 11)] + list('jqka')

suits = 'spades diamonds clubs hearts'.split()

def __init__(self):

self._cards = [card(rank, suit) for suit in self.suits for rank in self.ranks]

@pysnooper.snoop()

def __len__(self):

return len(self._cards)

@pysnooper.snoop()

def __getitem__(self, position):

return self._cards[position]

@pysnooper.snoop()

def __contains__(self, item):

if item:

return true

if __name__ == '__main__':

deck = frenchdeck()

print(len(deck))

print(deck[1])

首先明確一點,特殊方法的存在是為了被 python 直譯器呼叫的,你自己並不需要呼叫它 們。也就是說沒有my_object.__len__()這種寫法,而應該使用len(my_object)。在執行len(my_object)的時候,如果my_object是乙個自定義類的物件,那麼 python 會自己去調 用其中由你實現的__len__方法。但是,如果是python內建的型別,比如列表(list)、字串(str)、位元組序列(bytearray)等,那麼cpython會抄個近路,__len__實際上會直接返回pyvarobject裡的ob_size屬 性。pyvarobject是表示記憶體中長度可變的內建物件的 c 語言結構體。直接讀取這個值比 呼叫乙個方法要快很多。

很多時候,特殊方法的呼叫是隱式的,比如for i in x: 這個語句,背後其實用的是iter(x),而這個函式的背後則是x.__iter__()方法。當然前提是這個方法在 x 中被實現了。

通常你的**無需直接使用特殊方法。除非有大量的元程式設計存在,直接呼叫特殊方法的頻 率應該遠遠低於你去實現它們的次數。唯一的例外可能是__init__方法,你的**裡可能 經常會用到它,目的是在你自己的子類的__init__方法中呼叫超類的構造器。

下面在介紹一些特殊方法的實現

__repr____abs____add____mul__

from math import hypot

import pysnooper

class vector:

def __init__(self, x=0, y=0):

self.x = x

self.y = y

@pysnooper.snoop()

def __repr__(self):

return 'vector(%r, %r)' % (self.x, self.y)

@pysnooper.snoop()

def __str__(self):

return '物件字串化%r' % self

@pysnooper.snoop()

def __abs__(self):

return hypot(self.x, self.y)

@pysnooper.snoop()

def __bool__(self):

return bool(abs(self))

@pysnooper.snoop()

def __add__(self, other):

x = self.x + other.x

y = self.y + other.y

return vector(x, y)

@pysnooper.snoop()

def __mul__(self, scalar):

return vector(self.x * scalar, self.y * scalar)

@pysnooper.snoop()

def __len__(self):

return true if self else false

if __name__ == "__main__":

vector = vector(3, 4)

vector_1 = vector(5, 12)

print(vector.__repr__())

print(abs(vector))

vector_3 = vector + vector_1

print(vector_3)

print(vector_3*3)

print(str(vector_3))

print(vector_3.__len__())

print(bool(vector_3))

bool()

__repr____str__(都是列印輸出的作用) 區別在於,後者是在str()函式被使用,或是在用 print 函式列印 乙個物件的時候才被呼叫的,並且它返回的字串對終端使用者更友好。

如果你只想實現這兩個特殊方法中的乙個,__repr__是更好的選擇,因為如果乙個物件沒 有__str__函式,而 python 又需要呼叫它的時候,直譯器會用__repr__作為替代。

其他的python 特殊方法

這裡對於__len__方法做乙個特殊說明:對於使用者自定義的方法,python 會自己去調 用其中由你實現的__ len__方法, 但對於python內建的型別 ,比如列表(list)、字串(str)、位元組序列(bytearray) 等,那麼cpython會抄個近路,len 實際上會直接返回pyvarobject裡的ob_size屬 性。pyvarobject是表示記憶體中長度可變的內建物件的 c 語言結構體。直接讀取這個值比 呼叫乙個方法要快很多。

python的with是如何工作的

class sample def enter self print in enter return foo def exit self,type,value,trace print in exit def get sample return sample with get sample as sam...

python直譯器配置 Python直譯器的配置

1 準備工作 安裝好pycharm2017版本 電腦上安裝好python直譯器 2 本地直譯器配置 配置本地直譯器的步驟相對簡潔直觀 1 單擊工具欄中的設定按鈕。2 在settings preferences對話方塊中選中 project interpreter頁面,在project interpr...

JQuery選擇器是如何工作的

每次申明乙個jquery物件的時候,返回的是jquery.prototype.init物件,很多人就會不明白,init明明是jquery.fn的方法啊,實際上這裡不是方法,而是init的建構函式,因為js的prototype物件可以實現繼承,加上js的物件只是引用不會是拷貝,new jquery,n...