跳到主要内容

第5章:函数与方法

作为 Java 开发者,你已经熟悉了 Java 的方法定义和调用。Python 的函数与 Java 的方法有很多相似之处,但也有一些重要的区别。本章将详细对比两种语言的函数与方法。

5.1 函数定义

Java 方法定义

// 实例方法
public returnType methodName(parameterType parameterName) {
// 方法体
return returnValue;
}

// 静态方法
public static returnType methodName(parameterType parameterName) {
// 方法体
return returnValue;
}

Python 函数定义

def function_name(parameter_name):
"""函数文档字符串"""
# 函数体
return return_value

对比

特性JavaPython
定义关键字public, private, protected, staticdef
参数类型必须声明类型无需声明类型(动态类型)
返回类型必须声明类型无需声明类型
访问修饰符有(public, private, protected)无(通过命名约定)
方法体大括号包围缩进
文档Javadoc文档字符串(docstring)

Python 函数示例

# 基本函数
def greet(name):
"""问候函数"""
return f"Hello, {name}!"

print(greet("Alice")) # Hello, Alice!

# 带默认参数的函数
def greet(name, greeting="Hello"):
"""带默认参数的问候函数"""
return f"{greeting}, {name}!"

print(greet("Bob")) # Hello, Bob!
print(greet("Charlie", "Hi")) # Hi, Charlie!

# 带可变参数的函数
def sum_numbers(*args):
"""计算任意数量数字的和"""
return sum(args)

print(sum_numbers(1, 2, 3, 4, 5)) # 15

# 带关键字参数的函数
def print_person(**kwargs):
"""打印个人信息"""
for key, value in kwargs.items():
print(f"{key}: {value}")

print_person(name="Alice", age=25, city="New York")

5.2 参数传递

Java 参数传递

  • 基本类型:值传递
  • 引用类型:引用传递

Python 参数传递

  • 所有参数:引用传递
  • 不可变类型(int, str, tuple):类似值传递
  • 可变类型(list, dict, set):类似引用传递

对比示例

操作JavaPython
传递基本类型值传递引用传递(但不可变)
传递引用类型引用传递引用传递
修改参数基本类型不影响原值不可变类型不影响原值,可变类型影响原值

Python 参数传递示例

# 不可变类型参数
def modify_integer(x):
x = x + 1
print(f"Inside function: x = {x}")

a = 5
modify_integer(a)
print(f"Outside function: a = {a}") # a 仍然是 5

# 可变类型参数
def modify_list(lst):
lst.append(4)
print(f"Inside function: lst = {lst}")

b = [1, 2, 3]
modify_list(b)
print(f"Outside function: b = {b}") # b 变成了 [1, 2, 3, 4]

# 关键字参数
def person_info(name, age):
return f"Name: {name}, Age: {age}"

# 位置参数
print(person_info("Alice", 25)) # Name: Alice, Age: 25

# 关键字参数
print(person_info(name="Bob", age=30)) # Name: Bob, Age: 30
print(person_info(age=35, name="Charlie")) # Name: Charlie, Age: 35

# 混合使用
print(person_info("David", age=40)) # Name: David, Age: 40

5.3 函数返回值

Java 返回值

  • 必须声明返回类型
  • 可以返回基本类型或引用类型
  • void 表示无返回值

Python 返回值

  • 无需声明返回类型
  • 可以返回任意类型
  • 未显式返回时,默认返回 None
  • 可以返回多个值(作为元组)

对比示例

操作JavaPython
无返回值void 方法函数默认返回 None
单个返回值直接返回直接返回
多个返回值返回对象或数组直接返回多个值(元组)

Python 返回值示例

# 无返回值
def print_hello():
print("Hello")

result = print_hello()
print(result) # None

# 单个返回值
def add(a, b):
return a + b

result = add(3, 5)
print(result) # 8

# 多个返回值
def calculate(a, b):
return a + b, a - b, a * b, a / b

add_result, sub_result, mul_result, div_result = calculate(10, 5)
print(add_result, sub_result, mul_result, div_result) # 15 5 50 2.0

# 返回值作为元组
result = calculate(8, 4)
print(result) # (12, 4, 32, 2.0)
print(type(result)) # <class 'tuple'>

5.4 Lambda 表达式

Java Lambda 表达式

// Java 8+
Runnable runnable = () -> System.out.println("Hello");

Function<Integer, Integer> square = x -> x * x;

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.sort((a, b) -> a.compareTo(b));

Python Lambda 表达式

# Python lambda
greet = lambda name: f"Hello, {name}!"
print(greet("Alice")) # Hello, Alice!

square = lambda x: x * x
print(square(5)) # 25

# 作为函数参数
numbers = [3, 1, 4, 1, 5, 9]
numbers.sort(key=lambda x: x)
print(numbers) # [1, 1, 3, 4, 5, 9]

# 与内置函数配合
numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled) # [2, 4, 6, 8, 10]

filtered = list(filter(lambda x: x % 2 == 0, numbers))
print(filtered) # [2, 4]

对比

特性JavaPython
语法(parameters) -> expressionlambda parameters: expression
用途函数式接口实现匿名函数,常用于函数参数
复杂度可以包含代码块只能是表达式
类型推断编译器推断动态类型

5.5 函数作为对象

Java 函数作为对象

  • Java 8+ 引入了函数式接口
  • 使用 Function, Consumer, Supplier
  • 方法引用

Python 函数作为对象

  • 函数是一等公民
  • 可以赋值给变量
  • 可以作为参数传递
  • 可以作为返回值
  • 可以存储在数据结构中

对比示例

操作JavaPython
函数赋值Function<Integer, Integer> func = x -> x * x;func = lambda x: x * x
函数作为参数stream.map(func)map(func, iterable)
函数作为返回值复杂简单,直接返回函数
函数存储复杂简单,存储在列表、字典等

Python 函数作为对象示例

# 函数赋值给变量
def add(a, b):
return a + b

addition = add
print(addition(3, 5)) # 8

# 函数作为参数
def apply_function(func, x, y):
return func(x, y)

result = apply_function(add, 10, 20)
print(result) # 30

# 函数作为返回值
def create_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier

double = create_multiplier(2)
triple = create_multiplier(3)

print(double(5)) # 10
print(triple(5)) # 15

# 函数存储在列表中
functions = [add, lambda x, y: x - y, lambda x, y: x * y]
for func in functions:
print(func(10, 5)) # 15, 5, 50

# 函数存储在字典中
operations = {
"add": add,
"subtract": lambda x, y: x - y,
"multiply": lambda x, y: x * y,
"divide": lambda x, y: x / y
}

print(operations["add"](10, 5)) # 15
print(operations["subtract"](10, 5)) # 5

5.6 装饰器

Java 装饰器

  • 使用设计模式中的装饰器模式
  • 实现接口,包装原始对象

Python 装饰器

  • 使用 @ 语法
  • 函数装饰器
  • 类装饰器

Python 装饰器示例

# 简单装饰器
def log_function(func):
"""日志装饰器"""
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned {result}")
return result
return wrapper

@log_function
def add(a, b):
return a + b

print(add(3, 5)) # 会打印日志

# 带参数的装饰器
def repeat(n):
"""重复执行函数n次的装饰器"""
def decorator(func):
def wrapper(*args, **kwargs):
results = []
for i in range(n):
results.append(func(*args, **kwargs))
return results
return wrapper
return decorator

@repeat(3)
def greet(name):
return f"Hello, {name}!"

print(greet("Alice")) # 执行3次

# 类装饰器
class CountCalls:
"""统计函数调用次数的装饰器"""
def __init__(self, func):
self.func = func
self.calls = 0

def __call__(self, *args, **kwargs):
self.calls += 1
print(f"Call {self.calls} of {self.func.__name__}")
return self.func(*args, **kwargs)

@CountCalls
def say_hello(name):
return f"Hello, {name}!"

print(say_hello("Bob"))
print(say_hello("Charlie"))

5.7 作用域

Java 作用域

  • 类作用域
  • 方法作用域
  • 块作用域
  • 局部变量

Python 作用域

  • 全局作用域
  • 局部作用域
  • 嵌套作用域
  • 内置作用域

对比

作用域JavaPython
全局变量类变量模块级变量
局部变量方法内变量函数内变量
嵌套作用域支持(闭包)
作用域访问严格更灵活(nonlocal, global)

Python 作用域示例

# 全局变量
global_var = "global"

def outer():
# 闭包变量
outer_var = "outer"

def inner():
# 局部变量
inner_var = "inner"
# 访问全局变量
print(global_var)
# 访问闭包变量
print(outer_var)
# 访问局部变量
print(inner_var)

inner()

outer()

# 修改全局变量
def modify_global():
global global_var
global_var = "modified global"

modify_global()
print(global_var) # modified global

# 修改闭包变量
def outer():
count = 0

def inner():
nonlocal count
count += 1
return count

return inner

counter = outer()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3

5.8 递归函数

Java 递归

public int factorial(int n) {
if (n == 0) {
return 1;
}
return n * factorial(n - 1);
}

Python 递归

def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)

print(factorial(5)) # 120

对比

特性JavaPython
递归深度较深较浅(默认递归深度限制)
尾递归优化部分 JVM 支持不支持
语法相同相同

Python 递归示例

# 斐波那契数列
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10)) # 55

# 递归深度限制
import sys
print(sys.getrecursionlimit()) # 默认 1000

# 阶乘(递归)
def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)

print(factorial(100)) # 可以计算大的阶乘

5.9 内置函数

Java 内置方法

  • System.out.println()
  • Math.abs()
  • Arrays.sort()
  • 等等

Python 内置函数

  • print()
  • len()
  • range()
  • sum()
  • max()
  • min()
  • sorted()
  • type()
  • isinstance()
  • 等等

常用内置函数对比

功能JavaPython
打印System.out.println()print()
长度array.lengthcollection.size()len()
最大值Math.max()max()
最小值Math.min()min()
排序Arrays.sort()Collections.sort()sorted()
类型检查instanceofgetClass()type()isinstance()
输入Scannerinput()

5.10 练习

  1. 函数定义练习:定义一个函数,计算两个数的最大值
  2. 参数练习:定义一个函数,接受任意数量的参数,返回它们的平均值
  3. Lambda 练习:使用 lambda 函数和 filter(),过滤出列表中的所有奇数
  4. 装饰器练习:创建一个装饰器,计算函数执行时间
  5. 递归练习:定义一个递归函数,计算阶乘
  6. 函数作为对象练习:创建一个函数字典,实现简单的计算器

5.11 小结

  • Python 的函数定义比 Java 更简洁,不需要声明参数和返回类型
  • Python 支持默认参数、可变参数和关键字参数
  • Python 支持函数作为一等公民,可以赋值、传递和返回
  • Python 的 lambda 表达式比 Java 更简洁,常用于函数参数
  • Python 支持装饰器,可以修改函数行为
  • Python 的作用域规则更灵活,支持闭包
  • Python 的内置函数比 Java 更丰富,使用更方便
  • Python 的递归深度有限制,对于深层递归可能需要迭代实现

通过本章的学习,你已经了解了 Java 和 Python 在函数与方法上的主要区别。接下来,我们将学习 Python 的面向对象编程。