page contents

Python 语法的 5 个反直觉设计,知道的都是老手

入职第一周,我以为 Python 是最简单的语言。直到 SQL 查询前面多了一堆空格、装饰器在导入时就偷偷连了数据库。

attachments-2026-05-AMmYHx0M6a0bbd49d1223.png入职第一周,我以为 Python 是最简单的语言。直到 SQL 查询前面多了一堆空格、装饰器在导入时就偷偷连了数据库。

才发现这门简单语言,挖坑的姿势相当刁钻。

坑 1:多行字符串的缩进

先看这段代码,猜猜输出是什么:

def get_sql():    query = """    SELECT *    FROM users    WHERE active = 1    """    return query
print(repr(get_sql()))

你以为是没有前导空格

实际上输出的是每行前面有 4 个空格

三引号字符串会保留所有空白字符,包括缩进产生的空格。在函数内部使用多行字符串时,代码缩进会变成字符串内容的一部分。用 textwrap.dedent() 可以去掉公共前导空白。

正确写法:

import textwrap
def get_sql():    query = textwrap.dedent("""\    SELECT *    FROM users    WHERE active = 1    """)    return query.strip()

踩坑现场:SQL 查询拼接出来的语句前面多了一堆空格,数据库报语法错误。

坑 2:装饰器执行时机

先看这段代码,猜猜输出是什么:

def register(func):    print(f'注册: {func.__name__}')    return func
@registerdef hello():    print('hello')
print('--- 程序开始 ---')

你以为是先打印程序开始

实际上输出的是先打印注册: hello

装饰器在函数定义时就执行,不是在函数调用时。@register 等价于 hello = register(hello),这行代码在模块加载时就运行了。如果装饰器做了网络请求、数据库连接等操作,导入模块就会触发这些副作用。

正确写法:

# 如果需要延迟执行,装饰器只做标记REGISTRY = []
def register(func):    REGISTRY.append(func)  # 只记录,不执行    return func
@registerdef hello():    print('hello')
# 后续统一处理def run_all():    for func in REGISTRY:        func()

踩坑现场:测试框架的装饰器在导入时就执行了初始化,导致测试环境还没配置好就开始连数据库。

坑 3:海象运算符的限制

报错信息:SyntaxError: invalid syntax

出问题的代码:

# 不能用在普通赋值位置(x := 10)y := 20  # 这个不行

海象运算符 := 只能在表达式中使用,不能作为独立的赋值语句。它的设计目的是在 if、while 等需要表达式的地方同时赋值和判断。

修复方法:

# 正确用法:在表达式中赋值if (n := len(data)) > 10:    print(f'数据量 {n} 条')
# while 中也很好用while (line := f.readline()):    process(line)

坑 4:缩进混用空格和 Tab

报错信息:TabError: inconsistent use of tabs and spaces in indentation

出问题的代码:

def foo():    if True:        print('spaces')print('tab')

Python 3 不允许混用空格和 Tab 作为缩进。这个问题在复制粘贴代码时特别容易发生,因为不同编辑器对 Tab 的显示宽度不同。最佳实践是配置编辑器把 Tab 转换为 4 个空格。

修复方法:

# 配置编辑器:Tab 自动转为 4 空格def foo():    if True:        print('spaces')        print('also spaces')

坑 5:链式比较的隐含 and

最后来一道送分题,这段代码输出什么:

print(1 < 2 < 3)print(1 < 2 > 0)print(1 == 1 in [1, 2])

看起来应该是 True True True,实际也是 True True True

Python 的链式比较会展开为 and 连接:1 < 2 < 3 等于 1 < 2 and 2 < 3。这个特性很强大,但混合不同类型的比较时容易让人困惑。特别是 1 == 1 in [1,2] 不是 (1 == 1) in [1,2],而是 1 == 1 and 1 in [1,2]

以上 5 个坑,挑一个今天就记牢。写代码不怕慢,怕的是跑出来结果不对。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

2059 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 2228 文章
  3. Pack 2059 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章