日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python中代理模式分为几种_通俗 Python 设计模式——代理模式

發布時間:2025/3/8 python 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python中代理模式分为几种_通俗 Python 设计模式——代理模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天來說一說代理模式。

代理模式顧名思義,是對資源進行代理訪問的一種模式,這里的資源是泛指在程序中會使用到的數據、操作、過程、對象等等。當然,針對不同的資源,代理進行的操作不盡相同,根據前人的總結,有四種常見且知名的代理模式:

遠程代理,即在物理上的遠程資源(如服務器)在本地的代理

虛擬代理,即不是真實的代理,是對一些可以不在第一時間執行的操作進行的代理,他可以將比如復雜耗時的操作推遲到真正需要的時候再進行,所謂的惰性加載即是典型的虛擬代理模式

保護代理,即對敏感資源進行保護,在實際訪問前,進行相應安全性控制的代理

智能代理,即引用代理,在資源被訪問時,執行一些額外的預操作,如檢查引用計數或線程安全之類的

書中提供了一個惰性加載的實例,來講解虛擬代理,這里我們摘錄于此。

首先我們編寫一個名為 LazyProperty 的裝飾器,他的作用在于,將他裝飾的對象的執行時機從聲明之時推后到被調用之時。LazyProperty 裝飾器代碼如下:

class LazyProperty(object):

def __init__(self, method):

self.method = method

self.method_name = method.__name__

print('function overriden: {}'.format(self.method))

print("function's name: {}".format(self.method_name))

def __get__(self, obj, cls):

if not obj:

return None

value = self.method(obj)

print('value {}'.format(value))

setattr(obj, self.method_name, value)

return value

這里我們為 LazyProperty 重寫了 __get__ 方法,從代碼中可以看出,__get__ 方法其實本質上是代理了被 LazyProperty 所修飾的對象的訪問操作。也就是說,要訪問被 LazyProperty 所修飾的對象,在實際返回其值之前,會先執行 LazyProperty.__get__ 方法。下面我們來驗證一下。

編寫一個 Test 類,假設其中 resource 操作會花費較長時間,代碼如下:

class Test:

def __init__(self, x, y):

self.x = x

self.y = y

self._resource = None

def resource(self):

print('initializing self._resource which is: {}'.format(self._resource))

self._resource = tuple(range(x, y)) # 假設這一行的計算成本比較大

return self._resource

如果我們只是這樣編寫代碼,那么每次在遇到需要使用 self._resource 時,調用 Test.resource 方法,都會需要重新執行一遍其中復雜的操作。如下代碼所示:

def main():

t1 = Test(1,5)

t2 = Test(10,15)

print(t1.x)

print(t1.y)

print(t1._resource)

print(t2.x)

print(t2.y)

print(t2._resource)

# 做更多的事情……

print(t1.resource())

print(t2.resource())

print(t1._resource)

print(t2._resource)

print(t1.resource())

print(t2.resource())

main()

這段代碼的輸出是:

1

5

None

10

15

None

initializing self._resource which is: None

(1, 2, 3, 4)

initializing self._resource which is: None

(10, 11, 12, 13, 14)

(1, 2, 3, 4)

(10, 11, 12, 13, 14)

initializing self._resource which is: (1, 2, 3, 4)

(1, 2, 3, 4)

initializing self._resource which is: (10, 11, 12, 13, 14)

(10, 11, 12, 13, 14)

請注意其中兩次出現的 initializing self._resource which is: 內容,這表明,每次調用 t.resource(),都重新執行了一次賦值操作。

然而當我們使用 LazyProperty 裝飾器 & 描述符來修飾 Test.resource 方法時,修改 Test.resource 方法代碼如下:

@LazyProperty

def resource(self):

print('initializing self._resource which is: {}'.format(self._resource))

self._resource = tuple(range(self.x, self.y)) # 假設這一行的計算成本比較大

return self._resource

如此一來,我們再將 main() 方法中,各處調用 t.resource() 改為 t.resource (因為這里 LazyProperty 已經充當了描述符,使得 t.resource 可以像訪問屬性一樣直接訪問),會發現輸出內容有所改變,具體如下:

function overriden:

function's name: resource

1

5

None

10

15

None

initializing self._resource which is: None

value (1, 2, 3, 4)

(1, 2, 3, 4)

initializing self._resource which is: None

value (10, 11, 12, 13, 14)

(10, 11, 12, 13, 14)

(1, 2, 3, 4)

(10, 11, 12, 13, 14)

(1, 2, 3, 4)

(10, 11, 12, 13, 14)

除開最上面部分有一些之前沒有見過的內容,我們可以明顯的看到,初始化操作只執行了一次,之后的每次調用,都是直接獲取已經初始化好的 Test._resource 屬性。也就是說,本例中的虛擬代理 LazyProperty,一方面幫我們完成了惰性加載的操作,另一方面也充當了資源的描述符,方便其之后的獲取其值。當然,根據需要,也可以在 LazyProperty 中實現 __set__ 等其他相關描述符操作。

本例完整代碼如下:

class LazyProperty(object):

def __init__(self, method):

self.method = method

self.method_name = method.__name__

print('function overriden: {}'.format(self.method))

print("function's name: {}".format(self.method_name))

def __get__(self, obj, cls):

if not obj:

return None

value = self.method(obj)

print('value {}'.format(value))

setattr(obj, self.method_name, value)

return value

class Test(object):

def __init__(self, x, y):

self.x = x

self.y = y

self._resource = None

@LazyProperty

def resource(self):

print('initializing self._resource which is: {}'.format(self._resource))

self._resource = tuple(range(self.x, self.y)) # 假設這一行的計算成本比較大

return self._resource

def main():

t1 = Test(1,5)

t2 = Test(10,15)

print(t1.x)

print(t1.y)

print(t1._resource)

print(t2.x)

print(t2.y)

print(t2._resource)

# 做更多的事情……

print(t1.resource)

print(t2.resource)

print(t1._resource)

print(t2._resource)

print(t1.resource)

print(t2.resource)

main()

下面再將書中一個關于保護代理的實例摘錄于此。

我們首先有一個需要訪問的類,SensitiveInfo,其中包含了列表信息,一個讀取列表信息的方法以及一個修改列表內容的方法:

class SensitiveInfo(object):

def __init__(self):

self.users = ['nick', 'tom', 'ben', 'mike']

def read(self):

print('There are {} users: {}'.format(len(self.users), ' '.join(self.users)))

def add(self, user):

self.users.append(user)

print('Added user {}'.format(user))

這里我們假設他的列表信息是需要保密訪問的,只有獲取密碼后才能訪問相應內容,那么我們在不修改這個類本身的情況下,要實現訪問控制,就需要通過代理的方式來進行。增加一個 Info 類作為保護代理,他包含有與被保護對象 SensitiveInfo 相同的方法。代碼如下:

class Info(object):

def __init__(self):

self.protected = SensitiveInfo()

self.secret = '0xdeadbeef'

def read(self):

self.protected.read()

def add(self, user):

sec = input('what is the secret? ')

self.protected.add(user) if sec == self.secret else print("That's wrong!")

這里的 Info 中,將被保護對象作為一個屬性代理了起來,在要進行敏感操作(這里是修改被保護對象列表值)時,設定一系列驗證等檢測,來確保對被訪問對象的操作時安全或者符合要求的。

我們依舊編寫一個 main() 函數進行測試:

def main():

info = Info()

while True:

print('1. read list |==| 2. add user |==| 3. quit')

key = input('choose option: ')

if key == '1':

info.read()

elif key == '2':

name = input('choose username: ')

info.add(name)

elif key == '3':

exit()

else:

print('unknown option: {}'.format(key))

通過運行這個實例,可以看到保護代理是怎樣實現保護這一核心操作的。

同時,書上還留了幾道思考題,我摘錄最有價值的一題于此。其實現代碼將在本文最下方給出。

該示例有一個非常大的安全缺陷。沒有什么能阻止客戶端代碼通過直接創建一個SensitveInfo實例來繞過應用的安全設置。優化示例來阻止這種情況。一種方式是使用abc模塊來禁止直接實例化SensitiveInfo。在這種情況下,會要求進行其他哪些代碼變更呢?

答案:

from abc import ABCMeta, abstractmethod

# 將類聲明為抽象類,并為用 @abstractmethod 修飾相應的需要成為抽象方法的方法

# 如此一來,即無法直接將此類實例化,避免開發中的失誤導致繞過代理,出現不安全的情況

class SensitiveInfo(metaclass=ABCMeta):

def __init__(self):

self.users = ['nick', 'tom', 'ben', 'mike']

@abstractmethod

def read(self):

'''read'''

pass

@abstractmethod

def add(self, user):

'''add'''

pass

class Info(SensitiveInfo):

'''SensitiveInfo的保護代理'''

def __init__(self):

# 通過這種方式,調用 SensitiveInfo.__init__() 獲得 users 列表

super().__init__()

self.secret = '0xdeadbeef'

def read(self):

print('There are {} users: {}'.format(len(self.users), ' '.join(self.users)))

def add(self, user):

sec = input('what is the secret? ')

# 此時的操作全部基于從 SensitiveInfo 繼承來的 users 進行

self.users.append(user) if sec == self.secret else print("That's wrong!")

def main():

info = Info()

while True:

print('1. read list |==| 2. add user |==| 3. quit')

key = input('choose option: ')

if key == '1':

info.read()

elif key == '2':

name = input('choose username: ')

info.add(name)

elif key == '3':

exit()

else:

print('unknown option: {}'.format(key))

if __name__ == '__main__':

main()

總結

以上是生活随笔為你收集整理的python中代理模式分为几种_通俗 Python 设计模式——代理模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。