🐍 Python 语法全景图:一个 print() 引发的深度探索

🐍 Python 语法全景图:一个 print() 引发的深度探索

摘要 :从一个简单的 print() 函数签名出发,深入剖析 Python 的参数系统、对象模型、self 机制、推导式、装饰器等核心语法特性,帮你建立完整的 Python 语法知识体系。


📑 目录

  1. [print() 函数签名:一个窗口看 Python 参数体系](#print() 函数签名:一个窗口看 Python 参数体系 "#%E4%B8%80print-%E5%87%BD%E6%95%B0%E7%AD%BE%E5%90%8D%E4%B8%80%E4%B8%AA%E7%AA%97%E5%8F%A3%E7%9C%8B-python-%E5%8F%82%E6%95%B0%E4%BD%93%E7%B3%BB")
  2. [Python 对象模型:一切皆对象](#Python 对象模型:一切皆对象 "#%E4%BA%8Cpython-%E5%AF%B9%E8%B1%A1%E6%A8%A1%E5%9E%8B%E4%B8%80%E5%88%87%E7%9A%86%E5%AF%B9%E8%B1%A1")
  3. [数据结构与推导式:Python 的标志性语法](#数据结构与推导式:Python 的标志性语法 "#%E4%B8%89%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E6%8E%A8%E5%AF%BC%E5%BC%8Fpython-%E7%9A%84%E6%A0%87%E5%BF%97%E6%80%A7%E8%AF%AD%E6%B3%95")
  4. 函数进阶:装饰器、闭包与生成器
  5. [面向对象:self、init 与魔术方法](#面向对象:self、init 与魔术方法 "#%E4%BA%94%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1selfinit-%E4%B8%8E%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95")
  6. [name 与模块化:Python 项目的入口机制](#name 与模块化:Python 项目的入口机制 "#name-%E4%B8%8E%E6%A8%A1%E5%9D%97%E5%8C%96python-%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%85%A5%E5%8F%A3%E6%9C%BA%E5%88%B6")
  7. [现代 Python 语法糖:让代码更简洁](#现代 Python 语法糖:让代码更简洁 "#%E5%85%AD%E7%8E%B0%E4%BB%A3-python-%E8%AF%AD%E6%B3%95%E7%B3%96%E8%AE%A9%E4%BB%A3%E7%A0%81%E6%9B%B4%E7%AE%80%E6%B4%81")
  8. 异常处理:优雅地处理错误
  9. 综合实战:用所学知识构建一个简易工具

📌 前言

很多 Python 开发者写了好几年代码,可能都没认真看过 print() 函数的完整签名:

python 复制代码
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

但就是这么一行签名,背后藏着 Python 语法的精髓------可变参数、关键字参数、默认值、文件对象、缓冲机制......

今天我们就从这个 print() 出发,一路延伸到 Python 语法的方方面面,帮你把零散的知识点串成体系。

🎯 本文适合谁

  • 🔰 有基础但想系统梳理 Python 语法的开发者
  • 💼 准备面试需要全面复习 Python 基础的同学
  • 🚀 想从其他语言转 Python,快速掌握核心特性的工程师
  • 📚 对 Python 设计哲学感兴趣的好奇宝宝

📚 一、print() 函数签名:一个窗口看 Python 参数体系

1.1 完整签名拆解

python 复制代码
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
参数 类型 默认值 说明
*objects 可变位置参数 一个或多个要输出的对象,自动转为字符串
sep str ' ' 多个对象之间的分隔符
end str '\n' 输出末尾追加的字符串
file 文件对象 sys.stdout 输出的目标流(必须有 write() 方法)
flush bool False 是否强制刷新输出缓冲区

1.2 可变位置参数 *args

python 复制代码
print("a", "b", "c")   # *objects 接收任意数量的位置参数

* 前缀表示,会把多个位置参数打包成一个元组 。命名不固定,常见约定是 *args

python 复制代码
def demo(*args):
    print(type(args))  # <class 'tuple'>
    print(args)        # (1, 2, 3)

demo(1, 2, 3)

1.3 关键字参数 + 默认值

python 复制代码
print("a", "b", sep="-", end="!")
# 输出: a-b!

调用时可以用 参数名=值 的形式显式指定,定义时可以给默认值,调用时可不传。

1.4 参数定义的顺序规则

Python 函数参数定义有严格的顺序:

python 复制代码
def func(a, b, *args, c=10, **kwargs):
    pass
#  位置参数 → *args → 关键字参数 → **kwargs

💡 记住这个顺序:位置参数 → 可变位置参数 → 关键字参数 → 可变关键字参数

1.5 可变关键字参数 **kwargs

python 复制代码
def demo(**kwargs):
    print(type(kwargs))  # <class 'dict'>
    print(kwargs)        # {'name': '旺财', 'age': 3}

demo(name="旺财", age=3)

** 前缀表示,会把多个关键字参数打包成一个字典


📚 二、Python 对象模型:一切皆对象

2.1 什么是对象?

在 Python 中,一切皆对象(Everything is an object)

对象 = 数据(属性) + 行为(方法),是内存中实际存在的实体。

python 复制代码
# 数字也是对象,有方法!
n = 42
print(n.bit_length())  # 6

# 字符串也是对象
s = "hello"
print(s.upper())       # HELLO

# 函数也是对象,可以挂载属性
def foo():
    pass

foo.description = "这是一个函数"
print(foo.description)

# 类本身也是对象(元类的实例)
print(type(Dog))       # <class 'type'>

# 模块也是对象
import math
print(type(math))      # <class 'module'>

2.2 对象的三个核心特征

特征 获取方式 说明
身份(identity) id(obj) 对象的唯一内存地址
类型(type) type(obj) 对象所属的类
值(value) 对象本身 存储的数据
python 复制代码
a = [1, 2, 3]
print(id(a))     # 身份:内存地址
print(type(a))   # 类型:<class 'list'>
print(a)         # 值:[1, 2, 3]

2.3 变量是引用,不是容器

这是 Python 新手最容易踩的坑:

python 复制代码
a = [1, 2, 3]
b = a          # b 和 a 指向同一个对象
b.append(4)
print(a)       # [1, 2, 3, 4]  ------ a 也变了!

⚠️ 变量不是对象本身,变量只是贴在对象上的"标签"(引用)。 修改对象时,所有指向它的变量都会看到变化。

2.4 可变对象 vs 不可变对象

类型 是否可变 例子
不可变对象 创建后值不能改 intfloatstrtupleboolfrozenset
可变对象 创建后值可以改 listdictset、自定义类实例
python 复制代码
# 不可变:看起来"修改",其实是创建了新对象
s = "abc"
s = s.upper()   # 不是改原字符串,而是返回新字符串对象

# 可变:直接修改原对象
lst = [1, 2, 3]
lst.append(4)   # 原列表被修改

📚 三、数据结构与推导式:Python 的标志性语法

3.1 四大内置容器

类型 字面量 有序 可变 例子
列表 list [] [1, 2, 3]
元组 tuple () (1, 2, 3)
字典 dict {} ✅(3.7+) {"a": 1}
集合 set {} {1, 2, 3}

3.2 切片操作:序列类型的通用语法

python 复制代码
lst = [0, 1, 2, 3, 4, 5]
lst[1:4]      # [1, 2, 3]       从索引1到3
lst[::2]      # [0, 2, 4]       步长为2
lst[::-1]     # [5, 4, 3, 2, 1] 反转
lst[-1]       # 5               最后一个元素

3.3 推导式:一行代码表达复杂逻辑

推导式是 Python 最具标志性的语法之一,简洁且高效:

python 复制代码
# 列表推导式
squares = [x**2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 带条件的列表推导式
evens = [x for x in range(10) if x % 2 == 0]

# 字典推导式
square_dict = {x: x**2 for x in range(5)}

# 集合推导式
unique = {x % 3 for x in range(10)}  # {0, 1, 2}

# 生成器推导式(惰性计算,节省内存)
gen = (x**2 for x in range(10))

3.4 解包操作:优雅的数据拆分

python 复制代码
# 元组/列表解包
a, b, c = (1, 2, 3)
a, *rest = [1, 2, 3, 4]    # a=1, rest=[2, 3, 4]

# 字典解包
d1 = {"a": 1}
d2 = {"b": 2}
merged = {**d1, **d2}      # {"a": 1, "b": 2}

# 函数调用解包
args = (1, 2, 3)
print(*args)               # 等同于 print(1, 2, 3)

📚 四、函数进阶:装饰器、闭包与生成器

4.1 Lambda 匿名函数

python 复制代码
add = lambda x, y: x + y
print(add(3, 5))    # 8

# 常用于排序、映射
points = [(1, 2), (3, 1), (5, 4)]
points.sort(key=lambda p: p[1])
# [(3, 1), (1, 2), (5, 4)]

4.2 高阶函数:map / filter / reduce / zip

python 复制代码
# map ------ 映射
list(map(lambda x: x*2, [1, 2, 3]))    # [2, 4, 6]

# filter ------ 过滤
list(filter(lambda x: x > 0, [-1, 2, -3, 4]))  # [2, 4]

# reduce ------ 归约
from functools import reduce
reduce(lambda x, y: x + y, [1, 2, 3, 4])  # 10

# zip ------ 配对
list(zip([1, 2, 3], ["a", "b", "c"]))
# [(1, 'a'), (2, 'b'), (3, 'c')]

4.3 装饰器:不修改原函数,为其增加功能

装饰器是 Python 中最优雅的设计模式之一:

python 复制代码
import time
import functools

def timer(func):
    @functools.wraps(func)     # ⚠️ 必须加!保留原函数的元信息(名称、文档等)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"{func.__name__} 耗时: {time.time()-start:.4f}s")
        return result
    return wrapper

@timer                   # 等同于 slow_func = timer(slow_func)
def slow_func():
    time.sleep(1)

slow_func()
print(slow_func.__name__)  # slow_func(如果没有 @wraps,会变成 wrapper)

💡 装饰器的本质@timer 语法糖等价于 slow_func = timer(slow_func),它接收一个函数,返回一个增强后的新函数。
⚠️ 踩坑提醒 :不加 @functools.wraps(func) 会导致原函数的 __name____doc__ 等元信息丢失。我曾经在项目中因为漏掉这个,导致 Flask 路由注册全部指向同一个函数名,排查了两个小时才发现。记住:写装饰器,第一行就写 @wraps

4.4 闭包与作用域(LEGB 规则)

Python 查找变量的顺序:Local → Enclosing → Global → Built-in

python 复制代码
def outer():
    x = 10              # Enclosing 作用域
    def inner():
        print(x)        # 从闭包中捕获 x
    return inner

f = outer()
f()                     # 10

4.5 生成器:用 yield 实现惰性计算

python 复制代码
def countdown(n):
    while n > 0:
        yield n
        n -= 1

for num in countdown(3):
    print(num)          # 3, 2, 1

生成器不会一次性把所有值加载到内存,而是用到时才计算,非常适合处理大数据流。


📚 五、面向对象:self、init 与魔术方法

5.1 self 到底是什么?

很多从 Java/C++ 转来的同学会疑惑:为什么 Python 的实例方法必须显式写 self,而 Java 的 this 不需要?

python 复制代码
class Dog:
    def __init__(self, name):
        self.name = name          # self 指向正在被创建的实例

    def bark(self):
        print(f"{self.name}: 汪汪!")

dog = Dog("旺财")
dog.bark()                        # 旺财: 汪汪!

self 的本质 :它就是实例对象自身的引用 。当你调用 dog.bark() 时,Python 会自动把 dog 作为第一个参数传入,所以 bark(self) 里的 self 就是 dog

🤔 为什么 Python 选择显式写 self

Python 的设计哲学是 "Explicit is better than implicit"(显式优于隐式) 。显式声明 self 让你一眼就能区分实例属性和局部变量,也让方法的定义和调用保持一致性------虽然写起来多了几个字母,但代码的可读性和确定性更高。

常见错误:忘记写 self

python 复制代码
class Dog:
    def bark():              # ❌ 忘记 self
        print("汪汪")

dog = Dog()
dog.bark()                   # TypeError: bark() takes 0 positional arguments but 1 was given

Python 报错说"bark 需要 0 个参数但给了 1 个"------因为 dog.bark() 等价于 Dog.bark(dog)dog 被传进去了但函数签名里没有 self 来接收。

5.2 init:构造函数的正确打开方式

__init__ 是 Python 中最常用的魔术方法,负责初始化新创建的实例

python 复制代码
class Dog:
    def __init__(self, name, age=0):    # 支持默认参数
        self.name = name
        self.age = age

dog = Dog("旺财", 3)

init vs new 的区别:

__new__ __init__
作用 创建实例(分配内存) 初始化实例(设置属性)
第一个参数 cls(类本身) self(实例)
调用时机 __init__ 之前 __new__ 之后
何时重写 单例模式、不可变类型子类化 日常开发几乎只用这个
python 复制代码
class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self, name):
        self.name = name

a = Singleton("A")
b = Singleton("B")
print(a is b)        # True ------ 同一个实例!
print(a.name)        # B ------ __init__ 被调用了两次

⚠️ 经典踩坑:可变默认参数

python 复制代码
# ❌ 错误写法:所有实例共享同一个列表!
class BadExample:
    def __init__(self, items=[]):   # 默认参数在定义时求值,只创建一次
        self.items = items

a = BadExample()
a.items.append(1)
b = BadExample()
print(b.items)     # [1] ------ b 居然看到了 a 添加的元素!

# ✅ 正确写法
class GoodExample:
    def __init__(self, items=None):
        self.items = items if items is not None else []

继承中的 init 调用链:

python 复制代码
class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)    # 调用父类的 __init__
        self.breed = breed

dog = Dog("旺财", "柴犬")
print(dog.name)    # 旺财
print(dog.breed)   # 柴犬

5.3 封装:属性访问控制

python 复制代码
class Account:
    def __init__(self):
        self._balance = 0        # 单下划线:约定为"私有"

    @property
    def balance(self):            # getter
        return self._balance

    @balance.setter
    def balance(self, value):     # setter
        if value < 0:
            raise ValueError("余额不能为负")
        self._balance = value

acc = Account()
acc.balance = 100
print(acc.balance)    # 100

5.4 方法分类

python 复制代码
class MyClass:
    def instance_method(self):       # 实例方法:第一个参数是 self
        pass

    @classmethod
    def class_method(cls):           # 类方法:第一个参数是 cls
        pass

    @staticmethod
    def static_method():             # 静态方法:无强制参数
        pass

5.5 多继承与 MRO

python 复制代码
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

print(D.__mro__)
# (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

Python 使用 C3 线性化算法确定方法解析顺序(MRO),解决了菱形继承问题。

🤔 为什么 Python 支持多继承而 Java 不允许? Python 选择了灵活性------通过 MRO 算法保证方法调用的确定性。但实践中,优先使用组合而非多继承,多继承更适合 Mixin 模式。

5.6 魔术方法一览

方法 触发场景
__init__ 对象创建时(初始化)
__new__ 对象分配内存(创建实例)
__str__ / __repr__ print() / 交互模式显示
__len__ len(obj)
__getitem__ / __setitem__ obj[key] 读写
__iter__ / __next__ for 循环迭代
__enter__ / __exit__ with 语句
__call__ obj() 调用
__eq__ / __lt__ 比较运算符

📚 六、name 与模块化:Python 项目的入口机制

6.1 name 是什么?

__name__ 是 Python 的一个内置属性 ,每个 .py 文件(模块)都有。它的值取决于文件是如何被使用的:

python 复制代码
# my_module.py
print(f"__name__ = {__name__}")

def hello():
    print("Hello!")
python 复制代码
# 直接运行 my_module.py
# 输出:__name__ = __main__

# 在另一个文件中导入
import my_module
# 输出:__name__ = my_module
场景 __name__ 的值
文件被直接运行(python my_module.py "__main__"
文件被导入(import my_module "my_module"(模块名)

6.2 if name == "main":控制代码执行时机

这是 Python 项目中最常见的模式之一,用于区分"被直接运行"和"被导入":

python 复制代码
# calculator.py
def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

# 只在直接运行时执行,被导入时不执行
if __name__ == "__main__":
    print(add(1, 2))          # 3
    print(subtract(5, 3))     # 2

为什么需要这个?

python 复制代码
# main.py
import calculator

result = calculator.add(10, 20)   # ✅ 只导入函数,不会触发测试代码

如果没有 if __name__ == "__main__" 守卫,每次 import calculator 都会执行 print(add(1, 2))------这不是我们想要的。

💡 实际项目中的典型用法

  • 单元测试 :把测试代码放在 if __name__ == "__main__" 里,模块被导入时不会执行测试
  • 脚本入口:CLI 工具的启动代码放在这个守卫里
  • 调试代码:临时的调试 print 可以放在这里,不会污染导入方
python 复制代码
# 一个完整的 CLI 脚本模板
import argparse

def process_data(data, verbose=False):
    """核心业务逻辑"""
    result = data.upper()
    if verbose:
        print(f"处理结果: {result}")
    return result

def main():
    parser = argparse.ArgumentParser(description="数据处理工具")
    parser.add_argument("data", help="要处理的数据")
    parser.add_argument("-v", "--verbose", action="store_true")
    args = parser.parse_args()

    result = process_data(args.data, verbose=args.verbose)
    print(result)

if __name__ == "__main__":
    main()

📚 七、现代 Python 语法糖:让代码更简洁

7.1 f-string 格式化字符串(3.6+)

python 复制代码
name = "旺财"
age = 3
print(f"{name} {age}岁")            # 旺财 3岁
print(f"{2 + 2 = }")                # 2 + 2 = 4(3.8+ 调试语法)

7.2 海象运算符 := (3.8+)

在表达式中同时赋值和使用:

python 复制代码
# 传统写法
line = input()
while line != "quit":
    print(line)
    line = input()

# 海象运算符写法
while (line := input()) != "quit":
    print(line)

7.3 dataclass(3.7+)

自动生成 __init____repr__ 等样板代码:

python 复制代码
from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int
    email: str = ""

u = User("张三", 25)
print(u)   # User(name='张三', age=25, email='')

7.4 match-case 模式匹配(3.10+)

python 复制代码
def http_error(status):
    match status:
        case 200:
            return "OK"
        case 404:
            return "Not Found"
        case 500 | 503:
            return "Server Error"
        case _:
            return "Unknown"

7.5 类型注解(3.5+)

python 复制代码
def greet(name: str) -> str:
    return f"Hello, {name}"

# Python 3.10+ 简化写法
def func(x: int | None) -> list[int]:
    ...

7.6 上下文管理器与 with 语句

python 复制代码
# 基于类实现
class MyContext:
    def __enter__(self):
        print("进入")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("退出")
        return False

# 基于生成器(更简洁)
from contextlib import contextmanager

@contextmanager
def my_context():
    print("进入")
    yield
    print("退出")

📚 八、异常处理:优雅地处理错误

python 复制代码
try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"除零错误: {e}")
except (TypeError, ValueError) as e:
    print(f"类型或值错误: {e}")
else:
    print("没有异常时执行")
finally:
    print("无论是否异常都执行")

# 自定义异常
class MyError(Exception):
    pass

raise MyError("自定义错误信息")

💡 try/except/else/finally 四兄弟各有分工:except 捕获异常,else 在无异常时执行,finally 无论如何都执行(常用于资源清理)。


💡 九、重点总结

从一个 print() 函数出发,我们串起了 Python 语法的几大支柱:

语法特性 核心要点
函数参数系统 *args / **kwargs / 默认值 / 关键字参数
对象模型 一切皆对象,变量是引用,可变 vs 不可变
self 与 init self 是实例引用,init 初始化实例,可变默认参数陷阱
name 与模块化 if __name__ == "__main__" 控制模块入口
数据结构 list / dict / set / tuple,切片,推导式,解包
函数式编程 lambda / map / filter / 装饰器(+wraps) / 生成器 / 闭包
面向对象 封装 / 继承 / 多态 / 魔术方法 / MRO
现代语法糖 f-string / 海象运算符 / dataclass / match-case / 类型注解
工程化支撑 异常处理 / 上下文管理器 / 模块包管理

Python 的设计哲学是 「简洁而强大」------用最少的代码表达最复杂的逻辑。这些语法特性不是孤立的,它们相互配合,构成了 Python 独特的编程范式。


🛠️ 十、综合实战:用所学知识构建一个简易缓存装饰器

学了这么多语法特性,最后我们用一个实战案例把它们串起来。下面实现一个带 TTL(过期时间)和日志的缓存装饰器

python 复制代码
import time
import functools
from datetime import datetime

# ========== 1. 装饰器 + functools.wraps(4.3 节) ==========
def cache_with_ttl(ttl_seconds=60):
    """带过期时间的缓存装饰器(装饰器工厂:外层接收参数,内层接收函数)"""
    def decorator(func):
        cache = {}    # 闭包捕获的变量(4.4 节)

        @functools.wraps(func)    # 保留原函数元信息
        def wrapper(*args, **kwargs):    # 可变参数(1.2 节)
            key = (args, tuple(sorted(kwargs.items())))

            # 上下文管理器思路:检查缓存是否过期
            if key in cache:
                result, timestamp = cache[key]
                if time.time() - timestamp < ttl_seconds:
                    print(f"[缓存命中] {func.__name__}{args}")
                    return result
                else:
                    del cache[key]    # 过期清除

            # 调用原函数并缓存结果
            result = func(*args, **kwargs)
            cache[key] = (result, time.time())
            print(f"[缓存写入] {func.__name__}{args}")
            return result

        wrapper.cache_clear = lambda: cache.clear()    # 动态属性(对象特性,2.1 节)
        return wrapper
    return decorator

# ========== 2. 类 + self + __init__ + __str__(5.1、5.2 节) ==========
class APIClient:
    """模拟 API 客户端"""

    def __init__(self, base_url: str, timeout: int = 30):    # __init__ + 默认参数
        self.base_url = base_url
        self.timeout = timeout
        self._request_count = 0    # 私有属性(5.3 节)

    @property
    def request_count(self) -> int:    # @property + 类型注解(7.5 节)
        return self._request_count

    def __str__(self) -> str:    # 魔术方法(5.6 节)
        return f"APIClient({self.base_url}, 请求次数={self._request_count})"

    @cache_with_ttl(ttl_seconds=10)    # 装饰器应用(4.3 节)
    def get_user(self, user_id: int) -> dict:
        """模拟 API 调用(实际项目中会用 requests)"""
        self._request_count += 1
        time.sleep(0.5)    # 模拟网络延迟
        return {"id": user_id, "name": f"用户{user_id}"}

# ========== 3. 异常处理 + with 语句(8 节、7.6 节) ==========
def safe_api_call(client: APIClient, user_id: int):
    """带异常处理的安全调用"""
    try:
        result = client.get_user(user_id)
    except Exception as e:    # 通用异常捕获
        print(f"❌ 请求失败: {e}")
        return None
    else:
        print(f"✅ 请求成功: {result}")
        return result
    finally:
        print(f"📊 当前请求次数: {client.request_count}")

# ========== 4. if __name__ == "__main__"(6.2 节) ==========
if __name__ == "__main__":
    # f-string 格式化(7.1 节)
    client = APIClient("https://api.example.com")
    print(f"客户端信息: {client}")

    # 第一次调用:缓存写入
    safe_api_call(client, 1)

    # 第二次调用:缓存命中(不会真正调用 API)
    safe_api_call(client, 1)

    # 不同参数:缓存未命中
    safe_api_call(client, 2)

运行输出:

css 复制代码
客户端信息: APIClient(https://api.example.com, 请求次数=0)
[缓存写入] get_user(1,)
✅ 请求成功: {'id': 1, 'name': '用户1'}
📊 当前请求次数: 1
[缓存命中] get_user(1,)
✅ 请求成功: {'id': 1, 'name': '用户1'}
📊 当前请求次数: 1
[缓存写入] get_user(2,)
✅ 请求成功: {'id': 2, 'name': '用户2'}
📊 当前请求次数: 2

💡 这个小案例用到了本文讲过的 :装饰器 + functools.wraps*args/**kwargs、闭包、类定义、self/__init__@property、魔术方法 __str__、异常处理、if __name__ == "__main__"、f-string、类型注解------一个案例串联了 10+ 个语法特性


🔗 参考资料

💬 交流讨论

看到这里,不妨来挑战一下:

  1. 🧠 面试题__init____new__ 的区别是什么?什么场景需要重写 __new__
  2. 💬 评论区打卡 :你在项目中踩过最深的 Python 坑是什么?(我先来:装饰器没加 @wraps 导致 Flask 路由全乱了 😂)
  3. 觉得有收获的话,点个收藏,下次面试前翻出来复习会感谢自己的!

📖 下一篇预告:《Python 高级特性:迭代器协议、描述符、元类------从"会用"到"懂原理"》敬请期待!

相关推荐
沧海一笑-dj2 分钟前
【Python】Python学习笔记-初识 Python
python·python安装·python解释器
打工仔折腾 AI6 分钟前
FastAPI 从本机到生产服务器:Nginx+Gunicorn+Uvicorn 完整部署实录
人工智能·后端·python·nginx·fastapi·gunicorn
hanchenxing19 分钟前
AI 数据管道重构:从函数堆到链式管道的可读性实践
python
hhzz26 分钟前
【OpenCV 入门到精通 10】视频分析与光流跟踪:背景减除与运动检测
人工智能·python·opencv·性能优化
蓝胖的四次元口袋26 分钟前
Python基础语法入门
python
Patrick在香港1 小时前
Python 抓 0.91 GB 香港法例:Agent 的进度该写进磁盘,不是写进上下文
爬虫·python·api·claude·香港
ClinicTech1 小时前
实验室洗瓶机的清洗系统架构与自动化控制解析
java·python
洋洋不叫杨杨1 小时前
Codex 实战:用 AI 写运维脚本
大数据·python
高级程序源1 小时前
django大学生创新创业项目管理系统94923-计算机课程设计、毕业设计
javascript·vue.js·spring boot·后端·python·django·课程设计
wno7042 小时前
Spring Security短信验证码登录
java·python·spring