繼續總結Python中那些簡單好用的用法

ops-coffee發表於2024-03-08

上一篇文章Python中那些簡單又好用的特性和用法發出後,群裡的小夥伴又給補充了幾個好用的用法,結合生產實用經驗彙總整理如下,各位看官如有需要請自取

  1. 反射,反射是一種機制,可以在執行時獲取、檢查和修改物件的屬性和方法。Python提供了一些內建的函式和屬性,可以用於實現反射操作

dir()函式:返回物件的所有屬性和方法的列表

class MyClass:
    def __init__(self):
        self.name = "運維咖啡吧"
        self.age = 25

my_obj = MyClass()
print(dir(my_obj))

getattr()函式:獲取物件的屬性或方法

class MyClass:
    def __init__(self):
        self.name = "運維咖啡吧"
        self.age = 25

my_obj = MyClass()
name = getattr(my_obj, "name")
print(name)

setattr()函式:設定物件的屬性或方法

class MyClass:
    def __init__(self):
        self.name = "運維咖啡吧"
        self.age = 25

my_obj = MyClass()
setattr(my_obj, "name", "blog.ops-coffee.cn")
print(my_obj.name)

hasattr()函式:檢查物件是否具有指定的屬性或方法

class MyClass:
    def __init__(self):
        self.name = "運維咖啡吧"
        self.age = 25

my_obj = MyClass()
has_name = hasattr(my_obj, "name")
print(has_name)

這些函式和屬性可以幫助你在執行時動態地訪問和修改物件的屬性和方法。反射為編寫更靈活和通用的程式碼提供了一種機制,可以根據需要操作物件的屬性和方法

  1. 交換變數,這是一種非常常見和方便的操作,可以在需要時快速交換變數的值
a = 10
b = 20

a, b = b, a

print(a, b)  # 輸出: 20 10
  1. 可迭代物件解包,它允許你將可迭代物件的元素解包到單獨的變數中。這對於同時處理多個值非常有用
# 解包元組
a, b, c = (1, 2, 3)
print(a, b, c)   # 輸出: 1 2 3

# 解包列表
x, y, z = [4, 5, 6]
print(x, y, z)   # 輸出: 4 5 6
  1. 深複製和淺複製,當處理複雜的資料結構時,深複製和淺複製允許你建立物件的副本。深複製會建立一個全新的物件,而淺複製會建立一個新物件,但共享內部資料。
import copy

# 建立一個列表
original_list = [1, 2, [3, 4]]

# 淺複製
shallow_copy = copy.copy(original_list)

# 深複製
deep_copy = copy.deepcopy(original_list)

# 修改原始列表中的巢狀列表
original_list[2][0] = 5

print(original_list)   # 輸出: [1, 2, [5, 4]]
print(shallow_copy)    # 輸出: [1, 2, [5, 4]]
print(deep_copy)       # 輸出: [1, 2, [3, 4]]
  1. with語句的多個上下文管理器:在一個with語句中,你可以同時使用多個上下文管理器,以便在程式碼塊執行前後執行多個操作
class CustomContextManager1:
    def __enter__(self):
        print("Entering CustomContextManager1")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting CustomContextManager1")

class CustomContextManager2:
    def __enter__(self):
        print("Entering CustomContextManager2")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting CustomContextManager2")

# 使用多個上下文管理器
with CustomContextManager1(), CustomContextManager2():
    # 在這裡執行一些操作

比較常用的是一次開啟多個檔案進行操作,例如同時開啟檔案1和檔案2,讀取檔案1內容處理後寫入檔案2

with open("file1.txt") as file1, open("file2.txt") as file2:
    # 在這裡可以使用file1和file2進行操作
  1. 裝飾器,透過裝飾器來複用函式,簡化操作
# 建立一個裝飾器函式,用於計算函式執行時間
import time

def calculate_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"函式 {func.__name__} 執行時間為: {end_time - start_time} 秒")
        return result
    return wrapper

# 應用裝飾器到函式
@calculate_time
def long_running_function():
    time.sleep(2)

long_running_function()
  1. 使用字典來代替冗長的if/else判斷,提升程式碼可讀性
def operation_add(a, b):
    return a + b

def operation_subtract(a, b):
    return a - b

def operation_multiply(a, b):
    return a * b

def operation_divide(a, b):
    return a / b

# 定義一個操作字典,將操作名對映到對應的函式上
operations = {
    "add": operation_add,
    "subtract": operation_subtract,
    "multiply": operation_multiply,
    "divide": operation_divide
}

# 使用字典進行操作選擇和呼叫相應的函式
result = operations["multiply"](2, 3)
print("結果:", result)
  1. 字串格式化,使用佔位符和格式化字串來構建新的字串
name = "Alice"
age = 25
message = "My name is {} and I am {} years old.".format(name, age)
# 輸出: "My name is Alice and I am 25 years old."
  1. 使用lamba函式進行簡單的函式定義
add = lambda x, y: x + y
result = add(2, 3)
# 輸出: 5
  1. 使用reversed函式反轉可迭代物件
numbers = [1, 2, 3, 4, 5]
reversed_numbers = list(reversed(numbers))
# 輸出: [5, 4, 3, 2, 1]
  1. 使用map函式對可迭代物件中的每個元素應用指定的函式
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda x: x**2, numbers))
# 輸出: [1, 4, 9, 16, 25]
  1. 使用filter函式根據指定的條件篩選可迭代物件中的元素
numbers = [1, 2, 3, 4, 5]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
# 輸出: [2, 4]
  1. 生成器函式,使用yield關鍵字來生成一個值,並且在每次生成值後暫停執行,等待下一次呼叫
# 下面是一個簡單的生成器函式示例,用於生成斐波那契數列
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci()
print(next(fib))  # 輸出:0
print(next(fib))  # 輸出:1
print(next(fib))  # 輸出:1

生成器函式可以一次生成一個值,而不是一次生成所有值,這使得生成器函式非常適合處理大量資料或無限序列

  1. 使用functools模組中的partial函式進行函式引數固定:partial函式可以固定函式的部分引數,生成一個新的函式
from functools import partial

def power(x, y):
    return x ** y

square = partial(power, y=2)
cube = partial(power, y=3)

print(square(5))  # 輸出 25
print(cube(5))  # 輸出 125
  1. 使用try...else語句在try塊沒有引發異常時執行特定的程式碼
try:
    # 可能會引發異常的程式碼
    result = 10 / 2
except ZeroDivisionError:
    # 如果發生ZeroDivisionError異常
    print("除數不能為零!")
else:
    # 如果沒有發生異常
    print("結果為:", result)

類似的還有try...finally無論是否發生異常,都會執行

try:
    # 可能會引發異常的程式碼
    f = open('example.txt', 'r')
    # 其他操作
except IOError:
    # 如果發生IOError異常
    print("無法開啟檔案")
else:
    # 如果沒有發生異常
    print(f.read())
finally:
    # 無論是否發生異常,都會執行的清理程式碼
    f.close()
  1. 透過signal解耦程式碼
import signal
import os

# 定義一個事件處理函式
def handle_event(signum, frame):
    if signum == signal.SIGUSR1:
        print("接收到使用者定義訊號1,執行事件A")
        # 執行事件A的邏輯
    elif signum == signal.SIGUSR2:
        print("接收到使用者定義訊號2,執行事件B")
        # 執行事件B的邏輯
    else:
        print(f"接收到未知訊號: {signum}")

# 註冊事件處理函式
signal.signal(signal.SIGUSR1, handle_event)  # 註冊處理使用者定義訊號1的事件處理函式
signal.signal(signal.SIGUSR2, handle_event)  # 註冊處理使用者定義訊號2的事件處理函式

# 模擬傳送事件訊號
def send_event1():
    # 傳送使用者定義訊號1
    print("傳送使用者定義訊號1")
    os.kill(os.getpid(), signal.SIGUSR1)

def send_event2():
    # 傳送使用者定義訊號2
    print("傳送使用者定義訊號2")
    os.kill(os.getpid(), signal.SIGUSR2)

# 執行事件
send_event1()  # 執行事件1
send_event2()  # 執行事件2

兩篇文章一共總結了32個用法,先這麼多,歡迎大夥繼續補充

相關文章