跳到主要内容

第11章:高级特性

作为 Java 开发者,你已经熟悉了 Java 的高级特性。Python 也有许多强大的高级特性,本章将详细对比两种语言的高级特性。

11.1 装饰器

Java 装饰器

Java 使用设计模式中的装饰器模式,通过实现接口和包装对象来实现。

// 接口
interface Coffee {
double cost();
String description();
}

// 具体实现
class SimpleCoffee implements Coffee {
@Override
public double cost() {
return 5.0;
}

@Override
public String description() {
return "Simple Coffee";
}
}

// 装饰器
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;

public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}

// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}

@Override
public double cost() {
return coffee.cost() + 1.5;
}

@Override
public String description() {
return coffee.description() + " with Milk";
}
}

// 使用
Coffee coffee = new MilkDecorator(new SimpleCoffee());
System.out.println(coffee.description() + " costs " + coffee.cost());

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"))

# 类装饰器
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"))

对比

特性JavaPython
实现方式设计模式(接口 + 包装类)函数闭包 + @ 语法
语法显式包装对象简洁的 @ 语法
灵活性相对复杂更灵活,支持参数
用途主要用于扩展功能广泛用于日志、缓存、权限等

11.2 生成器

Java 生成器

Java 8+ 引入了 Stream API,可以实现类似生成器的功能。

// 使用 Stream 生成序列
IntStream.range(1, 10)
.filter(n -> n % 2 == 0)
.forEach(System.out::println);

// 自定义生成器
class FibonacciGenerator implements Iterator<Long> {
private long a = 0;
private long b = 1;

@Override
public boolean hasNext() {
return true; // 无限序列
}

@Override
public Long next() {
long result = a;
long next = a + b;
a = b;
b = next;
return result;
}
}

// 使用
FibonacciGenerator fib = new FibonacciGenerator();
for (int i = 0; i < 10; i++) {
System.out.println(fib.next());
}

Python 生成器

Python 使用 yield 语句实现生成器。

# 生成器函数
def fibonacci():
"""斐波那契数列生成器"""
a, b = 0, 1
while True:
yield a
a, b = b, a + b

# 使用生成器
fib = fibonacci()
for i in range(10):
print(next(fib))

# 生成器表达式
squares = (x**2 for x in range(10))
for square in squares:
print(square)

# 生成器的优势:节省内存
# 对于大序列,生成器比列表更节省内存
def big_range(n):
for i in range(n):
yield i

# 即使 n 很大,也不会占用太多内存
for i in big_range(1000000):
if i % 100000 == 0:
print(i)

对比

特性JavaPython
实现方式Iterator 接口或 Stream APIyield 语句
语法相对复杂简洁的 yield 语法
内存效率Stream 较高效生成器非常高效
用途主要用于集合处理广泛用于惰性计算

11.3 上下文管理器

Java 上下文管理器

Java 7+ 引入了 try-with-resources 语句。

// 使用 try-with-resources
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}

// 自定义 AutoCloseable 类
class Resource implements AutoCloseable {
public Resource() {
System.out.println("Resource created");
}

public void use() {
System.out.println("Resource used");
}

@Override
public void close() {
System.out.println("Resource closed");
}
}

// 使用
try (Resource resource = new Resource()) {
resource.use();
}

Python 上下文管理器

Python 使用 with 语句和 __enter__/__exit__ 方法实现上下文管理器。

# 使用内置上下文管理器
with open("example.txt", "r") as file:
content = file.read()
print(content)
# 文件自动关闭

# 自定义上下文管理器
class Timer:
def __enter__(self):
import time
self.start = time.time()
return self

def __exit__(self, exc_type, exc_val, exc_tb):
import time
self.end = time.time()
print(f"Elapsed time: {self.end - self.start:.2f} seconds")

with Timer():
# 执行一些操作
import time
time.sleep(1)

# 使用 contextmanager 装饰器
from contextlib import contextmanager

@contextmanager
def temporary_file():
"""临时文件上下文管理器"""
import tempfile
temp = tempfile.NamedTemporaryFile(mode='w', delete=False)
try:
yield temp
finally:
import os
os.unlink(temp.name)

with temporary_file() as f:
f.write("Temporary data")
print(f"Temp file: {f.name}")

对比

特性JavaPython
实现方式AutoCloseable 接口__enter__/__exit__ 方法
语法try-with-resourceswith 语句
灵活性相对有限更灵活,支持装饰器实现
用途主要用于资源管理广泛用于资源管理、事务等

11.4 类型提示

Java 类型系统

Java 是静态类型语言,编译时进行类型检查。

// 显式类型声明
String name = "Alice";
int age = 25;
List<String> names = new ArrayList<>();

// 方法参数和返回类型
public String greet(String name) {
return "Hello, " + name;
}

// 泛型
public class Box<T> {
private T value;

public void setValue(T value) {
this.value = value;
}

public T getValue() {
return value;
}
}

Python 类型提示

Python 3.5+ 引入了类型提示,是可选的。

# 类型提示
name: str = "Alice"
age: int = 25
names: list[str] = ["Alice", "Bob", "Charlie"]

# 函数类型提示
def greet(name: str) -> str:
return f"Hello, {name}"

# 泛型类型提示
from typing import List, Dict, Optional, Union, TypeVar, Generic

T = TypeVar('T')

class Box(Generic[T]):
def __init__(self, value: T):
self.value: T = value

def get_value(self) -> T:
return self.value

# 使用
box: Box[str] = Box("Hello")
print(box.get_value())

# 可选类型
def find_user(user_id: int) -> Optional[str]:
users = {1: "Alice", 2: "Bob"}
return users.get(user_id)

# 联合类型
def process_value(value: Union[int, str]) -> str:
return str(value)

对比

特性JavaPython
类型系统静态类型,编译时检查动态类型,类型提示是可选的
类型声明必须可选
泛型支持支持(通过 typing 模块)
类型检查编译时强制运行时可选(使用 mypy)
灵活性相对严格更灵活,类型提示不影响运行

11.5 异步编程

Java 异步编程

Java 使用 CompletableFutureExecutorService 实现异步编程。

// 使用 CompletableFuture
CompletableFuture.supplyAsync(() -> {
// 异步任务
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello";
}).thenAccept(result -> {
System.out.println("Result: " + result);
});

// 使用 ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<String> future = executor.submit(() -> {
// 异步任务
Thread.sleep(1000);
return "Hello";
});

// 获取结果
try {
String result = future.get();
System.out.println("Result: " + result);
} catch (Exception e) {
e.printStackTrace();
}

executor.shutdown();

Python 异步编程

Python 3.5+ 引入了 asyncawait 关键字。

import asyncio

# 异步函数
async def greet(name):
print(f"Hello, {name}!")
await asyncio.sleep(1) # 模拟耗时操作
print(f"Goodbye, {name}!")
return f"Greeted {name}"

# 异步主函数
async def main():
# 顺序执行
result1 = await greet("Alice")
result2 = await greet("Bob")
print(f"Results: {result1}, {result2}")

# 并发执行
tasks = [greet("Charlie"), greet("David")]
results = await asyncio.gather(*tasks)
print(f"Concurrent results: {results}")

# 运行异步代码
asyncio.run(main())

# 异步IO
import aiohttp

async def fetch_url(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()

async def main():
urls = ["https://api.github.com", "https://api.example.com"]
tasks = [fetch_url(url) for url in urls]
responses = await asyncio.gather(*tasks)
for url, response in zip(urls, responses):
print(f"{url} status: {len(response)} bytes")

asyncio.run(main())

对比

特性JavaPython
实现方式CompletableFuture, ExecutorServiceasync/await 关键字
语法相对复杂简洁的 async/await 语法
并发模型多线程单线程事件循环(协程)
适用场景CPU 密集型任务IO 密集型任务
库支持CompletableFutureasyncio, aiohttp

11.6 元编程

Java 元编程

Java 使用反射和注解实现元编程。

// 反射
Class<?> clazz = String.class;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}

// 注解
@interface MyAnnotation {
String value();
}

@MyAnnotation("test")
class MyClass {
@MyAnnotation("method")
public void myMethod() {
}
}

// 读取注解
MyAnnotation classAnnotation = MyClass.class.getAnnotation(MyAnnotation.class);
System.out.println(classAnnotation.value()); // test

Method method = MyClass.class.getMethod("myMethod");
MyAnnotation methodAnnotation = method.getAnnotation(MyAnnotation.class);
System.out.println(methodAnnotation.value()); // method

Python 元编程

Python 使用装饰器、元类和反射实现元编程。

# 反射
def greet(name):
return f"Hello, {name}!"

print(greet.__name__) # greet
print(greet.__doc__) # None
print(dir(greet)) # 查看所有属性和方法

# 装饰器(见前面的例子)

# 元类
class Meta(type):
def __new__(mcs, name, bases, dct):
# 在类创建时修改
dct['class_variable'] = 'value'
return super().__new__(mcs, name, bases, dct)

class MyClass(metaclass=Meta):
pass

print(MyClass.class_variable) # value

# 动态创建类
MyDynamicClass = type('MyDynamicClass', (object,), {'x': 1, 'y': 2})
instance = MyDynamicClass()
print(instance.x, instance.y) # 1 2

# 猴子补丁
class Person:
def greet(self):
return "Hello"

# 动态修改方法
Person.greet = lambda self: "Hi"

p = Person()
print(p.greet()) # Hi

对比

特性JavaPython
元编程方式反射、注解装饰器、元类、反射
灵活性相对有限非常灵活
语法相对复杂简洁直观
运行时修改有限强大的运行时修改能力
用途框架开发、依赖注入框架开发、元数据处理

11.7 练习

  1. 装饰器练习:创建一个装饰器,缓存函数的返回值
  2. 生成器练习:创建一个生成器,生成质数序列
  3. 上下文管理器练习:创建一个上下文管理器,管理数据库连接
  4. 类型提示练习:为一个函数添加完整的类型提示
  5. 异步编程练习:使用 asyncio 并发获取多个 URL 的内容
  6. 元编程练习:使用元类创建一个单例类

11.8 小结

  • Python 的装饰器比 Java 的装饰器模式更简洁、更强大
  • Python 的生成器使用 yield 语句,比 Java 的 Iterator 更直观
  • Python 的上下文管理器使用 with 语句,比 Java 的 try-with-resources 更灵活
  • Python 的类型提示是可选的,比 Java 的静态类型系统更灵活
  • Python 的异步编程使用 async/await,比 Java 的 CompletableFuture 更简洁
  • Python 的元编程能力比 Java 更强大,支持运行时修改类和函数

通过本章的学习,你已经了解了 Java 和 Python 在高级特性上的主要区别。接下来,我们将学习 Python 的标准库与生态。