文章目录
函数是 Python 编程中的基本构建块之一,它允许你将代码组织成可重用的模块。
基本函数定义
def greet(name):
"""这是一个简单的问候函数"""
print(f"Hello, {name}!")
greet("Alice") # 输出: Hello, Alice!
函数组成部分
1、def 关键字 - 用于定义函数
2、函数名 - 遵循变量命名规则
3、参数列表 - 在括号中定义
4、冒号 : - 表示函数头结束
5、函数体 - 缩进的代码块
参数类型
1. 位置参数
位置参数又称为必备参数:
def add(a, b):
return a + b
print(add(2, 3)) # 输出: 5
2. 默认参数
默认参数又称为可选参数:
在函数定义时,赋予默认值,在函数调用时如果不传入则使用默认值,如果传入则使用插入值。
注意:默认参数必须在位置参数的右边,否则报错。
def power(base, exponent=2):
return base ** exponent
print(power(3)) # 输出: 9 (使用默认 exponent=2)
print(power(3, 3)) # 输出: 27
3. 关键字参数
关键字参数相当于是默认参数和位置参数的显式传参。
"""
def func(a, b):
print(a)
print(b)
func(b = 2, a = 1)
"""
def
describe_person(name, age, city):
print(f"{name} is {age} years old and lives in {city}")
describe_person(age=25, city="New York", name="Bob")
4. 可变参数 (*args)
用于接收不确定数量的位置参数(非关键字参数)。
参数会被打包成一个元组(tuple)。
def sum_all(*numbers):
print(type(numbers)) # 输出<class 'tuple'>
return sum(numbers)
print(sum_all(1, 2, 3)) # 输出: 6
可以与其他参数混合使用,但 *args 必须在普通参数之后
def greet(name, *messages):
print(f"Hello, {name}!")
for msg in messages:
print(msg)
greet("Alice", "How are you?", "Welcome!")
# 输出:
# Hello, Alice!
# How are you?
# Welcome!
如果同时有默认参数,*args 必须在默认参数之前。
def foo(a, b=2, *args):
pass
5. 关键字可变参数 (**kwargs)
用于接收不确定数量的关键字参数(如 key=value 形式)。
参数会被打包成一个字典(dict)。
代码示例:
def print_info(**info):
print(type(info))
for key, value in info.items():
print(f"{key}: {value}")
print_info(name="Alice", age=30, city="London")
输出示例:
<class 'dict'>
name: Alice
age: 30
city: London
必须放在所有参数的最后:
def foo(a, b=2, *args, **kwargs):
pass
常用于配置选项或扩展函数行为:
def connect_db(**kwargs):
host = kwargs.get("host", "localhost")
port = kwargs.get("port", 3306)
print(f"Connecting to {host}:{port}")
connect_db(host="192.168.1.1", port=5432) # 自定义配置
connect_db() # 使用默认值
*args 和 **kwargs 的组合使用
典型场景:
需要同时接受任意数量的位置参数和关键字参数。
常见于装饰器、继承或包装函数。
def wrapper(*args, **kwargs):
print("Positional arguments:", args)
print("Keyword arguments:", kwargs)
# 通常在这里调用另一个函数,如:func(*args, **kwargs)
wrapper(1, 2, name="Alice", age=25)
# 输出:
# Positional arguments: (1, 2)
# Keyword arguments: {'name': 'Alice', 'age': 25}
解包参数(Unpacking Arguments)
- 解包可迭代对象(如列表、元组)
* def foo(a, b, c):
print(a, b, c)
args = [1, 2, 3]
foo(*args) # 等价于 foo(1, 2, 3)
** 解包字典(键名需匹配参数名)
def bar(name, age):
print(f"{name} is {age} years old")
kwargs = {"name": "Alice", "age": 25}
bar(**kwargs) # 等价于 bar(name="Alice", age=25)
强制关键字参数
强制关键字参数(Keyword-only Arguments) 是指某些参数在函数调用时 必须 以 参数名=值 的形式显式传递,不能作为位置参数传递。这是 Python 3 引入的特性,用于提高代码的可读性和安全性。
参数列表中用 * 作为分隔符,* 之后的参数就是强制关键字参数
def func(a, *, b, c):
pass
1、a 可以是位置参数或关键字参数
2、b 和 c 必须 以关键字形式传递
错误调用方式:
func(b=2, 1, c=3)
func(1, 2, 3) # TypeError: func() takes 1 positional argument but 3 were given
正确调用方式:
func(1, b=2, c=3) # 正确
func(a=1, b=2, c=3) # 也正确
应用场景
1、避免默认参数的位置限制
默认参数通常必须放在位置参数之后,但 * 可以灵活控制:
def connect(*, port=8080, host, timeout=10):
print(f"Connecting to {host}:{port} (timeout={timeout})")
connect(host=9090) # 只修改 host,其他用默认值
2、与 *args 和 **kwargs 结合
注意这里的verbose是强制关键字参数,并且参数verbose不可以写在 **kwargs后面
def process_data(*args, verbose=False, **kwargs):
if verbose:
print("Processing with:", args, kwargs)
process_data(1, 2, 3, verbose=True, mode="fast")
# args=(1, 2, 3), kwargs={"mode": "fast"}, verbose=True
参数常见问题
Q1:*args 和 **kwargs 必须命名为 args 和 kwargs 吗?
不是。* 和 ** 是语法关键部分,变量名可以自定义(如 *numbers、**options),但约定俗成使用 args 和 kwargs。
Q2:可变参数能否与普通参数混用?
可以,但顺序必须为:
1、普通位置参数(如 a, b)
2、默认参数(如 c=1)
3、可变位置参数(*args)
4、可变关键字参数(**kwargs)
Q3:如何强制某些参数必须用关键字传递?
在参数列表中插入 *:
def foo(a, *, b, c): # b 和 c 必须用关键字传递
pass
foo(1, b=2, c=3) # 正确
foo(1, 2, 3) # 报错:b 和 c 需显式指定
Q4:关键字参数必须放在位置参数之后吗?
在函数调用时,关键字参数必须在位置参数之后:
def foo(a, b, c):
pass
foo(1, c=3, b=2) # 正确
foo(a=1, 2, 3) # 报错:SyntaxError
返回值
函数可以使用 return 语句返回一个值。如果没有 return 语句,函数返回 None。
def is_even(num):
return num % 2 == 0
print(is_even(4)) # 输出: True
def is_none():
pass
print(is_none()) # 输出:None
注意点
在 Python 中,没有像 C/C++ 或 Java 那样的显式函数声明(即在调用前需要先声明函数原型)。