Python 語言以簡潔易學、功能強大著稱,然而要寫出真正高效與易維護的程式碼,則需要更深入的理解和技巧。本文彙整 50 個實務技巧,涵蓋從程式碼風格、資料結構運用到函式設計的各個導向,幫助你將 Python 程式碼提升到新的境界。首先,理解 Python 之禪的核心理念,例如簡潔、明確、優雅,並將其融入程式碼設計中。接著,掌握 Pythonic 的思維方式,善用內建函式和語言特性,避免不必要的複雜性。在資料結構方面,選擇合適的資料結構,例如 tuples、lists、dictionaries 和 sets,可以有效提升程式碼效率。同時,注重程式碼的表達能力,使用有意義的變數和函式名稱,避免魔法數字和字串,並善用列表解析和生成器表示式。在函式設計上,應盡可能編寫純函式,減少副作用,並使用檔案字串、函式註解和 doctests 提升程式碼可讀性和可測試性。最後,活用 Python 的進階特性,如 named tuples、closures、properties 和 metaclasses,以及裝飾器和閉包等技巧,可以寫出更具彈性與高效的程式碼。

掌握Python:提升程式碼品質的50個獨到技巧

Python以其簡潔和強大的功能,成為了廣泛應用的程式語言。但要寫出真正高效、可維護的Python程式碼,需要深入理解其特性並掌握一些進階技巧。玄貓將分享50個具體的技巧,助你精通Python,寫出更優質的程式碼。

Python之禪:編碼哲學的體現

Python之禪(The Zen of Python)是Python社群推崇的一套設計哲學,它體現在Python的設計原則中,例如「優雅勝於醜陋」、「明確勝於隱晦」。理解並遵循這些原則,能寫出更符合Python風格的程式碼。

import this

這段程式碼會顯示Python之禪的內容,時時提醒我們編碼時應追求簡潔、清晰和可讀性。

Pythonic思維:像Pythonista一樣思考

Pythonic是指以Python社群認可的最佳方式來編寫程式碼。這不僅僅是語法上的正確,更重要的是思維方式的轉變,例如充分利用Python內建的功能和特性,避免不必要的複雜性。

Pythonic思維:資料結構與程式碼表達

掌握Pythonic思維,意味著深入瞭解其資料結構、善用語言特性,並寫出簡潔易懂的程式碼。

掌握資料結構:高效編碼的根本

Python提供了多種內建的資料結構,如tuples、lists、dictionaries和sets。選擇合適的資料結構,能顯著提升程式碼的效率和可讀性。

Tuples:不可變的序列

Tuples是不可變的序列,常用於儲存不應被修改的資料。由於其不可變性,Tuples在某些情況下比Lists更有效率。

coordinates = (25.1217, 121.4747) # 經緯度
print(coordinates[0]) # 25.1217

Lists:靈活的可變序列

Lists是最常用的資料結構之一,可以儲存任意型別的元素,並且可以動態增長。

prime_numbers = [2, 3, 5, 7, 11]
prime_numbers.append(13)
print(prime_numbers) # [2, 3, 5, 7, 11, 13]

Dictionaries:鍵值對的樂園

Dictionaries是鍵值對的集合,提供了快速的查詢功能。在處理需要快速檢索的資料時,Dictionaries是理想的選擇。

student = {'name': '玄貓', 'age': 30, 'major': 'CS'}
print(student['name']) # 玄貓

Sets:獨一無二的元素集合

Sets是無序與不重複的元素集合,常用於去重和集合運算。

unique_numbers = {1, 2, 2, 3, 3, 3}
print(unique_numbers) # {1, 2, 3}

Arrays、Queues、Stacks、Heaps、Trees、Graphs:進階資料結構

除了內建資料結構,Python還可以透過模組如arraycollectionsheapq來使用更進階的資料結構,以應對不同的應用場景。

編寫具表達力的程式碼:讓程式碼自己說話

程式碼的可讀性至關重要。透過選擇有意義的名稱、避免魔法數字和字串、使用列表解析和生成器表示式,以及善用內建函式和with陳述式,可以編寫出更清晰易懂的程式碼。

選擇好的名稱:程式碼的自我解釋

變數和函式的命名應具有描述性,能清楚表達其用途。

# 不好的例子
def calc(x, y):
    return x * y

# 好的例子
def calculate_area(length, width):
    return length * width

避免魔法數字和字串:增加程式碼的可維護性

使用常數代替硬編碼的數字和字串,可以提高程式碼的可讀性和可維護性。

# 不好的例子
if score > 90:
    print("優秀")

# 好的例子
EXCELLENT_SCORE = 90
if score > EXCELLENT_SCORE:
    print("優秀")

使用列表解析和生成器表示式:簡潔高效的資料處理

列表解析和生成器表示式可以用簡潔的語法產生新的列表或迭代器。

# 列表解析
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 生成器表示式
even_numbers = (x for x in range(10) if x % 2 == 0)
for number in even_numbers:
    print(number) # 0 2 4 6 8

善用內建函式:事半功倍

Python提供了許多內建函式,如mapfilterreduce,可以簡化程式碼並提高效率。

numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda x: x**2, numbers))
print(squared_numbers) # [1, 4, 9, 16, 25]

使用with陳述式:優雅的資源管理

with陳述式可以確保資源在使用完畢後被正確釋放,例如檔案和網路連線。

with open('my_file.txt', 'r') as file:
    content = file.read()
    print(content)
# 檔案會自動關閉

使用裝飾器:程式碼的元程式設計

裝飾器可以用於修改函式或類別的行為,而無需修改其原始碼。

def my_decorator(func):
    def wrapper():
        print("在函式執行前")
        func()
        print("在函式執行後")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
# 在函式執行前
# Hello!
# 在函式執行後

編寫上下文管理器:自訂資源管理

透過編寫上下文管理器,可以自訂資源的管理方式,例如自動建立和關閉資料函式庫連線。

import contextlib

@contextlib.contextmanager
def database_connection():
    print("建立資料函式庫連線")
    yield
    print("關閉資料函式庫連線")

with database_connection():
    print("執行資料函式庫操作")
# 建立資料函式庫連線
# 執行資料函式庫操作
# 關閉資料函式庫連線

活用Python特性:進階技巧

Python提供了許多獨特的特性,如named tuples、closures、properties和metaclasses。掌握這些特性,可以寫出更靈活和高效的程式碼。

使用named tuples:具名的資料容器

Named tuples是tuples的擴充套件,允許為tuple的每個元素命名,提高程式碼的可讀性。

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])
point = Point(x=1, y=2)
print(point.x, point.y) # 1 2

活用closures:函式的狀態保持

Closures是指在函式中定義的函式,可以存取外部函式的變數,即使外部函式已經執行完畢。

def outer_function(msg):
    def inner_function():
        print(msg)
    return inner_function

hello_func = outer_function("Hello")
hello_func() # Hello

使用properties:控制屬性存取

Properties可以用於控制類別屬性的存取,例如進行驗證或計算。

class MyClass:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, new_value):
        if new_value < 0:
            raise ValueError("Value must be non-negative")
        self._value = new_value

obj = MyClass(10)
print(obj.value) # 10
obj.value = 20
print(obj.value) # 20

使用descriptors:自訂屬性行為

Descriptors可以用於自訂屬性的讀取、設定和刪除行為,提供更精細的控制。

使用metaclasses:類別的類別

Metaclasses可以用於在類別建立時修改其行為,實作更高階的元程式設計。

編寫符合Python慣例的程式碼:融入社群

編寫符合Python慣例的程式碼,可以使程式碼更易於理解和維護。這包括使用Pythonic迴圈、enumeratezip、三元運算元、多重指定和海象運算元。

編寫Pythonic迴圈:簡潔的迭代

使用for迴圈迭代序列時,應直接迭代元素,而不是使用索引。

# 不好的例子
my_list = ['a', 'b', 'c']
for i in range(len(my_list)):
    print(my_list[i])

# 好的例子
my_list = ['a', 'b', 'c']
for item in my_list:
    print(item)

使用enumeratezip:優雅的迭代工具

enumerate可以用於同時迭代索引和元素,zip可以用於同時迭代多個序列。

my_list = ['a', 'b', 'c']
for index, item in enumerate(my_list):
    print(index, item)
# 0 a
# 1 b
# 2 c

list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
for item1, item2 in zip(list1, list2):
    print(item1, item2)
# 1 a
# 2 b
# 3 c

使用三元運算元:簡潔的條件表示式

三元運算元可以用於在一行中表達簡單的條件判斷。

age = 20
status = "成年" if age >= 18 else "未成年"
print(status) # 成年

使用多重指定:優雅的變數交換

多重指定可以用於同時指定多個變數,也可以用於交換變數的值。

a, b = 1, 2
print(a, b) # 1 2

a, b = b, a
print(a, b) # 2 1

使用海象運算元:簡潔的指定和判斷

海象運算元(:=)可以在表示式中同時進行指定和判斷。

if (n := len(my_list)) > 10:
    print(f"List is too long ({n} elements)")

函式:程式碼的組織與重用

函式是程式碼的基本 building block。理解函式的基本概念、設計原則和進階技巧,能寫出更模組化和可維護的程式碼。

函式基礎:引數、傳回值和檔案

函式的基本要素包括引數、傳回值和檔案。良好的函式設計應考慮到這些要素。

函式引數和傳回值:資料的輸入和輸出

函式可以接收零個或多個引數,並傳回一個值。引數可以是必需的或可選的,傳回值可以是任意型別。

def add(x, y):
    """傳回x和y的和"""
    return x + y

result = add(1, 2)
print(result) # 3

檔案化函式:提高程式碼的可讀性

使用檔案字串(docstrings)可以為函式增加說明檔案,方便其他開發者理解函式的用途和使用方法。

def add(x, y):
    """
    傳回x和y的和

    引數:
    x (int): 第一個數字
    y (int): 第二個數字

    傳回值:
    int: x和y的和
    """
    return x + y

編寫doctests:驗證函式的正確性

Doctests是一種將測試程式碼嵌入到檔案字串中的方法,可以方便地驗證函式的正確性。

def add(x, y):
    """
    傳回x和y的和

    >>> add(1, 2)
    3
    >>> add(3, 4)
    7
    """
    return x + y

編寫函式註解:提高程式碼的可讀性

函式註解可以用於指定函式引數和傳回值的型別,提高程式碼的可讀性和可維護性。

def add(x: int, y: int) -> int:
    """傳回x和y的和"""
    return x + y

使用預設引數:簡化函式呼叫

預設引數可以為函式的引數提供預設值,簡化函式呼叫。

def greet(name="World"):
    """傳回一個問候語"""
    return f"Hello, {name}!"

print(greet()) # Hello, World!
print(greet("玄貓")) # Hello, 玄貓!

使用關鍵字引數:提高程式碼的可讀性

關鍵字引數允許在呼叫函式時使用引數的名稱,提高程式碼的可讀性。

def describe_person(name, age, city):
    """傳回一個人的描述"""
    return f"{name} is {age} years old and lives in {city}."

print(describe_person(name="玄貓", age=30, city="台北"))
# 玄貓 is 30 years old and lives in 台北.

使用*args**kwargs:靈活的引數處理

*args**kwargs可以用於接收不定數量的位置引數和關鍵字引數。

def my_function(*args, **kwargs):
    """接收不定數量的位置引數和關鍵字引數"""
    print("args:", args)
    print("kwargs:", kwargs)

my_function(1, 2, 3, name="玄貓", age=30)
# args: (1, 2, 3)
# kwargs: {'name': '玄貓', 'age': 30}

函式設計:純函式與副作用

良好的函式設計應考慮到函式的純度和副作用。純函式是指沒有副作用的函式,即不修改任何外部狀態。

編寫純函式:提高程式碼的可測試性

純函式是指沒有副作用的函式,即不修改任何外部狀態。純函式的輸出只取決於輸入,易於測試和除錯。

def multiply(x, y):
    """傳回x和y的乘積"""
    return x * y

編寫帶副作用的函式:與外部世界互動

帶副作用的函式是指會修改外部狀態的函式,例如修改全域變數或寫入檔案。帶副作用的函式需要謹慎使用,因為它們會使程式碼更難以測試和除錯。

編寫修改可變引數的函式:謹慎操作

修改可變引數的函式需要謹慎使用,因為它們可能會影響函式外部的資料。

使用@staticmethod@classmethod裝飾器:類別相關的函式

@staticmethod@classmethod裝飾器可以用於定義與類別相關的函式。@staticmethod定義的函式不接收self引數,@classmethod定義的函式接收cls引數。

使用partial函式:固定部分引數

Partial函式可以用於固定函式的部分引數,產生一個新的函式。

from functools import partial

def power(base, exponent):
    """傳回base的exponent次方"""
    return base ** exponent

square = partial(power, exponent=2)
print(square(5)) # 25

函式裝飾器和閉包:進階技巧

函式裝飾器和閉包是Python中強大的進階技巧,可以用於修改函式的行為或保持函式的狀態。

編寫簡單的裝飾器:修改函式行為

裝飾器可以用於修改函式的行為,而無需修改其原始碼。

編寫帶引數的裝飾器:更靈活的裝飾器

帶引數的裝飾器可以接收引數,提供更靈活的裝飾功能。

編寫類別裝飾器:裝飾類別

類別裝飾器可以用於裝飾類別,修改類別的行為。

使用閉包:保持函式的狀態

閉包是指在函式中定義的函式,可以存取外部函式的變數,即使外部函式已經執行完畢。

使用functools.partial:固定部分引數

functools.partial可以用於固定函式的部分引數,產生一個新的函式。