Funtion
1. Why function?
- 减少重复,容易维护和理解,复用性
- 模块化
Examples
- main()
- print()
- abs()
- math.sqrt()
- …
2. How?
2.1 Create (define)
def drawBar(a,b):
some 语句...def <name>(<formal-parameters>):
<body>def → define
drawBar → identifier
(a,b) → Formal-parameters
’:’ → sytax
some 语句 → Function body
2.2 Use (call)
drawBar(1,4)<name>(<actual parameters>)2.3 Local or Global (变量的作用域)
The scope of variable: namespaces 命名空间(namespace)包括三种:
- Build-in namespace
- Global namespace
- Local namespace 在函数内部定义的变量被称为局部变量 (Local Variable),它们只能在该函数内部访问。在函数外部定义的变量被称为全局变量 (Global Variable),它们可以在程序的任何地方访问,包括函数内部。
x = 10 # 全局变量
def my_function():
y = 5 # 局部变量
print("函数内部:", x) # 可以访问全局变量 x
print("函数内部:", y) # 可以访问局部变量 y
my_function()
print("函数外部:", x) # 可以访问全局变量 x
# print("函数外部:", y) # 报错!无法访问局部变量 y如果在函数内部尝试修改一个全局变量,并且函数内部没有定义同名的局部变量,那么会直接修改全局变量的值。但是如果在函数内部定义了一个同名的局部变量,那么对该变量的修改只会在函数内部生效,不会影响全局变量。
x = 10
def modify_global():
global x # 声明要修改全局变量 x
x = 20
print("函数内部修改后:", x)
modify_global()
print("函数外部修改后:", x)x = 10
def shadow_global():
x = 20 # 定义了一个局部变量 x,屏蔽了全局变量 x
print("函数内部:", x)
shadow_global()
print("函数外部:", x)2.4 参数传递 (Parameter Passing)
位置参数 (Positional Arguments)
按照参数定义的顺序进行传递。
def greet(name, greeting):
print(f"{greeting}, {name}!")
greet("Alice", "Hello") # 位置参数关键字参数 (Keyword Arguments)
通过参数名来传递参数,可以不按照参数定义的顺序。
def greet(name, greeting):
print(f"{greeting}, {name}!")
greet(greeting="Hi", name="Bob") # 关键字参数默认参数 (Default Arguments)
在函数定义时,可以为参数设置默认值。如果调用函数时没有传递该参数,则使用默认值。带有默认值的参数必须在末尾!
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")
greet("Charlie") # 使用默认参数 greeting="Hello"
greet("David", "Good morning") # 覆盖默认参数可变参数 (Variable Arguments)
同样的,可变参数必须在末尾!
*args: 接收任意数量的位置参数,并将它们打包成一个元组 (tuple)。
def print_args(*args):
for arg in args:
print(arg)
print_args(1, 2, 3, "a", "b")**kwargs: 接收任意数量的关键字参数,并将它们打包成一个字典 (dictionary)。
def print_kwargs(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_kwargs(name="Eve", age=30, city="New York")2.5 返回值 (Return Value)
函数可以使用 return 语句返回一个值。如果没有 return 语句,或者 return 语句后面没有表达式,则函数返回 None。
def add(a, b):
return a + b
result = add(3, 5)
print(result)函数可以返回多个值,实际上是返回一个元组。
def calculate(a, b):
sum = a + b
difference = a - b
return sum, difference
result = calculate(10, 4)
print(result) # 输出 (14, 6)
sum_result, diff_result = calculate(10, 4)
print(sum_result) # 输出 14
print(diff_result) # 输出 62.6 不同数据类型是否需要使用return的问题
有些数据类型是不可变的,有些是可变的,要考虑是否需要return
def func(num):
num = num * 2
a = 1000
func(a)
print(a)
# 输出1000def func(nums):
for i in range(len(nums)):
nums[i] = nums[i] * 2
a = [1000,100]
func(a)
print(a)
# 输出[2000,200]还有一个例子:
def squareEach(nums):
'''
对列表中的每个元素求平方
'''
for i in range(len(nums)):
nums[i] = nums[i] ** 2
'''
错误写法:
for num in nums:
num = num ** 2
'''2.7 递归 (Recursion)
递归是指函数调用自身。递归函数必须有一个或多个基本情况 (Base Case),用于停止递归调用,否则会导致无限循环。
def factorial(n):
if n == 0: # 基本情况
return 1
else:
return n * factorial(n - 1) # 递归调用
print(factorial(5))数学公式: 阶乘的定义:
2.8 匿名函数 (Lambda Functions)
匿名函数是一种没有名字的函数,通常用于简单的函数定义。使用 lambda 关键字创建。
square = lambda x: x * x
print(square(5))
print((lambda x: x * x)(5))Lambda函数通常与map(), filter(),sorted(), reduce()等函数一起使用。
numbers = [1, 2, 3, 4, 5]
# 使用 map() 函数将每个元素平方
squared_numbers = list(map(lambda x: x * x, numbers))
print(squared_numbers)
# 使用 filter() 函数过滤出偶数
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)2.9 解包运算符 (*和**)
解包运算符 * 和 ** 在函数调用和定义中都有重要的作用。
函数调用中的解包
*args解包位置参数: 如果有一个列表或元组,并且想将它的元素作为单独的位置参数传递给函数,可以使用*运算符。
def my_function(a, b, c):
print(a, b, c)
my_list = [1, 2, 3]
my_function(*my_list) # 等价于 my_function(1, 2, 3)
my_tuple = (4, 5, 6)
my_function(*my_tuple) # 等价于 my_function(4, 5, 6)**kwargs解包关键字参数: 如果有一个字典,并且想将它的键值对作为单独的关键字参数传递给函数,可以使用**运算符。 字典的键必须是字符串,并且与函数的形式参数名匹配。
def my_function(name, age, city):
print(f"Name: {name}, Age: {age}, City: {city}")
my_dict = {"name": "Alice", "age": 30, "city": "New York"}
my_function(**my_dict) # 等价于 my_function(name="Alice", age=30, city="New York")函数定义中的解包
*args收集位置参数: 允许函数接收任意数量的位置参数,并将它们收集到一个元组中。
def my_function(*args):
for arg in args:
print(arg)
my_function(1, 2, 3, "a", "b") # args 将会是 (1, 2, 3, "a", "b")**kwargs收集关键字参数: 允许函数接收任意数量的关键字参数,并将它们收集到一个字典中。
def my_function(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
my_function(name="Eve", age=30, city="New York") # kwargs 将会是{"name": "Eve", "age": 30, "city": "New York"}示例:结合使用 *args 和 **kwargs
def my_function(a, b, *args, **kwargs):
print(f"a: {a}, b: {b}")
print("args:", args)
print("kwargs:", kwargs)
my_function(1, 2, 3, 4, name="Alice", age=30)
# 输出:
# a: 1, b: 2
# args: (3, 4)
# kwargs: {'name': 'Alice', 'age': 30}
my_list = [5,6]
my_dict = {'city': 'beijing', 'country': 'china'}
my_function(1, 2, *my_list, **my_dict)
# 输出:
# a: 1, b: 2
# args: (5, 6)
# kwargs: {'city': 'beijing', 'country': 'china'}