Skip to content

Python 进阶面试题

1. 装饰器

问题:什么是装饰器?如何实现装饰器?

答案

python
# 1. 基本装饰器
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before function call")
        result = func(*args, **kwargs)
        print("After function call")
        return result
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

# 等价于 say_hello = my_decorator(say_hello)

# 2. 带参数的装饰器
def repeat(num):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

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

# 3. 类装饰器
class CountCalls:
    def __init__(self, func):
        self.func = func
        self.count = 0
    
    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f"Call {self.count} of {self.func.__name__}")
        return self.func(*args, **kwargs)

@CountCalls
def say_hi():
    print("Hi!")

# 4. 常用装饰器
import functools
import time

# 保留原函数信息
def my_decorator(func):
    @functools.wraps(func)  # 保留 __name__, __doc__ 等
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

# 计时装饰器
def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        elapsed = time.time() - start
        print(f"{func.__name__} took {elapsed:.4f} seconds")
        return result
    return wrapper

# 缓存装饰器(LRU Cache)
@functools.lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 5. 实际应用示例
# 权限检查
def require_login(func):
    @functools.wraps(func)
    def wrapper(user, *args, **kwargs):
        if not user.is_authenticated:
            raise PermissionError("User not logged in")
        return func(user, *args, **kwargs)
    return wrapper

# 重试机制
def retry(max_attempts=3, delay=1):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise
                    time.sleep(delay)
            return None
        return wrapper
    return decorator

# 6. 多个装饰器
@timer
@retry(max_attempts=3)
def fetch_data():
    # 可能失败的操作
    pass

# 执行顺序:从下往上
# fetch_data = timer(retry(fetch_data))

2. 生成器和迭代器

问题:生成器和迭代器有什么区别?如何使用?

答案

python
# 1. 迭代器协议
class CountDown:
    def __init__(self, start):
        self.start = start
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.start <= 0:
            raise StopIteration
        self.start -= 1
        return self.start + 1

# 使用
count = CountDown(5)
for num in count:
    print(num)  # 5, 4, 3, 2, 1

# 2. 生成器函数
def countdown(n):
    while n > 0:
        yield n
        n -= 1

# 使用
for num in countdown(5):
    print(num)

# 3. 生成器表达式
gen = (x**2 for x in range(10))
print(sum(gen))  # 285

# 4. yield from(Python 3.3+)
def flatten(nested):
    for item in nested:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item

nested = [1, [2, [3, 4]], 5]
print(list(flatten(nested)))  # [1, 2, 3, 4, 5]

# 5. 生成器状态
def gen():
    print("Start")
    yield 1
    print("Continue")
    yield 2
    print("End")

g = gen()
print(next(g))  # Start, 1
print(next(g))  # Continue, 2
# print(next(g))  # End, StopIteration

# 6. send() 方法
def accumulator():
    total = 0
    while True:
        value = yield total
        if value is None:
            break
        total += value

acc = accumulator()
next(acc)  # 预激生成器
print(acc.send(10))   # 10
print(acc.send(20))   # 30
print(acc.send(30))   # 60
acc.close()

# 7. 实际应用:读取大文件
def read_large_file(file_path):
    """惰性读取大文件"""
    with open(file_path, 'r') as f:
        for line in f:
            yield line.strip()

# 处理大文件,内存友好
for line in read_large_file('huge_file.txt'):
    process_line(line)

# 8. 无限序列
def fibonacci_generator():
    """无限斐波那契数列"""
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci_generator()
for _ in range(10):
    print(next(fib))

3. 上下文管理器

问题:什么是上下文管理器?如何实现?

答案

python
# 1. 类实现上下文管理器
class FileManager:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.file = None
    
    def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.file:
            self.file.close()
        # 返回 True 表示异常已处理,不传播
        return False

# 使用
with FileManager('test.txt', 'w') as f:
    f.write('Hello')

# 2. contextmanager 装饰器
from contextlib import contextmanager

@contextmanager
def managed_file(filename, mode):
    f = open(filename, mode)
    try:
        yield f
    finally:
        f.close()

# 使用
with managed_file('test.txt', 'w') as f:
    f.write('World')

# 3. 实际应用:数据库连接
@contextmanager
def database_connection(config):
    conn = create_connection(config)
    try:
        yield conn
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()

# 4. 临时修改环境
import os
from contextlib import contextmanager

@contextmanager
def temporary_env_var(key, value):
    old_value = os.environ.get(key)
    os.environ[key] = value
    try:
        yield
    finally:
        if old_value is None:
            del os.environ[key]
        else:
            os.environ[key] = old_value

# 使用
with temporary_env_var('DEBUG', '1'):
    # 在这个上下文中 DEBUG=1
    run_tests()

# 5. 上下文管理器组合
from contextlib import ExitStack

with ExitStack() as stack:
    files = [
        stack.enter_context(open(fname))
        for fname in ['file1.txt', 'file2.txt']
    ]
    # 所有文件会自动关闭

# 6. suppress 忽略特定异常
from contextlib import suppress

with suppress(FileNotFoundError):
    os.remove('maybe_not_exists.txt')

# 7. redirect_stdout/stderr
from contextlib import redirect_stdout
import io

f = io.StringIO()
with redirect_stdout(f):
    print('Hello')
output = f.getvalue()

4. 元类

问题:什么是元类?如何使用元类?

答案

python
# 1. 元类基础
# type 是 Python 的默认元类
class MyClass:
    pass

# 等价于
MyClass = type('MyClass', (), {})

# 2. 自定义元类
class Meta(type):
    """自定义元类"""
    def __new__(mcs, name, bases, namespace):
        # 创建类之前
        print(f"Creating class: {name}")
        
        # 修改命名空间
        namespace['created_by'] = 'Meta'
        
        # 创建类
        cls = super().__new__(mcs, name, bases, namespace)
        return cls
    
    def __init__(cls, name, bases, namespace):
        # 初始化类
        super().__init__(name, bases, namespace)
        print(f"Initializing class: {name}")

class MyClass(metaclass=Meta):
    x = 1

print(MyClass.created_by)  # Meta

# 3. ORM 风格示例
class Field:
    def __init__(self, name, field_type):
        self.name = name
        self.field_type = field_type

class ModelMeta(type):
    def __new__(mcs, name, bases, namespace):
        if name == 'Model':
            return super().__new__(mcs, name, bases, namespace)
        
        # 收集字段
        fields = {}
        for key, value in list(namespace.items()):
            if isinstance(value, Field):
                fields[key] = value
                del namespace[key]
        
        namespace['_fields'] = fields
        return super().__new__(mcs, name, bases, namespace)

class Model(metaclass=ModelMeta):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
    
    def save(self):
        print(f"Saving {self.__class__.__name__}")
        for name, field in self._fields.items():
            value = getattr(self, name, None)
            print(f"  {name}: {value}")

class User(Model):
    name = Field('name', 'string')
    age = Field('age', 'integer')

# 使用
user = User(name='Alice', age=25)
user.save()

# 4. 单例模式(使用元类)
class SingletonMeta(type):
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class Database(metaclass=SingletonMeta):
    def __init__(self):
        print("Initializing database")

db1 = Database()
db2 = Database()
print(db1 is db2)  # True

# 5. 抽象基类(ABC)
from abc import ABCMeta, abstractmethod

class Base(metaclass=ABCMeta):
    @abstractmethod
    def process(self):
        pass

class Concrete(Base):
    def process(self):
        print("Processing")

# base = Base()  # 错误!不能实例化抽象类
concrete = Concrete()  # 正确

5. 多线程与多进程

问题:Python 中的 GIL 是什么?如何实现多线程和多进程?

答案

python
# 1. GIL(全局解释器锁)
# - CPython 中,同一时刻只有一个线程执行 Python 字节码
# - 多线程适合 I/O 密集型任务
# - 多进程适合 CPU 密集型任务

# 2. threading 模块
import threading
import time

def worker(num):
    print(f"Worker {num} started")
    time.sleep(1)
    print(f"Worker {num} finished")

# 创建线程
threads = []
for i in range(5):
    t = threading.Thread(target=worker, args=(i,))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

# 3. 线程池
from concurrent.futures import ThreadPoolExecutor, as_completed

def fetch_url(url):
    import requests
    return requests.get(url).status_code

urls = ['http://example.com'] * 10

with ThreadPoolExecutor(max_workers=5) as executor:
    # 提交任务
    futures = [executor.submit(fetch_url, url) for url in urls]
    
    # 获取结果
    for future in as_completed(futures):
        print(future.result())

# 4. multiprocessing 模块
import multiprocessing

def cpu_intensive(n):
    """CPU 密集型任务"""
    count = 0
    for i in range(n):
        count += i ** 2
    return count

# 创建进程池
with multiprocessing.Pool(processes=4) as pool:
    results = pool.map(cpu_intensive, [1000000] * 4)
    print(results)

# 5. 进程间通信
from multiprocessing import Process, Queue, Pipe

# 使用 Queue
def producer(queue):
    for i in range(5):
        queue.put(i)
        time.sleep(0.1)

def consumer(queue):
    while True:
        item = queue.get()
        if item is None:
            break
        print(f"Got: {item}")

queue = Queue()
p = Process(target=producer, args=(queue,))
c = Process(target=consumer, args=(queue,))

p.start()
c.start()
p.join()
queue.put(None)
c.join()

# 6. 共享内存
from multiprocessing import Value, Array

def increment(n, arr):
    n.value += 1
    for i in range(len(arr)):
        arr[i] += 1

num = Value('i', 0)
arr = Array('i', range(10))

processes = [Process(target=increment, args=(num, arr)) for _ in range(10)]
for p in processes:
    p.start()
for p in processes:
    p.join()

print(num.value)  # 10
print(arr[:])     # [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

# 7. 锁和同步
from threading import Lock, Semaphore, Event

# 互斥锁
counter = 0
counter_lock = Lock()

def increment():
    global counter
    for _ in range(100000):
        with counter_lock:
            counter += 1

# 信号量
semaphore = Semaphore(3)  # 最多3个线程同时访问

def limited_resource():
    with semaphore:
        print("Accessing limited resource")
        time.sleep(1)

# 事件
event = Event()

def wait_for_event():
    print("Waiting...")
    event.wait()
    print("Event received!")

def trigger_event():
    time.sleep(2)
    event.set()

# 8. asyncio(异步 IO)
import asyncio

async def async_task(name, delay):
    print(f"Task {name} starting")
    await asyncio.sleep(delay)
    print(f"Task {name} finished")
    return name

async def main():
    # 并发执行
    tasks = [
        async_task("A", 1),
        async_task("B", 2),
        async_task("C", 1)
    ]
    results = await asyncio.gather(*tasks)
    print(results)

# 运行
asyncio.run(main())

# 9. 异步 HTTP 请求
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def fetch_all():
    urls = ['http://example.com'] * 10
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        return results

6. 内存管理与垃圾回收

问题:Python 的内存管理和垃圾回收机制是怎样的?

答案

python
# 1. 引用计数
import sys

a = []
print(sys.getrefcount(a))  # 2(a + getrefcount 参数)

b = a
print(sys.getrefcount(a))  # 3

del b
print(sys.getrefcount(a))  # 2

# 2. 垃圾回收器(处理循环引用)
import gc

# 查看垃圾回收统计
gc.get_stats()

# 手动触发垃圾回收
gc.collect()

# 禁用/启用垃圾回收
gc.disable()
gc.enable()

# 3. 循环引用示例
class Node:
    def __init__(self, name):
        self.name = name
        self.parent = None
        self.children = []
    
    def add_child(self, child):
        self.children.append(child)
        child.parent = self

# 创建循环引用
parent = Node("parent")
child = Node("child")
parent.add_child(child)

# 即使删除引用,循环引用仍然存在
del parent
del child

# 垃圾回收器会自动处理
gc.collect()

# 4. 弱引用(避免循环引用)
import weakref

class Data:
    def __init__(self, value):
        self.value = value

data = Data(42)
weak_ref = weakref.ref(data)

print(weak_ref())  # <__main__.Data object>

del data
print(weak_ref())  # None

# 5. 弱引用字典和集合
weak_dict = weakref.WeakKeyDictionary()
weak_set = weakref.WeakSet()

# 6. __slots__ 节省内存
class Point:
    __slots__ = ['x', 'y']  # 不使用 __dict__
    
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(1, 2)
# p.z = 3  # 错误!不能添加新属性

# 7. 内存分析
import tracemalloc

# 开始跟踪
tracemalloc.start()

# 执行代码
data = [i for i in range(100000)]

# 获取内存快照
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')

for stat in top_stats[:10]:
    print(stat)

tracemalloc.stop()

# 8. 对象复用(小整数、短字符串)
a = 100
b = 100
print(a is b)  # True(-5 到 256 之间的整数会被缓存)

a = 1000
b = 1000
print(a is b)  # False(通常,但可能在交互式环境中为 True)

# 9. 生成器节省内存
def large_list():
    """返回大列表,占用大量内存"""
    return [i for i in range(1000000)]

def large_generator():
    """生成器,惰性计算,节省内存"""
    for i in range(1000000):
        yield i

# 使用生成器
for num in large_generator():
    if num > 100:
        break  # 只生成需要的部分

7. 设计模式

问题:Python 中如何实现常见的设计模式?

答案

python
# 1. 单例模式
class Singleton:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

# 使用装饰器实现
from functools import wraps

def singleton(cls):
    instances = {}
    @wraps(cls)
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper

@singleton
class Database:
    pass

# 2. 工厂模式
class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

class AnimalFactory:
    @staticmethod
    def create(animal_type):
        animals = {
            'dog': Dog,
            'cat': Cat
        }
        return animals.get(animal_type, Animal)()

# 使用
dog = AnimalFactory.create('dog')
print(dog.speak())  # Woof!

# 3. 观察者模式
class Subject:
    def __init__(self):
        self._observers = []
    
    def attach(self, observer):
        self._observers.append(observer)
    
    def detach(self, observer):
        self._observers.remove(observer)
    
    def notify(self, message):
        for observer in self._observers:
            observer.update(message)

class Observer:
    def __init__(self, name):
        self.name = name
    
    def update(self, message):
        print(f"{self.name} received: {message}")

# 使用
subject = Subject()
obs1 = Observer("Observer 1")
obs2 = Observer("Observer 2")

subject.attach(obs1)
subject.attach(obs2)
subject.notify("Hello!")

# 4. 策略模式
from abc import ABC, abstractmethod

class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

class CreditCardPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Paid {amount} using Credit Card")

class PayPalPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Paid {amount} using PayPal")

class ShoppingCart:
    def __init__(self):
        self._strategy = None
    
    def set_strategy(self, strategy):
        self._strategy = strategy
    
    def checkout(self, amount):
        if self._strategy:
            self._strategy.pay(amount)

# 使用
cart = ShoppingCart()
cart.set_strategy(CreditCardPayment())
cart.checkout(100)

# 5. 装饰器模式
class Coffee:
    def cost(self):
        return 5
    
    def description(self):
        return "Simple coffee"

class CoffeeDecorator(Coffee):
    def __init__(self, coffee):
        self._coffee = coffee
    
    def cost(self):
        return self._coffee.cost()
    
    def description(self):
        return self._coffee.description()

class Milk(CoffeeDecorator):
    def cost(self):
        return self._coffee.cost() + 1
    
    def description(self):
        return self._coffee.description() + ", milk"

class Sugar(CoffeeDecorator):
    def cost(self):
        return self._coffee.cost() + 0.5
    
    def description(self):
        return self._coffee.description() + ", sugar"

# 使用
coffee = Coffee()
coffee = Milk(coffee)
coffee = Sugar(coffee)
print(coffee.description())  # Simple coffee, milk, sugar
print(coffee.cost())         # 6.5

# 6. 建造者模式
class Pizza:
    def __init__(self):
        self.dough = None
        self.sauce = None
        self.topping = []
    
    def __str__(self):
        return f"Pizza with {self.dough}, {self.sauce}, {self.topping}"

class PizzaBuilder:
    def __init__(self):
        self.pizza = Pizza()
    
    def set_dough(self, dough):
        self.pizza.dough = dough
        return self
    
    def set_sauce(self, sauce):
        self.pizza.sauce = sauce
        return self
    
    def add_topping(self, topping):
        self.pizza.topping.append(topping)
        return self
    
    def build(self):
        return self.pizza

# 使用
pizza = (PizzaBuilder()
         .set_dough("thin")
         .set_sauce("tomato")
         .add_topping("cheese")
         .add_topping("mushrooms")
         .build())
print(pizza)

8. 函数式编程

问题:Python 如何支持函数式编程?

答案

python
# 1. 高阶函数
def apply_operation(x, operation):
    return operation(x)

result = apply_operation(5, lambda x: x ** 2)  # 25

# 2. map, filter, reduce
from functools import reduce

# map
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, numbers))

# filter
evens = list(filter(lambda x: x % 2 == 0, numbers))

# reduce
product = reduce(lambda x, y: x * y, numbers)  # 120

# 3. 偏函数
from functools import partial

def power(base, exponent):
    return base ** exponent

square = partial(power, exponent=2)
cube = partial(power, exponent=3)

print(square(5))  # 25
print(cube(3))    # 27

# 4. 函数组合
def compose(*functions):
    def composed(x):
        result = x
        for f in reversed(functions):
            result = f(result)
        return result
    return composed

def add_one(x):
    return x + 1

def double(x):
    return x * 2

def square(x):
    return x ** 2

# (x + 1) * 2 ^ 2
transform = compose(square, double, add_one)
print(transform(3))  # ((3 + 1) * 2) ^ 2 = 64

# 5. 不可变数据结构
from collections import namedtuple

# namedtuple 是不可变的
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
# p.x = 30  # 错误!不可变

# 使用 frozenset
frozen = frozenset([1, 2, 3])
# frozen.add(4)  # 错误!不可变

# 6. 递归
# 尾递归优化(Python 不支持尾递归优化,但可以使用装饰器模拟)
class TailRecurseException(Exception):
    def __init__(self, args, kwargs):
        self.args = args
        self.kwargs = kwargs

def tail_call_optimized(func):
    def wrapper(*args, **kwargs):
        f = func
        while True:
            try:
                return f(*args, **kwargs)
            except TailRecurseException as e:
                args = e.args
                kwargs = e.kwargs
                f = e.kwargs.pop('__func__', func)
    return wrapper

@tail_call_optimized
def factorial(n, acc=1):
    if n == 0:
        return acc
    raise TailRecurseException(
        args=(n - 1, n * acc),
        kwargs={'__func__': factorial}
    )

# 7. 闭包
def make_multiplier(n):
    def multiplier(x):
        return x * n
    return multiplier

double = make_multiplier(2)
triple = make_multiplier(3)

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

# 8. 惰性求值
def fibonacci():
    """无限斐波那契数列"""
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# 惰性求值
fib = fibonacci()
first_10 = [next(fib) for _ in range(10)]

# itertools 中的惰性求值
import itertools

# 无限序列
count = itertools.count(1)
evens = (x for x in count if x % 2 == 0)

# 惰性切片
first_5_evens = list(itertools.islice(evens, 5))

9. 性能优化

问题:如何优化 Python 代码的性能?

答案

python
# 1. 使用内置函数和库
# 慢
result = []
for i in range(1000):
    result.append(i * 2)

# 快
result = [i * 2 for i in range(1000)]

# 更快
result = list(map(lambda x: x * 2, range(1000)))

# 2. 使用生成器节省内存
def read_large_file(file_path):
    """生成器方式,内存友好"""
    with open(file_path, 'r') as f:
        for line in f:
            yield line.strip()

# 3. 使用 __slots__ 节省内存
class Point:
    __slots__ = ['x', 'y']
    
    def __init__(self, x, y):
        self.x = x
        self.y = y

# 4. 使用 lru_cache 缓存
from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 5. 使用 C 扩展
# Cython
# import pyximport
# pyximport.install()

# Numba
from numba import jit

@jit(nopython=True)
def fast_sum(arr):
    total = 0
    for i in range(len(arr)):
        total += arr[i]
    return total

# 6. 使用多进程处理 CPU 密集型任务
from multiprocessing import Pool

def cpu_intensive(n):
    return sum(i ** 2 for i in range(n))

with Pool(4) as pool:
    results = pool.map(cpu_intensive, [1000000] * 4)

# 7. 使用 asyncio 处理 I/O 密集型任务
import asyncio
import aiohttp

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

async def main():
    urls = ['http://example.com'] * 10
    tasks = [fetch(url) for url in urls]
    results = await asyncio.gather(*tasks)

# 8. 使用 NumPy 进行数值计算
import numpy as np

# 慢:纯 Python
result = [x ** 2 for x in range(1000000)]

# 快:NumPy
arr = np.arange(1000000)
result = arr ** 2

# 9. 使用 Pandas 进行数据处理
import pandas as pd

# 向量化操作比循环快
df = pd.DataFrame({'A': range(1000000), 'B': range(1000000)})

# 慢
result = []
for i in range(len(df)):
    result.append(df.iloc[i]['A'] + df.iloc[i]['B'])

# 快
df['C'] = df['A'] + df['B']

# 10. 性能分析
import cProfile
import pstats

# 使用 cProfile
profiler = cProfile.Profile()
profiler.enable()

# 要分析的代码
slow_function()

profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(10)

# 使用 timeit
import timeit

print(timeit.timeit('"-".join(str(n) for n in range(100))', number=10000))

# 使用 line_profiler
# @profile
# def my_function():
#     pass

10. Python 3 新特性

问题:Python 3 相比 Python 2 有哪些重要新特性?

答案

python
# 1. print 函数(Python 3.0)
# Python 2: print "Hello"
# Python 3: 
print("Hello")

# 2. 除法(Python 3.0)
# Python 2: 5 / 2 = 2(整数除法)
# Python 3:
print(5 / 2)   # 2.5(真除法)
print(5 // 2)  # 2(地板除法)

# 3. Unicode 字符串(Python 3.0)
# Python 3 中 str 是 Unicode,bytes 是字节
s = "中文"  # Unicode
b = b"bytes"  # 字节

# 4. 迭代器取代列表(Python 3.0)
# range, map, filter, zip 返回迭代器
print(range(10))  # range(0, 10),不是列表

# 5. 非局部变量 nonlocal(Python 3.0)
def outer():
    x = 10
    def inner():
        nonlocal x  # 修改外层非全局变量
        x = 20
    inner()
    return x

print(outer())  # 20

# 6. 函数注解(Python 3.0)
def greet(name: str, age: int) -> str:
    return f"Hello {name}, you are {age}"

# 7. 矩阵乘法运算符 @(Python 3.5)
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
c = a @ b  # 矩阵乘法

# 8. 异步编程 async/await(Python 3.5)
import asyncio

async def fetch_data():
    await asyncio.sleep(1)
    return "data"

async def main():
    result = await fetch_data()
    print(result)

asyncio.run(main())

# 9. f-string(Python 3.6)
name = "Alice"
age = 25
print(f"My name is {name}, I'm {age} years old")
print(f"Next year I'll be {age + 1}")

# 10. 数据类 dataclass(Python 3.7)
from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int = 0

p = Person("Alice", 25)
print(p)  # Person(name='Alice', age=25)

# 11. 海象运算符 :=(Python 3.8)
# 在表达式中赋值
if (n := len([1, 2, 3])) > 2:
    print(f"Length is {n}")

# 12. 位置参数和关键字参数分隔符 / 和 *(Python 3.8)
def func(a, b, /, c, d, *, e, f):
    """
    a, b: 必须是位置参数
    c, d: 可以是位置或关键字参数
    e, f: 必须是关键字参数
    """
    pass

func(1, 2, 3, 4, e=5, f=6)  # 正确
func(1, 2, c=3, d=4, e=5, f=6)  # 正确
# func(1, 2, 3, 4, 5, 6)  # 错误!e, f 必须是关键字参数

# 13. 类型提示增强(Python 3.9+)
# Python 3.9: 内置泛型类型
from typing import List, Dict

def process(data: list[int]) -> dict[str, int]:
    return {}

# Python 3.10: 联合类型使用 |
def func(x: int | str) -> None:
    pass

# Python 3.10: match-case 模式匹配
def http_status(status):
    match status:
        case 200:
            return "OK"
        case 404:
            return "Not Found"
        case 500:
            return "Server Error"
        case _:
            return "Unknown"

# Python 3.11: 异常组和处理
# except* 用于处理 ExceptionGroup

# Python 3.12: 类型参数语法
def func[T](x: T) -> T:
    return x