醉了,面個功能測試,還問我Python裝飾器

?

Python 裝飾器是個強大的工具,可幫你生成整潔、可重用和可維護的代碼。某種意義上說,會不會用裝飾器是區分新手和老鳥的重要標志。如果你不熟悉裝飾器,你可以將它們視為將函數作為輸入并在不改變其主要用途的情況下擴展其功能的函數。裝飾器可以有效提高你的工作效率并避免重復代碼。本文我整理了項目中經常用到的 12 個裝飾器,值得每一個Python開發者掌握。

01 @logger

我們從最簡單的裝飾器開始,手動實現一個可以記錄函數開始和結束的裝飾器。

被修飾函數的輸出結果如下所示:

  1. some_function(args)

  2. # ----- some_function: start -----

  3. # some_function executing

  4. # ----- some_function: end -----

要實現一個裝飾器,首先要給裝飾器起一個合適的名稱:這里我們給裝飾器起名為logger。

裝飾器本質上是一個函數,它將一個函數作為輸入并返回一個函數作為輸出。?輸出函數通常是輸入的擴展版。在我們的例子中,我們希望輸出函數用start和end語句包圍輸入函數的調用。

由于我們不知道輸入函數都帶有什么參數,我們可以使用?*args?和?**kwargs?從包裝函數傳遞它們。*args?和?**kwargs?允許傳遞任意數量的位置參數和關鍵字參數。

下面是logger裝飾器的示例代碼:

  1. def logger(function):

  2. ? ? def wrapper(*args, **kwargs):

  3. ? ? ? ? print(f"----- {function.__name__}: start -----")

  4. ? ? ? ? output = function(*args, **kwargs)

  5. ? ? ? ? print(f"----- {function.__name__}: end -----")

  6. ? ? ? ? return output

  7. ? ? return wrapper

logger函數可以應用于任意函數,比如:

decorated_function = logger(some_function)

上面的語句是正確的,但Python 提供了更?Pythonic?的語法——使用 @ 修飾符。

因此更通常的寫法是:

  1. @logger

  2. def some_function(text):

  3. ? ? print(text)

  4. some_function("first test")

  5. # ----- some_function: start -----

  6. # first test

  7. # ----- some_function: end -----

  8. some_function("second test")

  9. # ----- some_function: start -----

  10. # second test

  11. # ----- some_function: end -----

02?@wraps

要了解 @wraps 的作用以及為什么需要它,讓我們將前面寫的logger裝飾器應用到一個將兩個數字相加的簡單函數中。

下面的代碼是未使用@wraps裝飾器的版本

  1. def logger(function):

  2. ? ? def wrapper(*args, **kwargs):

  3. ? ? ? ? """wrapper documentation"""

  4. ? ? ? ? print(f"----- {function.__name__}: start -----")

  5. ? ? ? ? output = function(*args, **kwargs)

  6. ? ? ? ? print(f"----- {function.__name__}: end -----")

  7. ? ? ? ? return output

  8. ? ? return wrapper

  9. @logger

  10. def add_two_numbers(a, b):

  11. ? ? """this function adds two numbers"""

  12. ? ? return a + b

如果我們用__name__?和?__doc__來查看被裝飾函數add_two_numbers的名稱和文檔,會得到如下結果

  1. add_two_numbers.__name__

  2. 'wrapper'

  3. add_two_numbers.__doc__

  4. 'wrapper documentation'

輸出的是wrapper函數的名稱和文檔。這是我們預期想要的結果,我們希望保留原始函數的名稱和文檔。這時@wraps裝飾器就派上用場了。

我們唯一需要做的就是給wrapper函數加上@wraps裝飾器。

  1. from functools import wraps

  2. def logger(function):

  3. ? ? @wraps(function)

  4. ? ? def wrapper(*args, **kwargs):

  5. ? ? ? ? """wrapper documentation"""

  6. ? ? ? ? print(f"----- {function.__name__}: start -----")

  7. ? ? ? ? output = function(*args, **kwargs)

  8. ? ? ? ? print(f"----- {function.__name__}: end -----")

  9. ? ? ? ? return output

  10. ? ? return wrapper

  11. @logger

  12. def add_two_numbers(a, b):

  13. ? ? """this function adds two numbers"""

  14. ? ? return a + b

再此檢查add_two_numbers函數的名稱和文檔,我們可以看到該函數的元數據。

  1. add_two_numbers.__name__

  2. # 'add_two_numbers'

  3. add_two_numbers.__doc__

  4. # 'this function adds two numbers'

03?@lru_cache

@lru_cache是Python內置裝飾器,可以通過from functools import lru_cache引入。@lru_cache的作用是緩存函數的返回值,當緩存裝滿時,使用least-recently-used(LRU)算法丟棄最少使用的值。

@lru_cache裝飾器適合用于輸入輸出不變且運行時間較長的任務,例如查詢數據庫、請求靜態頁面或一些繁重的處理。

在下面的示例中,我使用@lru_cache來修飾一個模擬某些處理的函數。然后連續多次對同一輸入應用該函數。

  1. import random

  2. import time

  3. from functools import lru_cache

  4. @lru_cache(maxsize=None)

  5. def heavy_processing(n):

  6. ? ? sleep_time = n + random.random()

  7. ? ? time.sleep(sleep_time)

  8. # 初次調用

  9. %%time

  10. heavy_processing(0)

  11. # CPU times: user 363 μs, sys: 727 μs, total: 1.09 ms

  12. # Wall time: 694 ms

  13. # 第二次調用

  14. %%time

  15. heavy_processing(0)

  16. # CPU times: user 4 μs, sys: 0 ns, total: 4 μs

  17. # Wall time: 8.11 μs

  18. # 第三次調用

  19. %%time

  20. heavy_processing(0)

  21. # CPU times: user 5 μs, sys: 1 μs, total: 6 μs

  22. # Wall time: 7.15 μs

從上面的輸出可以看到,第一次調用花費了694ms,因為執行了time.sleep()函數。后面兩次調用由于參數相同,直接返回緩存值,因此并沒有實際執行函數內容,因此非常快地得到函數返回。

04 @repeat

該裝飾器的所用是多次調用被修飾函數。這對于調試、壓力測試或自動化多個重復任務非常有用。

跟前面的裝飾器不同,@repeat接受一個輸入參數,

  1. def repeat(number_of_times):

  2. ? ? def decorate(func):

  3. ? ? ? ? @wraps(func)

  4. ? ? ? ? def wrapper(*args, **kwargs):

  5. ? ? ? ? ? ? for _ in range(number_of_times):

  6. ? ? ? ? ? ? ? ? func(*args, **kwargs)

  7. ? ? ? ? return wrapper

  8. ? ? return decorate

上面的代碼定義了一個名為repeat的裝飾器,有一個輸入參數number_of_times。與前面的案例不同,這里需要decorate函數來傳遞被修飾函數。然后,裝飾器定義一個名為wrapper的函數來擴展被修飾函數。

  1. @repeat(5)

  2. def hello_world():

  3. ? ? print("hello world")

  4. hello_world()

  5. # hello world

  6. # hello world

  7. # hello world

  8. # hello world

  9. # hello world

05 @timeit

該裝飾器用來測量函數的執行時間并打印出來。這對調試和監控非常有用。

在下面的代碼片段中,@timeit裝飾器測量process_data函數的執行時間,并以秒為單位打印所用的時間。

  1. import time

  2. from functools import wraps

  3. def timeit(func):

  4. ? ? @wraps(func)

  5. ? ? def wrapper(*args, **kwargs):

  6. ? ? ? ? start = time.perf_counter()

  7. ? ? ? ? result = func(*args, **kwargs)

  8. ? ? ? ? end = time.perf_counter()

  9. ? ? ? ? print(f'{func.__name__} took {end - start:.6f} seconds to complete')

  10. ? ? ? ? return result

  11. ? ? return wrapper

  12. @timeit

  13. def process_data():

  14. ? ? time.sleep(1)

  15. process_data()

  16. # process_data took 1.000012 seconds to complete

06?@retry

其工作原理如下:

  • wrapper函數啟動num_retrys次迭代的for循環。

  • 將被修飾函數放到try/except塊中。每次迭代如果調用成功,則中斷循環并返回結果。否則,休眠sleep_time秒后繼續下一次迭代。

  • 當for循環結束后函數調用依然不成功,則拋出異常。

示例代碼如下:

  1. import random

  2. import time

  3. from functools import wraps

  4. def retry(num_retries, exception_to_check, sleep_time=0):

  5. ? ? """

  6. ? ? 遇到異常嘗試重新執行裝飾器

  7. ? ? """

  8. ? ? def decorate(func):

  9. ? ? ? ? @wraps(func)

  10. ? ? ? ? def wrapper(*args, **kwargs):

  11. ? ? ? ? ? ? for i in range(1, num_retries+1):

  12. ? ? ? ? ? ? ? ? try:

  13. ? ? ? ? ? ? ? ? ? ? return func(*args, **kwargs)

  14. ? ? ? ? ? ? ? ? except exception_to_check as e:

  15. ? ? ? ? ? ? ? ? ? ? print(f"{func.__name__} raised {e.__class__.__name__}. Retrying...")

  16. ? ? ? ? ? ? ? ? ? ? if i < num_retries:

  17. ? ? ? ? ? ? ? ? ? ? ? ? time.sleep(sleep_time)

  18. ? ? ? ? ? ? # 嘗試多次后仍不成功則拋出異常

  19. ? ? ? ? ? ? raise e

  20. ? ? ? ? return wrapper

  21. ? ? return decorate

  22. @retry(num_retries=3, exception_to_check=ValueError, sleep_time=1)

  23. def random_value():

  24. ? ? value = random.randint(1, 5)

  25. ? ? if value == 3:

  26. ? ? ? ? raise ValueError("Value cannot be 3")

  27. ? ? return value

  28. random_value()

  29. # random_value raised ValueError. Retrying...

  30. # 1

  31. random_value()

  32. # 5

07?@countcall

@countcall用于統計被修飾函數的調用次數。這里的調用次數會緩存在wraps的count屬性中。

  1. from functools import wraps

  2. def countcall(func):

  3. ? ? @wraps(func)

  4. ? ? def wrapper(*args, **kwargs):

  5. ? ? ? ? wrapper.count += 1

  6. ? ? ? ? result = func(*args, **kwargs)

  7. ? ? ? ? print(f'{func.__name__} has been called {wrapper.count} times')

  8. ? ? ? ? return result

  9. ? ? wrapper.count = 0

  10. ? ? return wrapper

  11. @countcall

  12. def process_data():

  13. ? ? pass

  14. process_data()

  15. process_data has been called 1 times

  16. process_data()

  17. process_data has been called 2 times

  18. process_data()

  19. process_data has been called 3 times

08?@rate_limited

@rate_limited裝飾器會在被修飾函數調用太頻繁時,休眠一段時間,從而限制函數的調用速度。這在模擬、爬蟲、接口調用防過載等場景下非常有用

  1. import time

  2. from functools import wraps

  3. def rate_limited(max_per_second):

  4. ? ? min_interval = 1.0 / float(max_per_second)

  5. ? ? def decorate(func):

  6. ? ? ? ? last_time_called = [0.0]

  7. ? ? ? ? @wraps(func)

  8. ? ? ? ? def rate_limited_function(*args, **kargs):

  9. ? ? ? ? ? ? elapsed = time.perf_counter() - last_time_called[0]

  10. ? ? ? ? ? ? left_to_wait = min_interval - elapsed

  11. ? ? ? ? ? ? if left_to_wait > 0:

  12. ? ? ? ? ? ? ? ? time.sleep(left_to_wait)

  13. ? ? ? ? ? ? ret = func(*args, **kargs)

  14. ? ? ? ? ? ? last_time_called[0] = time.perf_counter()

  15. ? ? ? ? ? ? return ret

  16. ? ? ? ? return rate_limited_function

  17. ? ? return decorate

該裝飾器的工作原理是:測量自上次函數調用以來所經過的時間,并在必要時等待適當的時間,以確保不超過速率限制。其中等待時間=min_interval - elapsed,這里min_intervalue是兩次函數調用之間的最小時間間隔(以秒為單位),已用時間是自上次調用以來所用的時間。如果經過的時間小于最小間隔,則函數在再次執行之前等待left_to_wait秒。

?注意:該函數在調用之間引入了少量的時間開銷,但確保不超過速率限制。

如果不想自己手動實現,可以用第三方包,名叫ratelimit。

pip install ratelimit

使用非常簡單,只需要裝飾被調用函數即可:

  1. from ratelimit import limits

  2. import requests

  3. FIFTEEN_MINUTES = 900

  4. @limits(calls=15, period=FIFTEEN_MINUTES)

  5. def call_api(url):

  6. ? ? response = requests.get(url)

  7. ? ? if response.status_code != 200:

  8. ? ? ? ? raise Exception('API response: {}'.format(response.status_code))

  9. ? ? return response

如果被裝飾函數的調用次數超過允許次數,則會拋出ratelimit.RateLimitException異常。要處理該異常可以將@sleep_and_retry裝飾器與@limits裝飾器一起使用。

  1. @sleep_and_retry

  2. @limits(calls=15, period=FIFTEEN_MINUTES)

  3. def call_api(url):

  4. ? ? response = requests.get(url)

  5. ? ? if response.status_code != 200:

  6. ? ? ? ? raise Exception('API response: {}'.format(response.status_code))

  7. ? ? return response

這樣被裝飾函數在再次執行之前會休眠剩余時間。

09 @dataclass

Python 3.7 引入了@dataclass裝飾器,將其加入到標準庫,用于裝飾類。它主要用于存儲數據的類自動生成諸如__init__,?__repr__,?__eq__,?__lt__,__str__?等特殊函數。這樣可以減少模板代碼,并使類更加可讀和可維護。

另外,@dataclass還提供了現成的美化方法,可以清晰地表示對象,將其轉換為JSON格式,等等。

  1. from dataclasses import dataclass,?

  2. @dataclass

  3. class Person:

  4. ? ? first_name: str

  5. ? ? last_name: str

  6. ? ? age: int

  7. ? ? job: str

  8. ? ? def __eq__(self, other):

  9. ? ? ? ? if isinstance(other, Person):

  10. ? ? ? ? ? ? return self.age == other.age

  11. ? ? ? ? return NotImplemented

  12. ? ? def __lt__(self, other):

  13. ? ? ? ? if isinstance(other, Person):

  14. ? ? ? ? ? ? return self.age < other.age

  15. ? ? ? ? return NotImplemented

  16. john = Person(first_name="John",?

  17. ? ? ? ? ? ? ? last_name="Doe",?

  18. ? ? ? ? ? ? ? age=30,?

  19. ? ? ? ? ? ? ? job="doctor",)

  20. anne = Person(first_name="Anne",?

  21. ? ? ? ? ? ? ? last_name="Smith",?

  22. ? ? ? ? ? ? ? age=40,?

  23. ? ? ? ? ? ? ? job="software engineer",)

  24. print(john == anne)

  25. # False

  26. print(anne > john)

  27. # True

  28. asdict(anne)

  29. #{'first_name': 'Anne',

  30. # 'last_name': 'Smith',

  31. # 'age': 40,

  32. # 'job': 'software engineer'}

10 @register

如果你的Python腳本意外終止,但你仍想執行一些任務來保存你的工作、執行清理或打印消息,那么@register在這種情況下非常方便。

  1. from atexit import register

  2. @register

  3. def terminate():

  4. ? ? perform_some_cleanup()

  5. ? ? print("Goodbye!")

  6. while True:

  7. ? ? print("Hello")

運行上面的代碼會不斷在控制臺輸出"Hello",點擊Ctrl + C強制終止腳本運行,你會看到控制臺輸出"Goodbye",說明程序在中斷后執行了@register裝飾器裝飾的terminate()函數。

11 @property

@property裝飾器用于定義類屬性,這些屬性本質上是類實例屬性的getter、setter和deleter方法。

通過使用@property裝飾器,可以將方法定義為類屬性,并將其作為類屬性進行訪問,而無需顯式調用該方法。

如果您想在獲取或設置值時添加一些約束和驗證邏輯,使用@property裝飾器會非常方便。

下面的示例中,我們在rating屬性上定義了一個setter,對輸入執行約束(介于0和5之間)。

  1. class Movie:

  2. ? ? def __init__(self, r):

  3. ? ? ? ? self._rating = r

  4. ? ? @property

  5. ? ? def rating(self):

  6. ? ? ? ? return self._rating

  7. ? ? @rating.setter

  8. ? ? def rating(self, r):

  9. ? ? ? ? if 0 <= r <= 5:

  10. ? ? ? ? ? ? self._rating = r

  11. ? ? ? ? else:

  12. ? ? ? ? ? ? raise ValueError("The movie rating must be between 0 and 5!")

  13. batman = Movie(2.5)

  14. batman.rating

  15. # 2.5

  16. batman.rating = 4

  17. batman.rating

  18. # 4

  19. batman.rating = 10

  20. # ---------------------------------------------------------------------------

  21. # ValueError? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recent call last)

  22. # Input In [16], in <cell line: 1>()

  23. # ----> 1 batman.rating = 10

  24. # Input In [11], in Movie.rating(self, r)

  25. #? ? ? 12? ? ?self._rating = r

  26. #? ? ? 13 else:

  27. # ---> 14? ? ?raise ValueError("The movie rating must be between 0 and 5!")

  28. #

  29. # ValueError: The movie rating must be between 0 and 5!

12?@singledispatch

@singledispatch允許函數對不同類型的參數有不同的實現,有點像Java等面向對象語言中的函數重載。

  1. from functools import singledispatch

  2. @singledispatch

  3. def fun(arg):

  4. ? ? print("Called with a single argument")

  5. @fun.register(int)

  6. def _(arg):

  7. ? ? print("Called with an integer")

  8. @fun.register(list)

  9. def _(arg):

  10. ? ? print("Called with a list")

  11. fun(1)? # Prints "Called with an integer"

  12. fun([1, 2, 3])? # Prints "Called with a list"

結論

裝飾器是一個重要的抽象思想,可以在不改變原始代碼的情況下擴展代碼,如緩存、自動重試、速率限制、日志記錄,或將類轉換為超級數據容器等。

裝飾器的功能遠不止于此,本文介紹的12個常用裝飾器只是拋磚引玉,當你理解了裝飾器思想和用法后,可以發揮創造力,實現各種自定義裝飾器來解決具體問題。

總結:

感謝每一個認真閱讀我文章的人!!!

作為一位過來人也是希望大家少走一些彎路,如果你不想再體驗一次學習時找不到資料,沒人解答問題,堅持幾天便放棄的感受的話,在這里我給大家分享一些自動化測試的學習資源,希望能給你前進的路上帶來幫助。

軟件測試面試文檔

我們學習必然是為了找到高薪的工作,下面這些面試題是來自阿里、騰訊、字節等一線互聯網大廠最新的面試資料,并且有字節大佬給出了權威的解答,刷完這一套面試資料相信大家都能找到滿意的工作。

?

? ? ? ? ? 視頻文檔獲取方式:
這份文檔和視頻資料,對于想從事【軟件測試】的朋友來說應該是最全面最完整的備戰倉庫,這個倉庫也陪伴我走過了最艱難的路程,希望也能幫助到你!以上均可以分享,點下方小卡片即可自行領取。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/12945.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/12945.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/12945.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

dhcp(接口和全局地址池模式)

接口地址池和全局地址池 dhcp應用 1.全部開啟dhcp功能 2.ar5 0口接口地址池 1口全局地址池 3.ar6和ar7配置&#xff0c;查看能否自動獲取ip 左右不同兩個網絡&#xff0c;接口和全局地址池的區別 部分截圖 ar6 ar7 ar5

(實測驗證)【移遠EC800M-CN 】TCP 透傳

引言 本文章使用自研“超小體積TTL轉4GGPS集成模塊”進行實測驗證&#xff1b; 1、配置移遠EC800M-CN TCP 透傳 串口助手發送&#xff1a; ATQIOPEN1,0,"TCP","36.137.226.30",39755,0,2 //配置服務器地址和端口號&#xff1b; 4G模組返回…

07-Fortran基礎--Fortran指針(Pointer)的使用

07-Fortran基礎--Fortran指針Pointer的使用 0 引言1 指針&#xff08;Poionter&#xff09;的有關內容1.1 一般類型指針1.2 數組指針1.3 派生類(type)指針1.4 函數指針 2 可運行code 0 引言 Fortran是一種廣泛使用的編程語言&#xff0c;特別適合科學計算和數值分析。Fortran 9…

java代碼混淆工具ProGuard混淆插件

java代碼混淆工具ProGuard混淆插件 介紹 ProGuard是一個純java編寫的混淆工具&#xff0c;有客戶端跟jar包兩種使用方式。可以將程序打包為jar&#xff0c;然后用工具進行混淆&#xff0c;也可以在maven中導入ProGuard的插件&#xff0c;對代碼進行混淆。 大家都知道 java代…

【華為OD機試-C卷D卷-200分】田忌賽馬(C++/Java/Python)

【華為OD機試】-(A卷+B卷+C卷+D卷)-2024真題合集目錄 【華為OD機試】-(C卷+D卷)-2024最新真題目錄 題目描述 給定兩個只包含數字的數組a,b,調整數組 a 里面的數字的順序,使得盡可能多的a[i] > b[i]。 數組a和b中的數字各不相同。 輸出所有可以達到最優結果的a數組的…

SadTalker 自定義容器化部署配置

Docker 環境檢查 執行docker info 查看環境種是否有安裝docker&#xff0c;否則首先安裝好docker 運行環境。在線環境安裝執行執行兩條指令即可 sudo apt install docker sudo apt-get install docker-ce sudo apt-get install docker-composesudo systemctl restart dockerG…

langchain源碼

itemgetter&#xff1a;返回一個函數&#xff0c;函數取輸入dict的某個指定key Runnable 的基本方法有 invoke、 batch、 await、 ainvoke、 abatch 同步轉異步 Runnable 還具有的方法&#xff1a;bind、 with_config。 input_schema 屬性、output_schema 屬性 with_retry方…

Uniapp H5開發常見問題解析

引言 在移動應用開發領域&#xff0c;Uniapp已經成為一個備受矚目的技術框架&#xff0c;其跨平臺能力和高效開發特性使得開發者能夠更加便捷地構建出功能豐富、性能優越的應用程序。特別是在H5開發中&#xff0c;Uniapp的應用場景日益廣泛&#xff0c;然而&#xff0c;隨之而…

Vue2之使用provide和inject實現兩個不相干組件之間的通信

Vue2之使用provide和inject實現兩個不相干組件之間的通信 文章目錄 Vue2之使用provide和inject實現兩個不相干組件之間的通信1. 祖先組件中使用provide提供數據2.后代組件A中使用inject注入并使用數據3.后代組件B中使用inject注入并使用數據 在Vue 2中以使用provide和inject來實…

[ciscn 2022 東北賽區]math

1.題目 import gmpy2 from Crypto.Util.number import * from flag import flag assert flag.startswith(b"flag{") assert flag.endswith(b"}") messagebytes_to_long(flag) def keygen(nbit, dbit):if 2*dbit < nbit:while True:a1 getRandomNBitIn…

編輯器目錄樹的設計,一點也不簡單

朋友們好&#xff0c;我是優秀的大鵬 今天花了很長時間思考一個網頁文檔編輯器&#xff0c;云端目錄樹要怎么設計 這個看似簡單的需求&#xff0c;技術上和產品上的思考卻非常復雜 下面以幾種編輯器為例&#xff0c;講一下各種編輯器在技術上和產品的思考 1、以Vscode為代表的本…

Delphi DataSet轉JSon (使用SuperObject)

Delphi中將TDataSet轉換為JSon字符串。 with ATM.LoadDataSet() dobeginif IsEmpty thenbeginLogObj.WriteLog(未查詢到該視圖名稱下該時間段內的上傳數據&#xff0c;視圖名稱&#xff1a; AViewname 開始時間&#xff1a; AStartdate 結束時間&#xff1a; AEnddate);exit…

【神經網絡與深度學習】Transformer原理

transformer ENCODER 輸入部分 對拆分后的語句x [batch_size, seq_len]進行以下操作 Embedding 將離散的輸入&#xff08;如單詞索引或其他類別特征&#xff09;轉換為稠密的實數向量&#xff0c;以便可以在神經網絡中使用。位置編碼 與RNN相比&#xff0c;RNN是一個字一個字…

Django Rest Framework 全局異常處理

在Django Rest Framework&#xff08;DRF&#xff09;中&#xff0c;全局異常處理是一種重要的機制&#xff0c;它可以幫助我們更好地管理API中的異常情況&#xff0c;并返回統一的錯誤響應。本文將詳細介紹兩種全局異常處理的方法&#xff1a;使用中間件&#xff08;Middlewar…

機器學習(3)

目錄 3-1線性回歸 3-2最小二乘解 3-3多元線性回歸 3-4廣義線性模型 3-5對率回歸 3-6對率回歸求解 3-7線性判別分析 3-8LDA的多類推廣 3-9多分類學習基本思路 3-10類別不平衡 3-1線性回歸 線性模型為什么重要&#xff1f; 人類在考慮問題時&#xff0c;通常…

用python寫一個自動生成android開機動畫的工具

要創建一個自動生成Android開機動畫的工具&#xff0c;你需要一些基本的知識&#xff0c;比如Python編程、圖像處理和Android開機動畫的格式。以下是一個簡單的Python腳本示例&#xff0c;它可以生成一個基本的Android開機動畫&#xff0c;具體效果可能需要更多的調整和優化。 …

記錄glide加載圖片,設置圓角

支持所有角的圓角&#xff0c;自動計算合適的半徑&#xff0c;不用擔心圖片比預定值小導致的圓角過大的問題 修改自&#xff1a;https://blog.csdn.net/qq_15059163/article/details/97613790 增加了指定圖片尺寸、解決了圖片某些情況下圓角過大的問題 public class GlideRou…

先有JVM還是先有垃圾回收器?很多人弄混淆了

是先有垃圾回收器再有JVM呢&#xff0c;還是先有JVM再有垃圾回收器呢&#xff1f;或者是先有垃圾回收再有JVM呢&#xff1f;歷史上還真是垃圾回收更早面世&#xff0c;垃圾回收最早起源于1960年誕生的LISP語言&#xff0c;Java只是支持垃圾回收的其中一種。下面我們就來刨析刨析…

外賣系統的JWT實現登錄

1、什么是JWT jwt可以生成一個加密的token&#xff0c;作為用戶登錄的令牌&#xff0c;當用戶登陸成功之后&#xff0c;發放給客戶端。請求需要登錄的資源或者接口的時候&#xff0c;將token攜帶&#xff0c;后端驗證token是否合法。jwt有三部分組成&#xff1a; A&#xff1a;…

【特大喜訊】國內前33位持有PMI-RMP風險管理專業認證的學員分享~!

【學員背景】 沈陽某信息科技有限公司&#xff0c;從事企業采購供應鏈數字化轉型方向&#xff1b; 為企業提供有效的降本增效解決方案。 【學員順利拿證后期訪問】 問&#xff1a;學員您好&#xff0c;首先恭喜您順利拿到RMP證書&#xff0c;請問您在此次備考過程中&#xf…