加油,今天的任務是學習面向對象編程,設計一個簡單的寵物管理系統(寵物類、貓 / 狗子類),先做5道題目開啟學習狀態吧!
1 setdefault()
在 Python 中,setdefault()
?是字典(dict
)對象的一個內置方法,用于安全地獲取或設置字典中的鍵值對。
它的核心作用是:當字典中不存在指定的鍵時,自動為其設置默認值并返回;若鍵已存在,則直接返回現有值。
基本語法
python
運行
dict.setdefault(key, default=None)
- 參數:
key
:必需,要查找或設置的鍵。default
:可選,當鍵不存在時設置的默認值(默認為?None
)。
- 返回值:鍵對應的值(若鍵已存在)或新設置的默認值(若鍵不存在)。
核心邏輯
- 若鍵已存在:直接返回鍵對應的值,不修改字典。
- 若鍵不存在:
- 將鍵添加到字典中,值設為?
default
。 - 返回這個默認值。
- 將鍵添加到字典中,值設為?
典型應用場景
1.?統計元素頻率(如你提供的代碼)
python
運行
s = "abcasdacbdec"
d = {}
for char in s:d[char] = d.setdefault(char, 0) + 1
print(d) # 輸出:{'a': 2, 'b': 2, 'c': 3, 's': 1, 'd': 2, 'e': 1}
等價邏輯(不用?setdefault()
):
python
運行
if char not in d:d[char] = 0 # 初始化
d[char] += 1 # 累加
2.?初始化嵌套字典
python
運行
data = {}
data.setdefault("users", {})["Alice"] = {"age": 30}
print(data) # 輸出:{'users': {'Alice': {'age': 30}}}
等價于:
python
運行
if "users" not in data:data["users"] = {}
data["users"]["Alice"] = {"age": 30}
3.?處理默認值的復雜場景
python
運行
# 統計每個字母開頭的名字列表
names = ["Alice", "Bob", "Charlie", "Alex"]
groups = {}
for name in names:letter = name[0]groups.setdefault(letter, []).append(name)
print(groups)
# 輸出:{'A': ['Alice', 'Alex'], 'B': ['Bob'], 'C': ['Charlie']}
與其他方法的對比
方法 | 鍵存在時 | 鍵不存在時 | 是否修改字典 |
---|---|---|---|
dict.setdefault(key, default) | 返回現有值 | 設置默認值并返回 | ? |
dict.get(key, default) | 返回現有值 | 返回默認值(不修改字典) | ? |
key in dict ?+ 手動賦值 | 需要額外判斷 | 需手動初始化并賦值 | ? |
注意事項
默認值的計算時機:
default
?參數在鍵不存在時才會被計算。例如:python
運行
d = {} d.setdefault("key", [].append(1)) # 默認值為 None,因為 append() 返回 None
避免使用可變對象作為默認值:
python
運行
# 錯誤示范:所有鍵共享同一個列表 d = {} d.setdefault("a", []).append(1) d.setdefault("b", []).append(2) print(d) # 可能輸出 {'a': [1, 2], 'b': [1, 2]}(取決于實現)
正確做法:每次調用時創建新對象:
python
運行
d.setdefault("a", list()).append(1)
性能考量:
setdefault()
?比先判斷?if key not in dict
?再賦值略快,因為只需要查找一次鍵。
總結
setdefault()
?的核心優勢在于用一行代碼替代三行代碼(判斷鍵是否存在 → 不存在則初始化 → 返回值),讓代碼更簡潔。
但在需要頻繁初始化默認值的場景中,使用?collections.defaultdict
?可能更高效。
2 lambda函數
在 Python 中,lambda
?函數是一種匿名函數(即沒有顯式定義函數名的函數),它允許你快速創建簡單的、單行的函數。它的核心設計目的是為了滿足臨時、一次性使用的簡單函數需求,讓代碼更簡潔。
一、基本語法
python
運行
lambda 參數1, 參數2, ...: 表達式
- 參數:可以有零個或多個,用逗號分隔。
- 表達式:函數的返回值,只能包含一個表達式(不能包含語句,如?
if
、for
?等)。
示例:定義一個加法函數:
python
運行
add = lambda x, y: x + y
print(add(3, 5)) # 輸出:8
等價的普通函數:
python
運行
def add(x, y):return x + y
二、核心特性
1.?匿名性
lambda
?函數沒有顯式的函數名,通常賦值給變量或作為參數傳遞給其他函數。
python
運行
# 作為參數傳遞給 sorted()
names = ["Alice", "Bob", "Charlie"]
sorted_names = sorted(names, key=lambda name: len(name))
print(sorted_names) # 輸出:['Bob', 'Alice', 'Charlie']
2.?單一表達式
lambda
?只能包含一個表達式,不能包含復雜的邏輯。例如,不能直接使用條件語句,但可以用三元表達式:
python
運行
# 返回絕對值
abs_value = lambda x: x if x >= 0 else -x
print(abs_value(-5)) # 輸出:5
3.?即時執行
可以立即調用?lambda
?函數:
python
運行
result = (lambda x: x * x)(3)
print(result) # 輸出:9
三、常見應用場景
1.?作為高階函數的參數
在?sorted()
、map()
、filter()
、reduce()
?等函數中作為排序規則或操作邏輯:
python
運行
# map():對列表每個元素平方
nums = [1, 2, 3]
squares = list(map(lambda x: x**2, nums))
print(squares) # 輸出:[1, 4, 9]# filter():篩選偶數
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens) # 輸出:[2]
2.?回調函數
在 GUI 編程或異步編程中作為事件處理函數:
python
運行
# 示例(偽代碼):按鈕點擊事件
button.on_click(lambda: print("Button clicked!"))
3.?閉包
捕獲外部變量,創建閉包:
python
運行
def multiplier(n):return lambda x: x * ndouble = multiplier(2)
print(double(5)) # 輸出:10
四、優缺點
優點
- 簡潔:減少代碼行數,適合簡單邏輯。
- 可讀性:在合適場景下(如排序規則),比普通函數更直觀。
- 臨時使用:無需命名,避免污染命名空間。
缺點
- 功能受限:只能包含單個表達式,復雜邏輯需改用普通函數。
- 可讀性下降:過度使用或嵌套?
lambda
?會導致代碼晦澀難懂。 - 調試困難:沒有函數名,堆棧跟蹤信息不直觀。
五、與普通函數的對比
特性 | lambda 函數 | 普通函數 (def ) |
---|---|---|
定義語法 | 單行表達式 | 多行語句塊 |
函數名 | 匿名,需賦值給變量 | 必須有函數名 |
返回值 | 自動返回表達式結果 | 必須顯式使用?return ?語句 |
邏輯復雜度 | 只能包含簡單表達式 | 可以包含任意復雜邏輯 |
文檔字符串 | 不支持 | 支持(使用?__doc__ ) |
六、注意事項
- 避免過度使用:如果?
lambda
?邏輯復雜,建議用普通函數提高可讀性。 - 默認參數:支持默認參數,但需注意參數綁定問題:
python
運行
# 錯誤示例:所有函數共享同一個 x 值 funcs = [lambda x=x: x*2 for x in range(3)] print(funcs[0](10)) # 輸出:20(正確)
- 性能:與普通函數無顯著差異,但復雜邏輯用普通函數更高效。
總結
lambda
?函數是 Python 中一種輕量級的函數定義方式,適合快速定義簡單的、一次性使用的函數。它在高階函數、回調邏輯等場景中特別有用,但需適度使用,避免犧牲代碼可讀性。對于復雜或復用性高的函數,仍建議使用普通函數。
個人理解:看起來就是懶得def一個函數了(^ ^)
你的觀察很準確!lambda
?的核心設計目的就是為了避免為簡單功能專門定義一個完整的函數,讓代碼更簡潔。它本質上是一種語法糖,用于快速創建一次性的、簡短的函數,特別適合作為參數傳遞給其他函數的場景。
為什么需要?lambda
?
對比以下兩種寫法:
場景:對列表按元素長度排序
使用?def
:
python
運行
def get_length(s):return len(s)names = ["Alice", "Bob", "Charlie"]
sorted(names, key=get_length) # 需要先定義函數,再傳遞
使用?lambda
:
python
運行
names = ["Alice", "Bob", "Charlie"]
sorted(names, key=lambda s: len(s)) # 直接內聯定義,無需命名
優勢:
- 減少命名污染:無需為臨時函數創建名稱(如?
get_length
)。 - 代碼緊湊:函數定義與使用位置更接近,邏輯更連貫。
- 即時性:適合只需使用一次的簡單邏輯,避免函數定義的 “儀式感”。
哪些場景最適合用?lambda
?
- 排序規則(如?
sorted()
、list.sort()
?的?key
?參數)。 - 數據轉換(如?
map()
、filter()
?的操作函數)。 - 回調函數(如 GUI 事件處理、異步編程)。
- 閉包(如創建輕量級工廠函數)。
與?def
?的權衡
場景 | lambda | def |
---|---|---|
簡單的單行邏輯 | ? 完美選擇 | ? 過于繁瑣 |
復雜邏輯(多語句、循環等) | ? 不支持 | ? 必須使用 |
需要復用的函數 | ? 難以復用 | ? 定義一次,多處調用 |
需要文檔字符串或類型注解 | ? 不支持 | ? 完整支持 |
一句話總結
lambda
?就像是程序員的 “便利貼”—— 當你需要快速寫一個臨時的、簡單的功能,又不想費心思命名和組織一個完整的函數時,它就是最佳選擇。
但對于復雜或需要復用的邏輯,還是應該用?def
?定義正式的函數。
3?zip函數
在 Python 里,zip()
?是一個很實用的內置函數,它能夠將多個可迭代對象(像列表、元組、字符串等)中對應的元素打包成一個個元組,最后返回由這些元組組成的迭代器。
這種功能在需要同時處理多個可迭代對象的元素時特別有用。下面為你詳細介紹它的用法和特性:
基本語法
python
運行
zip(*iterables)
這里的?*iterables
?表示接受任意數量的可迭代對象作為參數。
基礎示例
python
運行
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]# 對兩個列表進行打包
zipped = zip(names, ages)# 將迭代器轉換為列表查看結果
print(list(zipped)) # 輸出:[('Alice', 25), ('Bob', 30), ('Charlie', 35)]
處理多個可迭代對象
zip()
?函數可以處理任意數量的可迭代對象。
python
運行
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
scores = [85, 90, 78]# 對三個列表進行打包
zipped = zip(names, ages, scores)print(list(zipped)) # 輸出:[('Alice', 25, 85), ('Bob', 30, 90), ('Charlie', 35, 78)]
處理不同長度的可迭代對象
當可迭代對象的長度不一致時,zip()
?會以最短的可迭代對象為標準進行截斷。
python
運行
names = ['Alice', 'Bob', 'Charlie'] # 長度為3
ages = [25, 30] # 長度為2zipped = zip(names, ages)print(list(zipped)) # 輸出:[('Alice', 25), ('Bob', 30)],'Charlie'被忽略了
與循環結合使用
在循環中使用?zip()
?可以同時遍歷多個可迭代對象。
python
運行
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]for name, age in zip(names, ages):print(f"{name} is {age} years old.")# 輸出:
# Alice is 25 years old.
# Bob is 30 years old.
# Charlie is 35 years old.
解壓操作
借助?*
?操作符和?zip()
?可以實現解壓。
python
運行
pairs = [('Alice', 25), ('Bob', 30), ('Charlie', 35)]names, ages = zip(*pairs)print(names) # 輸出:('Alice', 'Bob', 'Charlie')
print(ages) # 輸出:(25, 30, 35)
注意事項
- 返回的是迭代器:在 Python 3 中,
zip()
?返回的是一個迭代器,這意味著它是惰性計算的,僅在需要時才生成值。如果需要多次使用結果或者將其轉換為列表,就需要手動進行轉換。 - 截斷行為:當可迭代對象長度不同時,
zip()
?會截斷結果,只處理到最短的可迭代對象結束。要是你希望處理到最長的可迭代對象結束,可以使用?itertools.zip_longest()
?函數。 - 空可迭代對象:如果傳入空的可迭代對象,
zip()
?會直接返回一個空迭代器。
zip()
?函數是 Python 中進行并行迭代的重要工具,在數據處理、循環操作以及函數參數傳遞等場景中都經常會用到。
4 Python 的?dict
(字典)
Python 的?dict
(字典)?是一種非常重要且強大的數據結構,用于存儲鍵值對(Key-Value Pairs)。它類似于現實中的字典,通過 “鍵”(key)可以快速找到對應的 “值”(value)。下面從基礎到進階詳細介紹:
1. 基礎概念
特點
- 無序存儲(Python 3.7+ 后保留插入順序)。
- 鍵必須唯一,且不可變(如字符串、數字、元組)。
- 值可以是任意類型,如整數、列表、甚至其他字典。
創建字典
python
運行
# 方式 1:直接用花括號
empty_dict = {}
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}# 方式 2:使用 dict() 構造函數
person = dict(name='Bob', age=30, city='London') # 關鍵字參數# 方式 3:從鍵值對列表創建
pairs = [('name', 'Charlie'), ('age', 35)]
person = dict(pairs) # {'name': 'Charlie', 'age': 35}# 方式 4:使用 dict.fromkeys()
keys = ['a', 'b', 'c']
default_value = 0
my_dict = dict.fromkeys(keys, default_value) # {'a': 0, 'b': 0, 'c': 0}
2. 基本操作
訪問值
python
運行
person = {'name': 'Alice', 'age': 25}print(person['name']) # 輸出:Alice(鍵存在)
# print(person['city']) # 報錯:KeyError(鍵不存在)print(person.get('city')) # 輸出:None(默認值)
print(person.get('city', 'N/A')) # 輸出:N/A(自定義默認值)
修改 / 添加鍵值對
python
運行
person = {'name': 'Alice', 'age': 25}person['age'] = 26 # 修改已有鍵的值
person['city'] = 'Paris' # 添加新鍵值對print(person) # 輸出:{'name': 'Alice', 'age': 26, 'city': 'Paris'}
刪除鍵值對
python
運行
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}age = person.pop('age') # 刪除鍵 'age',返回其值 25
del person['city'] # 直接刪除鍵 'city'print(person) # 輸出:{'name': 'Alice'}
判斷鍵是否存在
python
運行
person = {'name': 'Alice', 'age': 25}print('name' in person) # 輸出:True
print('city' in person) # 輸出:False
3. 常用方法
獲取所有鍵 / 值 / 鍵值對
python
運行
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}print(person.keys()) # 輸出:dict_keys(['name', 'age', 'city'])
print(person.values()) # 輸出:dict_values(['Alice', 25, 'New York'])
print(person.items()) # 輸出:dict_items([('name', 'Alice'), ('age', 25), ('city', 'New York')])# 遍歷鍵值對
for key, value in person.items():print(f"{key}: {value}")
合并字典
python
運行
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}# 方式 1:update() 方法(修改原字典)
dict1.update(dict2)
print(dict1) # 輸出:{'a': 1, 'b': 3, 'c': 4}# 方式 2:使用 | 運算符(Python 3.9+)
merged = dict1 | dict2 # 創建新字典,不修改原字典
安全獲取值:setdefault()
python
運行
person = {'name': 'Alice', 'age': 25}# 如果鍵不存在,設置默認值并返回
city = person.setdefault('city', 'New York')
print(city) # 輸出:New York
print(person) # 輸出:{'name': 'Alice', 'age': 25, 'city': 'New York'}# 如果鍵存在,不修改并返回已有值
age = person.setdefault('age', 30)
print(age) # 輸出:25(已有值)
4. 高級用法
字典推導式
python
運行
# 從列表創建字典
numbers = [1, 2, 3, 4]
squares = {num: num**2 for num in numbers}
print(squares) # 輸出:{1: 1, 2: 4, 3: 9, 4: 16}# 篩選元素
even_squares = {num: num**2 for num in numbers if num % 2 == 0}
print(even_squares) # 輸出:{2: 4, 4: 16}
嵌套字典
python
運行
students = {'Alice': {'age': 25, 'grades': [85, 90, 95]},'Bob': {'age': 24, 'grades': [75, 80, 85]}
}print(students['Alice']['grades']) # 輸出:[85, 90, 95]
有序字典(Python 3.7+ 默認有序)
python
運行
# Python 3.7+ 中,dict 會保留插入順序
ordered_dict = {}
ordered_dict['a'] = 1
ordered_dict['b'] = 2
ordered_dict['c'] = 3print(ordered_dict) # 輸出:{'a': 1, 'b': 2, 'c': 3}
5. 性能特點
- 查找速度極快:時間復雜度為 O (1),適合大數據量的快速查找。
- 鍵必須可哈希:鍵需要是不可變類型(如字符串、數字、元組),因為字典使用哈希表實現。
6. 常見應用場景
統計詞頻
python
運行
words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']
word_count = {}for word in words:word_count[word] = word_count.get(word, 0) + 1print(word_count) # 輸出:{'apple': 3, 'banana': 2, 'cherry': 1}
配置管理
python
運行
default_config = {'theme': 'light','font_size': 12,'show_ads': True
}user_config = {'font_size': 14,'show_ads': False
}# 合并配置
final_config = default_config.copy()
final_config.update(user_config)print(final_config) # 輸出:{'theme': 'light', 'font_size': 14, 'show_ads': False}
7. 與其他數據結構的對比
數據結構 | 特點 | 適用場景 |
---|---|---|
dict | 鍵值對,無序,查找快 | 快速查找、統計、配置管理 |
list | 有序,可重復,支持索引 | 有序集合、需要順序訪問的場景 |
set | 無序,唯一,支持集合運算 | 去重、成員檢測、集合操作 |
總結
dict
?是 Python 中最常用的數據結構之一,其核心優勢是高效的鍵值對存儲和快速查找。掌握?dict
?的各種方法(如?get()
、setdefault()
、update()
)和高級用法(推導式、嵌套),能讓你的代碼更簡潔、高效。
5??Python 的?zip()
、dict
?和?Java 的?Map
?放在一起對比
1. 核心概念對比
特性 | Python?zip() | Python?dict | Java?Map |
---|---|---|---|
本質 | 迭代器(生成元組) | 鍵值對集合(哈希表) | 鍵值對接口(如?HashMap ) |
用途 | 并行迭代多個序列,生成臨時配對 | 存儲、查詢和操作鍵值對 | 存儲、查詢和操作鍵值對 |
鍵的唯一性 | 不保證(可重復) | 鍵必須唯一(重復會覆蓋) | 鍵必須唯一 |
示例語法 | zip(keys, values) | {'a': 1, 'b': 2} | Map<String, Integer> map = new HashMap<>() |
2. 三者關聯與轉換
從?zip()
?到?dict
~~~~~~\(@_@)/~~~~~~
zip()
?生成的元組可直接轉為?dict
:
python
運行
keys = ['a', 'b', 'c']
values = [1, 2, 3]# 用 zip() 創建字典
my_dict = dict(zip(keys, values))
print(my_dict) # 輸出:{'a': 1, 'b': 2, 'c': 3}
Python?dict
?與 Java?Map
?的等價操作
操作 | Python?dict | Java?Map |
---|---|---|
創建字典 / 映射 | person = {'name': 'Alice', 'age': 25} | Map<String, Integer> map = new HashMap<>(); |
添加 / 修改鍵值對 | person['city'] = 'New York' | map.put("city", "New York"); |
獲取值 | name = person.get('name', 'Unknown') | String name = map.getOrDefault("name", "Unknown"); |
刪除鍵值對 | person.pop('age') | map.remove("age"); |
判斷鍵是否存在 | 'name' in person | map.containsKey("name"); |
獲取所有鍵 | person.keys() | map.keySet(); |
獲取所有值 | person.values() | map.values(); |
獲取鍵值對數量 | len(person) | map.size(); |
3. 關鍵方法對比
zip()
?的核心用法
python
運行
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]# 并行迭代
for name, age in zip(names, ages):print(f"{name} is {age} years old.")# 生成字典
person_dict = dict(zip(names, ages))
print(person_dict) # 輸出:{'Alice': 25, 'Bob': 30, 'Charlie': 35}
dict
?的核心方法
python
運行
# 創建字典
person = {'name': 'Alice', 'age': 25}# get():安全獲取值
print(person.get('name')) # 輸出:Alice
print(person.get('city', 'N/A')) # 輸出:N/A(默認值)# setdefault():獲取值或初始化
person.setdefault('city', 'New York')
print(person) # 輸出:{'name': 'Alice', 'age': 25, 'city': 'New York'}# update():批量更新
person.update({'age': 26, 'job': 'Engineer'})
print(person) # 輸出:{'name': 'Alice', 'age': 26, 'city': 'New York', 'job': 'Engineer'}
Java?Map
?的核心方法
java
import java.util.HashMap;
import java.util.Map;public class MapExample {public static void main(String[] args) {// 創建 MapMap<String, Integer> scores = new HashMap<>();// 添加鍵值對scores.put("Alice", 90);scores.put("Bob", 85);// get():獲取值System.out.println(scores.get("Alice")); // 輸出:90// getOrDefault():安全獲取值System.out.println(scores.getOrDefault("Charlie", 0)); // 輸出:0// putIfAbsent():類似 setdefault()scores.putIfAbsent("Bob", 100); // 不修改已存在的鍵scores.putIfAbsent("Charlie", 75);// putAll():類似 update()Map<String, Integer> newScores = Map.of("David", 88, "Eve", 92);scores.putAll(newScores);System.out.println(scores); // 輸出:{Alice=90, Bob=85, Charlie=75, David=88, Eve=92}}
}
4. 應用場景對比
場景 | Python 方案 | Java 方案 |
---|---|---|
統計詞頻 | word_count = {} for word in words: word_count[word] = word_count.get(word, 0) + 1 | Map<String, Integer> wordCount = new HashMap<>(); for (String word : words) { wordCount.put(word, wordCount.getOrDefault(word, 0) + 1); } |
并行迭代多個列表 | for name, age in zip(names, ages): print(f"{name} is {age}") | for (int i = 0; i < names.size(); i++) { System.out.println(names.get(i) + " is " + ages.get(i)); } |
配置合并 | default_config = {...} user_config = {...} final_config = default_config.copy() final_config.update(user_config) | Map<String, Object> defaultConfig = ... Map<String, Object> userConfig = ... Map<String, Object> finalConfig = new HashMap<>(defaultConfig); finalConfig.putAll(userConfig); |
5. 總結
zip()
?是 Python 的 “配對工具”,用于生成臨時的元組序列,常作為構建?dict
?的中間步驟。dict
?是 Python 的核心數據結構,相當于 Java 的?HashMap
,提供高效的鍵值對存儲。- Java?
Map
?是接口,需通過?HashMap
?等實現類使用,語法更繁瑣但類型更嚴格。
一句話概括:
- Python:
zip()
?→ 生成配對 →?dict
?存儲 - Java:直接用?
Map
?存儲
6 python命令行參數的傳遞方式
在 Python 中,命令行參數的傳遞是腳本與外部環境交互的重要方式。以下是幾種常見的參數傳遞方式及其使用場景:
1. 基礎方式:sys.argv
原理:Python 的?sys
?模塊提供?argv
?列表,包含命令行傳遞的所有參數。
特點:簡單直接,適合小型腳本。
示例代碼
python
運行
# myscript.py
from sys import argvprint("腳本名:", argv[0]) # 第一個元素是腳本本身
print("所有參數:", argv) # 完整參數列表# 獲取特定參數
if len(argv) > 2:print("第一個參數:", argv[1])print("第二個參數:", argv[2])
運行示例
bash
python myscript.py hello world
# 輸出:
# 腳本名: myscript.py
# 所有參數: ['myscript.py', 'hello', 'world']
# 第一個參數: hello
# 第二個參數: world
注意事項
- 索引從 0 開始:
argv[0]
?是腳本名,argv[1]
?是第一個參數。 - 參數類型:所有參數都是字符串類型,需要手動轉換(如?
int(argv[1])
)。 - 邊界檢查:使用前需通過?
len(argv)
?檢查參數數量,避免索引越界。
2. 標準庫:argparse
(推薦)
原理:提供更高級的參數解析功能,支持參數選項(如?-h
、--verbose
)和自動生成幫助信息。
特點:功能強大,適合復雜命令行工具。
示例代碼
python
運行
# mytool.py
import argparse# 創建解析器
parser = argparse.ArgumentParser(description='處理命令行參數')# 添加位置參數(必需參數)
parser.add_argument('input_file', help='輸入文件路徑')
parser.add_argument('output_file', help='輸出文件路徑')# 添加可選參數
parser.add_argument('-v', '--verbose', action='store_true', help='顯示詳細信息')
parser.add_argument('-n', '--number', type=int, default=10, help='處理數量')# 解析參數
args = parser.parse_args()# 使用參數
print(f"輸入文件: {args.input_file}")
print(f"輸出文件: {args.output_file}")
print(f"處理數量: {args.number}")
if args.verbose:print("正在進行詳細處理...")
運行示例
bash
# 基本用法
python mytool.py input.txt output.txt# 使用可選參數
python mytool.py input.txt output.txt -v --number 20# 查看幫助信息
python mytool.py -h
核心功能
- 位置參數:按順序傳遞的必需參數(如?
input_file
)。 - 可選參數:以?
-
?或?--
?開頭的參數(如?-v
、--number
)。 - 參數類型:通過?
type=int
?指定參數類型。 - 默認值:通過?
default=10
?設置默認值。 - 幫助信息:自動生成?
-h
?幫助文檔。
3. 第三方庫:click
原理:基于裝飾器的命令行接口庫,提供更優雅的參數定義方式。
特點:代碼簡潔,支持子命令,適合構建復雜工具。
示例代碼
python
運行
# mycli.py
import click@click.command()
@click.option('--count', default=1, help='重復次數')
@click.option('--name', prompt='你的名字', help='問候對象')
def hello(count, name):"""簡單的問候工具"""for _ in range(count):click.echo(f"Hello, {name}!")if __name__ == '__main__':hello()
運行示例
bash
# 交互式模式
python mycli.py
# 提示:你的名字: [默認值]
# 輸入名字后輸出問候# 命令行指定參數
python mycli.py --count 3 --name Alice
# 輸出三次 "Hello, Alice!"
核心功能
- 裝飾器語法:通過?
@click.command()
?和?@click.option()
?定義命令和參數。 - 交互式提示:自動處理用戶輸入(如?
prompt='你的名字'
)。 - 類型檢查:自動處理參數類型轉換。
- 子命令:支持創建多級命令(如?
git commit
、git push
)。
4. 其他傳遞方式
環境變量
通過?os.environ
?獲取環境變量,適合傳遞敏感信息(如 API Key):
python
運行
import osapi_key = os.environ.get('API_KEY')
if api_key:print(f"使用 API Key: {api_key}")
else:print("未設置 API_KEY 環境變量")
配置文件
讀取外部配置文件(如 JSON、YAML):
python
運行
import jsonwith open('config.json', 'r') as f:config = json.load(f)print(f"配置: {config}")
管道輸入
通過標準輸入(stdin)接收數據:
python
運行
import sys# 讀取所有輸入行
for line in sys.stdin:print(f"處理: {line.strip()}")
使用示例:
bash
echo "hello" | python myscript.py
選擇建議
場景 | 推薦方式 |
---|---|
簡單腳本,少量參數 | sys.argv |
復雜命令行工具 | argparse |
優雅的 CLI 界面 | click |
敏感信息或全局配置 | 環境變量 |
大量配置參數 | 配置文件 |
總結
sys.argv
:適合簡單腳本,直接獲取原始參數列表。argparse
:標準庫,功能全面,適合中型工具。click
:第三方庫,語法簡潔,適合構建專業 CLI 工具。- 環境變量 / 配置文件:適合傳遞非命令行參數(如密鑰、路徑)。
根據需求選擇合適的方式,能讓你的腳本更易用、更健壯。