Python 函數
函數是組織好的,可重復使用的,用來實現單一,或相關聯功能的代碼段
lambda 匿名函數
對于單行函數,使用 lambda
表達式可以省去定義函數的過程,讓代碼更加簡潔;
對于不需要多次復用的函數,使用lambda
表達式可以在用完之后立即釋放,提高程序執(zhí)行的性能。
格式:
-
一般形式
lambda arguments: expression # 示例: add_lambda = lambda a, b: a + b print(add_lambda(10, 20)) # 輸出:30 # 不將 lambda 函數分配給變量,直接使用 result = (lambda x: x * 2)(3) print(result) # 輸出 6
-
含 if 判斷的形式
lambda arguments: value_if_true if condition else value_if_false # 示例: a = lambda x : "偶數" if x % 2 == 0 else "奇數" print(a(10)) # 輸出:偶數
lambda 函數與 def 函數的區(qū)別:
- lambda 可以立刻傳遞(無需變量) ,自動返回結果
- lambda 在內部只能包含一行代碼
- lambda 是一個為編寫簡單的函數而設計的,而 def 用來處理更大的任務
- lambda 可以定義一個匿名函數,而 def 定義的函數必須有一個名字
自定義函數
語法
-
基本語法:
def functionName(param1, param2, ..., paramN): # function_suite return [expression]
-
def :關鍵字,定義函數的聲明
-
functionName :自定義函數名稱
-
(param1, param2, … , paramN) :定義入參
-
Python中,根據實際參數的類型不同,函數參數的傳遞方式可分為按值傳遞和按引用傳遞
-
按值傳遞:適用于字符串、數字、元組
按值傳遞的參數值在函數代碼中發(fā)生改變,函數外面的變量值并不會受到任何影響
-
按引用傳遞:適用于列表,字典、集合
按引用傳遞的參數值在函數中的值改變了,函數外部的值也改變
-
-
可以為參數設定一個默認的值,調用函數時如果沒有傳參,則使用默認值,而如果傳參了,則會覆蓋默認值
默認參數通常放置在參數列表的末尾,以便在函數調用時更靈活。如果將默認參數放在非默認參數之前,則在函數調用時必須使用參數名稱傳參。
def my_sum(num1, num2=1): return num1 + num2
-
參數名稱前面可以加一個星號:表示它會將傳遞進來的(一個或多個)值轉為元組類型
def my_def(*str): print(str) my_def("a") # 輸出:('a',) my_def("a", "b") # 輸出:('a','b')
-
參數名稱前面可以加兩個星號:表示該參數需要接收字典類型的數據,即傳參時需要用等號賦值的形式
def my_def(**str): print(str) my_def(a=1) # 輸出:{'a': 1} my_def(a=1, b=2) # 輸出:{'a': 1, 'b': 2}
-
配置
*
作為函數的一個形參:Python 不會對該*
做任何事情,但是它將知道之后的所有參數都應作為關鍵字參數(鍵值對,也被稱為 kwargs)來調用。即使它們沒有默認值。
-
-
function_suite :函數的邏輯處理代碼塊
-
return [expression] :結束函數,并選擇性地返回一個或多個值給調用方
函數返回值可以是各種數值,字符,類,函數等對象,返回多個值時會被打包為一個元組
如果函數沒有顯式指定返回值,則默認返回
None
,表示空值。None
是一個特殊的Python對象,表示缺失或無效的值。沒有返回值時,return 可省略
-
-
注:
-
函數內容以冒號起始,并且縮進
-
函數的第一行語句可以選擇性地使用文檔字符串(用于存放函數說明)
-
主程序調用函數時,如果函數沒有在之前定義,那就會報出錯誤
但如果是在函數中去調用函數,那函數定義的先后就不受影響
-
調用函數傳參時,可以通過位置和參數名稱兩種方法傳參
def person_info(name, age): print(f"Name: {name}") print(f"Age: {age}") # 位置傳參 person_info(25, "Alice") # 參數名稱傳參 person_info(age=25, name="Alice")
-
返回多個值的解包:
在函數調用時,可以使用多個變量來接收函數返回的多個值。這被稱為解包,可以通過位置或變量名來解包返回的值。
def calculate(x, y): sum = x + y difference = x - y return sum, difference result_sum, result_diff = calculate(8, 3) print(result_sum) # 輸出: 11 print(result_diff) # 輸出: 5
-
由于 python 是不需要編譯的,所以其函數 def 是可執(zhí)行的一條語句,也就意味著直到函數被調用前,這個函數都不存在,直到函數被調用時,def 語句才會創(chuàng)建一個新的函數對象,并賦予名字
-
函數嵌套
-
python 函數還有一大特性就是支持函數的嵌套。所謂的函數嵌套,就是函數里面又有函數
def f1(): print('hello') def f2(): print('python') f2() f1()
-
函數嵌套可以保證內部函數的隱私。
內部函數只能被外部函數所調用和訪問,不會暴露在全局作用域,因此,如果函數內部有一些隱私數據,不想暴露在外,那就可以使用函數的嵌套,將其封裝在內部函數中,只通過外部函數來訪問。其另一個作用就是可以簡化代碼。
函數變量作用域
-
python 函數中變量的作用域和其他語言類似,分為全局變量和局部變量
- 全局變量:函數外定義的變量,程序任意位置都可以訪問
- 局部變量:函數內定義的變量
-
在 python 中不能直接在函數內部隨意改變全局變量的值(直接修改會報錯)
如果需要修改在函數中修改全局變量的值,需要先在函數內使用 global 關鍵字聲明該變量是全局變量
a = 10 def myPrint(): global a a = a + 1 myPrint() print(a) # 輸出:11
-
如果函數內與函數外定義了同名變量,則函數內部就是函數內部定義的值,函數外則是函數外定義的值
-
映射至函數嵌套。如果內部函數要修改外部函數的值,需要先在內部函數內使用 nonlocal 關鍵字聲明一下
def myPrint(): a = 10 def myPrintIn(): nonlocal a a = a + 1 myPrintIn() print(a) myPrint() # 輸出:11
閉包
-
和嵌套函數類似,不同的是外部函數返回的是一個函數,而不是一個具體的值。
當一個內部函數引用了外部函數的變量,并且在外部函數執(zhí)行完畢之后仍然存在,這個內部函數就被認為是一個閉包。
-
閉包的主要優(yōu)點是:
- 可以保護隱藏在外部函數作用域中的數據,使其不能被意外修改。
- 可以為外部函數提供一種延續(xù)性,即使外部函數已經執(zhí)行完畢,閉包仍然可以訪問和使用外部函數的變量。
- 可以允許在多個函數調用之間共享數據。
- 可以使代碼更加簡潔。
-
閉包一般與裝飾器一起使用!
-
示例:
# 定義閉包函數 def color_print(color): def print_with_color(text): print(f"\033[{color}m{text}\033[0m") return print_with_color # 返回內部函數,形成閉包 # 調用閉包函數并賦值變量(創(chuàng)建不同的顏色打印函數) red_print = color_print("31") # 紅色 green_print = color_print("32") # 綠色 # 調用顏色打印函數 red_print("Hello, World!") green_print("Hello, World!")
裝飾器
-
裝飾器是 Python 中一種強大而有用的編程工具,它允許修改、擴展或包裝函數或方法的行為,而無需修改其原始代碼。
裝飾器通常用于代碼重用、修改函數的行為、日志記錄、權限檢查、性能測量等方面。
-
在 Python 中,裝飾器本質上是一個函數,它接受一個函數作為參數,并返回一個新的函數。這個新函數通常會在調用被裝飾的函數之前或之后執(zhí)行一些額外的操作,實現將額外的功能添加到原始函數上。
裝飾器通過在被裝飾的函數定義之前使用 @ 符號來應用。
-
基本語法:
from functools import wraps # 定義裝飾器 def my_decorator(func): # 定義裝飾器的內部函數 @wraps(func) def wrapper(*args, **kwargs): # 執(zhí)行原始函數之前的操作 result = func(*args, **kwargs) # 執(zhí)行原始函數并獲取返回值 # 執(zhí)行原始函數之后的操作 return result return wrapper
-
functools 模塊中的 @wraps 裝飾器:是一個用于創(chuàng)建裝飾器的實用工具。它通常與自定義裝飾器一起使用,以確保被裝飾的函數保留原始函數的元數據(如函數名、文檔字符串、參數列表等)。
當創(chuàng)建一個裝飾器時,通常會包裝或修改原始函數,這可能會導致原始函數的元數據丟失。使用 @wraps 裝飾器可以解決這個問題,它會將包裝函數的元數據設置為與原始函數相同。
@wraps 裝飾器非必需,但推薦使用,比如使用自定義裝飾器裝飾使用 fastapi 框架定義的路由函數時,不加會報錯(解析參數失敗)!
-
裝飾器的內部函數 wrapper 的參數列表通常使用
*args
和**kwargs
,以便能夠接收任意數量和類型的位置參數和名稱參數,并將它們傳遞給原始函數。 -
func(*args, **kwargs)
:調用原始函數并獲取其返回值。 -
在裝飾器的返回語句中,通常是返回 wrapper 函數,注意:是返回 wrapper,不是返回 wrapper()
-
在裝飾器中傳遞參數:可以在裝飾器函數外部包裝一個額外的函數,該額外函數接受參數并返回裝飾器函數。
這樣,就可以通過調用包裝函數來為裝飾器傳遞參數。
-
-
示例:
import datetime # 定義裝飾器外部包裝函數 def timestamp_decorator(arg1, arg2): # 定義裝飾器 def decorator(func): # 定義裝飾器的內部函數 @wraps(func) def wrapper(*args, **kwargs): # 獲取當前時間 timestamp = datetime.datetime.now() # 格式化時間戳 formatted_timestamp = timestamp.strftime("%Y-%m-%d %H:%M:%S") # 打印時間戳并調用原函數 print("[{}]".format(formatted_timestamp), end=" ") return func(*args, **kwargs) return wrapper return decorator # 應用裝飾器 @timestamp_decorator(arg1='', arg2='') def print_with_timestamp(str): print(str) # 調用函數 print_with_timestamp("Hello, World!") # 輸出:[2023-07-16 02:04:59] Hello, World!
為自定義函數寫數據類型注解
-
語法示例
from typing import List # 示例函數,接受一個整數列表作為輸入,并返回一個整數值。 def fun(questions: List[int]) -> int: # 函數體 return 1
-
questions :傳進去的參數
:List[int]
:表明傳入的 questions 類型是整數列表 -
-> int
:表明函數的返回值是 int 類型
注意:
:List[int]
和-> int
都只起到提示作用,并不會改變傳入值返回值的類型和值。 -
-
優(yōu)點:
-
類型注解:
通過在函數定義的參數和返回值上進行類型注解,明確指定了函數的輸入和輸出類型,這樣其他開發(fā)人員在使用和閱讀代碼時更容易理解函數的預期行為和使用方式。
-
錯誤預防:
類型注解可以幫助開發(fā)人員在編寫代碼時捕獲潛在的類型錯誤。如果無意中將其他類型的數據傳遞給函數,或者函數返回了錯誤的類型,類型檢查器可以在開發(fā)階段或靜態(tài)分析階段發(fā)現問題,避免了在運行時出現潛在錯誤。
-
文檔說明:
類型注解可以作為代碼文檔的一部分,幫助其他開發(fā)人員了解函數的預期輸入和輸出。它可以增加代碼的可讀性,讓其他人更容易理解函數的目的和返回值的含義。
-
常用裝飾器
裝飾器是 Python 中一種強大的編程工具,它允許在不修改函數本身的情況下,添加、修改或擴展函數的行為。
常用的 Python 裝飾器:
-
@staticmethod 和 @classmethod : 用于將方法標記為靜態(tài)方法和類方法。
-
@abstractmethod : 用于定義抽象基類和抽象方法,確保子類實現了這些方法
from abc import abstractmethod class Person: @staticmethod def static_method(): pass @classmethod def class_method(cls): pass @abstractmethod def abstract_method(cls): pass
-
@dataclass :用于自動為類生成特殊的方法和默認的特殊方法,以簡化數據類的創(chuàng)建和管理。
@dataclass 可以用來裝飾包含屬性的類,它會自動生成一些通常需要手動編寫的方法,如
__init__()
、__repr__()
、__eq__()
等,從而減少了代碼的重復和冗余。它引入自 Python 3.7,并在 Python 3.8 中得到了增強(如字段類型注解、默認值、默認值工廠函數等)
from dataclasses import dataclass @dataclass class Point: x: int y: int
-
@property 和 @<attribute_name>.setter : 用于創(chuàng)建屬性(getter)和設置屬性(setter)方法,其中
<attribute_name>
應該替換為實際的屬性名稱。通常用于訪問和修改私有實例屬性注:私有實例屬性名稱以一個下劃線
_
開頭,這是一種約定,用于指示這是一個受保護的屬性,不應該直接訪問。通過屬性的 getter 和 setter 方法來訪問和修改屬性值是一種良好的習慣,因為可以在屬性訪問過程中添加額外的邏輯或驗證。
from abc import abstractmethod class Person: def __init__(self, name): self._name = name @property def name(self): return self._name @name.setter def name(self, value): self._name = value person = Person("b") person.name = "a" print(person.name) # 輸出:a
-
@wraps : 用于保留原始函數的元數據(例如文檔字符串、函數名等),通常在自定義裝飾器中使用。
常用內置函數
open():打開并操作文件
-
open() 函數是 Python 內置的文件操作函數,用于打開文件以進行讀取、寫入或追加操作。
通常和
with
語句一起使用,在文件操作完成后,文件會被自動關閉,不需要顯式調用file.close()
。這是一種良好的習慣,可以避免資源泄漏問題。 -
語法如下:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
-
file :要打開的文件的路徑
-
mode :打開文件的操作模式
選項有:
-
‘r’ :只讀模式(打開文件以進行讀?。?,默認。如果文件不存在,則引發(fā)
FileNotFoundError
-
‘w’ :寫入模式(打開文件以進行寫入)。如果文件存在,則會覆蓋已有內容;如果文件不存在,則創(chuàng)建文件
-
‘a’ :追加模式(打開文件以進行寫入)。如果文件存在,將在文件末尾追加數據;如果不存在,則創(chuàng)建文件
-
‘x’ :獨占創(chuàng)建模式(打開文件以供寫入)。如果文件已存在,會引發(fā)
FileExistsError
。用于確保在創(chuàng)建文件時不會覆蓋現有文件。 -
‘t’:文本模式,默認。與上述模式組合(例如 ‘rt’、‘wt’),用于處理文本文件
-
‘b’ :二進制模式。與上述模式組合(例如 ‘rb’、‘wb’),用于處理二進制文件,如圖像、音頻或視頻文件
-
**‘+’ **:讀寫模式與上述模式組合,用于同時讀取和寫入文件
- ‘r+’:讀寫模式,打開文件以供讀取和寫入。如果文件不存在,會引發(fā) FileNotFoundError
- ‘w+’:寫入和讀取模式,打開文件以供讀取和寫入。如果文件不存在,會創(chuàng)建一個新文件,如果文件存在,會覆蓋已有內容
- ‘a+’:追加和讀取模式,打開文件以供讀取和寫入。如果文件不存在,會創(chuàng)建一個新文件。如果文件存在,寫入的內容會追加到文件末尾,而不會清空文件。
-
‘U’ :通用換行模式,打開文件以供讀取。自動識別不同平臺的換行符(
\n
、\r
、\r\n
)Python 3 不建議使用
注意,不同模式的組合可能會導致不同的文件操作行為,因此在選擇模式時要特別小心,以確保符合預期
-
-
buffering :控制文件的緩沖方式,通??梢院雎?,-1 表示使用系統(tǒng)默認的緩沖大小
-
encoding :用于指定文本文件的編碼方式,通常在文本模式下使用。例如:
encoding='utf-8'
-
errors :指定編碼錯誤的處理方式
-
newline :控制換行符的處理方式,在文本模式下使用
-
closefd :指定是否在關閉文件時同時關閉文件描述符,默認為 True。在某些情況下,可能需要將其設置為 False
-
opener :自定義文件打開器,通常不需要使用
-
-
open() 返回的文件對象是一個 Python 內置的文件流,它提供了多種方法來進行文件操作,包括讀取、寫入、定位文件指針等。
以下是一些常用的文件對象方法:
-
read(size=-1) : 從文件中讀取指定數量的字符或字節(jié)。如果未指定大小或大小為負數,則會讀取整個文件
-
readline(size=-1) : 從文件中讀取一行內容。如果指定 size,則讀取指定數量的字符或字節(jié)
-
readlines(hint=-1) : 從文件中讀取多行內容,并將其以列表形式返回。
每一行都作為列表中的一個元素,保留了行尾的換行符(
\n
),換行符可以使用 strip() 函數進行處理。注意,它會將整個文件內容加載到內存中,所以對于非常大的文件可能會導致內存占用問題。如果處理大型文件,可能需要逐行讀取文件而不是一次性讀取所有行。
hint 參數:
-
hint 參數應該作為位置參數傳遞,使用關鍵字參數傳遞會報錯!
-
指定 hint=0 或 hint=-1:用于讀取所有行(直到結束符 EOF)并返回列表
-
指定 hint 的值大于0:
-
對于文本數據:字符數量以 UNICODE 編碼字符集的字符為單位計算。
支持多字節(jié)的字符,如中文一個漢字表示1字符,空格算一個字符。
對于文本文件,換行符是否計入字符,有如下兩種情況:
- 指定字符數中間包含 \n,則 \n 算做字符
- 如果 \n 在指定內容末尾,則不計入字符,算作換行符
-
在二進制模式下,字符數量是以 ASCII 碼對應的單字節(jié)為單位來計算的,不剔除換行符,字符 ‘\n’ 占用一個字節(jié)長度;
-
如果 hint 的值 大于前 n 行的總字數但小于前 n+1 行的總字數,則執(zhí)行函數會讀取文件的前 n+1 行
-
-
-
write(string) :將字符串寫入文件。這個方法在文件以寫入模式 ‘w’、‘a’、‘x’ 或 ‘w+’ 打開時可用
-
writelines(lines) : 將字符串列表寫入文件,通常用于寫入多行文本
-
seek(offset, whence=0) : 將文件指針移動到指定位置
offset 是相對于 whence 參數的偏移量
- whence 值為 0(默認),表示從文件開頭計算偏移量
- whence 值為 1,表示從當前位置計算偏移量
- whence 值為 2,表示從文件末尾計算偏移量
-
tell() :返回當前文件指針的位置,以字節(jié)為單位
-
flush() : 將緩沖區(qū)的數據刷新到文件。通常,文件對象會自動緩沖數據,但在某些情況下,可能需要手動刷新
-
-
示例:
with open('example.txt', 'w+') as file: file.write('Hello, World!') # 寫入文本 file.seek(0) # 將文件指針移回文件開頭 content = file.read() # 讀取文件內容 file.writelines(['Line 1\n', 'Line 2\n', 'Line 3\n']) # 寫入多行文本 file.seek(0) cleaned_lines = [line.strip() for line in lines] # 去除每行末尾的換行符
eval():執(zhí)行字符串命令
-
將字符串當成有效表達式來求值并返回計算結果。
-
eval 函數的作用是去掉字符串最外面的一對引號,然后把去掉最外側引號的字符串通過 python 語句的方式進行操作
-
變量是為了獲取去掉引號后的值,以便進行操作
-
可同 input() 函數一起使用,獲得用戶輸入的數值,使用方式為 變量=eval(input())
-
示例:
eval('print("aaaa")') # 輸出:aaaa
round() :截取小數點后幾位
-
round() 是 Python 內置函數,用于將一個浮點數四舍五入為指定的小數位數。
-
語法:
round(number, ndigits)
- number :是要四舍五入的浮點數。
- ndigits :是要保留的小數位數,可以省略,默認為 0
-
注意:round() 函數在處理浮點數時有一些潛在的問題,可能會導致結果與預期不符。如果對浮點數沒有精度要求時,可以使用 round 函數。如果對浮點數的精度要求較高,推薦使用 decimal 模塊。
-
以下是一些常見的“坑”:
- 精度丟失問題: 浮點數在計算機內部以二進制形式表示,某些十進制分數無法準確表示為二進制分數。這可能導致四舍五入時的精度丟失。
-
奇偶規(guī)則: 當一個數剛好在兩個可能的結果中間時,
round()
函數采用奇偶規(guī)則(round half to even),也稱為銀行家舍入規(guī)則。這意味著它會選擇最接近的偶數。 - 大數問題: 對于非常大的浮點數,四舍五入可能會導致不準確的結果,因為浮點數的精度有限。
-
示例:
print(round(2.875,2)) # 輸出:2.88 # 精度丟失問題 print(round(1.225, 2)) # 輸出: 1.22,而不是 1.2。因為十進制的1.225無法準確表示為二進制分數 # 奇偶規(guī)則 print(round(0.5)) # 輸出: 0 # 大數問題 print(round(1e16 + 0.5)) # 輸出: 10000000000000000,而不是 10000000000000001
vars() 函數
-
用于返回對象的
__dict__
屬性。__dict__
是一個字典,包含了對象的命名空間(即對象的屬性和值)。 -
將一個類實例傳遞給
vars()
函數時,它會返回該實例的屬性和值的字典。將一個類傳遞給
vars()
函數,它會返回該類的命名空間(類屬性和方法)。 -
示例:
class Person: def __init__(self, name, age): self.name = name self.age = age person = Person("Alice", 30) # 返回實例的屬性和值的字典 person_dict = vars(person) print(person_dict) # 輸出:{'name': 'Alice', 'age': 30} # 返回類的命名空間(屬性和方法) person_class_dict = vars(Person) print(person_class_dict) # 輸出:{'__module__': '__main__', '__init__': <function Person.__init__ at 0x...>, ...}
其他的簡單函數
-
type() :用于獲取對象的數據類型
-
range() :返回一個指定范圍內的數字序列
基本語法:
range(start, stop, step)
-
len():用于獲取序列(字符串、列表、元組等)的長度或項目數量
fruits = ['apple', 'banana', 'orange', 'grape'] print(len(fruits)) # 輸出:4
-
sum() :計算序列(例如列表)中的元素總和
-
max()、min() :用于找到序列中的最大值和最小值
-
abs():返回一個數的絕對值
-
sorted():對可迭代對象進行排序
-
enumerate():用于在迭代中獲取元素的索引和值
-
zip():將多個可迭代對象的元素配對成元組
-
map():對可迭代對象的每個元素應用函數
-
filter():過濾可迭代對象中的元素
-
all()、any():分別用于檢查可迭代對象中的所有元素是否為 True 或是否至少有一個元素為 True
-
str.join():將字符串列表或其他可迭代對象的元素連接成一個字符串文章來源:http://www.zghlxwxcb.cn/news/detail-717849.html
-
chr()、ord():分別用于將整數轉換為字符和將字符轉換為整數文章來源地址http://www.zghlxwxcb.cn/news/detail-717849.html
到了這里,關于Python 函數(lambda 匿名函數、自定義函數、裝飾器)基本使用指南的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!