python的鬼畜写法(从js角度看)

目录标题

    • [1. 切片赋值(Slice Assignment)------ 替换列表中间的一段](#1. 切片赋值(Slice Assignment)—— 替换列表中间的一段)
    • [2. `for-else` 和 `while-else` ------ 循环没被 `break` 就执行](#2. for-elsewhile-else —— 循环没被 break 就执行)
    • [3. 链式比较(Chained Comparison)------ `a < b > c`](#3. 链式比较(Chained Comparison)—— a < b > c)
    • [4. 海象运算符(Walrus Operator)------ `:=`(Python 3.8+)](#4. 海象运算符(Walrus Operator)—— :=(Python 3.8+))
    • [5. 函数参数解包(`*` 和 `**` 在函数调用时)](#5. 函数参数解包(*** 在函数调用时))
    • [6. 下划线 `_` 的多种用途(乱用警告)](#6. 下划线 _ 的多种用途(乱用警告))
    • [7. `zip` + `*` 解包实现矩阵转置(终极鬼畜)](#7. zip + * 解包实现矩阵转置(终极鬼畜))
    • 8.作用域for
    • [💡 总结:这些"鬼畜"写法的本质](#💡 总结:这些“鬼畜”写法的本质)

一、单行 if(条件表达式)

javascript 复制代码
let status = age >= 18 ? '成年' : '未成年';
python 复制代码
status = '成年' if age >= 18 else '未成年'

二、多变量赋值(解构)

javascript 复制代码
let [a, b] = [1, 2];          // 数组解构
let { name, age } = person;   // 对象解构
python 复制代码
a, b = 1, 2           # 元组解构(看起来像没括号,其实右边是 (1, 2))
name, age = person    # 但必须按位置对应,不能像 JS 那样按属性名解构

三、最"抽象"的:*args 和 **kwargs

javascript 复制代码
function sum(...numbers) {     // ... 把参数收成数组
    return numbers.reduce((a, b) => a + b);
}
python 复制代码
def sum(*args):       # *args 收集成元组
    return sum(args)  # 这里用了内置 sum,但名字冲突了

总结:除了上面三个还有啥鬼畜写法吗

哈哈,你既然主动问"还有啥鬼畜写法",那我就不客气了------Python 里确实还有一堆"第一次见会怀疑人生"的写法。我挑几个最经典的,按"震惊程度"排序给你看:


1. 切片赋值(Slice Assignment)------ 替换列表中间的一段

写法:

python 复制代码
a = [1, 2, 3, 4, 5]
a[1:4] = [99, 88]   # 把索引 1~3 替换成 [99, 88]
print(a)  # [1, 99, 88, 5]

鬼畜在哪?

  • 左边是切片(取一段),右边是列表,长度可以不一样
  • 如果右边比左边短,列表会变短;如果右边比左边长,列表会变长。
  • 相当于用一段新数据"替换"旧数据,但长度自动调整------像"橡皮泥"一样可以伸缩。

对比 JS :JS 里要 splice(1, 3, 99, 88),专门用一个方法;Python 直接用赋值语法干这事。


2. for-elsewhile-else ------ 循环没被 break 就执行

写法:

python 复制代码
for i in range(5):
    if i == 10:
        break
else:
    print("循环正常结束,没有被 break")
# 输出:循环正常结束,没有被 break

鬼畜在哪?

  • else 不是和 if 配对,而是和 for/while 配对!
  • 它的逻辑是:如果循环没有被 break 中断,就执行 else
  • 用途:查找某个元素,如果找到了就 break,如果没找到就执行 else(比如"没找到,显示提示")。

对比 JS :没有这种写法,必须手动加一个 found 标志变量。


3. 链式比较(Chained Comparison)------ a < b > c

写法:

python 复制代码
x = 5
if 1 < x < 10:   # 等价于 1 < x and x < 10
    print("在范围内")

鬼畜在哪?

  • 你可以在一个表达式里写 a < b > c <= d,Python 会自动拆成多个比较,而且保证每个变量只计算一次。
  • 这在数学上很自然(1 < x < 10 是数学写法),但在编程语言里很少见。

对比 JS :JS 不支持链式比较,必须写成 1 < x && x < 10


4. 海象运算符(Walrus Operator)------ :=(Python 3.8+)

写法:

python 复制代码
if (n := len([1, 2, 3])) > 2:
    print(f"长度是 {n}")   # 输出:长度是 3

鬼畜在哪?

  • if 条件里同时完成赋值和使用
  • 相当于 n = len(...)if n > 2 写在一行。
  • 名字"海象"是因为 := 像海象的牙齿和眼睛(: 是眼睛,= 是牙齿)。

对比 JS :JS 里可以 if ((n = arr.length) > 2),但会警告(赋值在条件里通常被 eslint 禁止)。Python 专门造了个新语法来支持这件事。


5. 函数参数解包(*** 在函数调用时)

写法:

python 复制代码
def foo(a, b, c):
    print(a, b, c)

lst = [1, 2, 3]
foo(*lst)        # 输出:1 2 3(把列表拆成位置参数)

dct = {'a': 1, 'b': 2, 'c': 3}
foo(**dct)       # 输出:1 2 3(把字典拆成关键字参数)

鬼畜在哪?

  • 同一个 * 符号,在函数定义 里是"收集参数",在函数调用里是"展开参数"------含义刚好相反。
  • ** 在定义里收集关键字参数,在调用里展开字典。
  • 新手经常搞混 *args(定义时)和 func(*list)(调用时)。

对比 JS :JS 用 ... 同时做收集和展开,符号统一,更好记。


6. 下划线 _ 的多种用途(乱用警告)

用法 1:表示"我不需要这个值"

python 复制代码
for _ in range(10):   # 循环10次,不关心当前值
    print("hello")

用法 2:解构时忽略某些位置

python 复制代码
a, _, b = (1, 2, 3)   # a=1, b=3,2被忽略

用法 3:交互式环境里代表上一次表达式的结果

python 复制代码
>>> 3 + 4
7
>>> _ + 2
9   # _ 自动记住上次结果 7

用法 4:作为变量名(但会被 linter 警告)

python 复制代码
_ = 5   # 合法,但建议别这么用

鬼畜在哪?

  • 同一个 _ 符号,在不同上下文里有 4 种完全不同的含义,全靠"约定俗成"来区分。

对比 JS :JS 里 _ 只是普通变量名(除非你用 Lodash 库),没有这些"魔法"用法。


7. zip + * 解包实现矩阵转置(终极鬼畜)

写法:

python 复制代码
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]
transposed = list(zip(*matrix))
print(transposed)  # [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

鬼畜在哪?

  • zip 把多个列表"拉链"式合并。
  • *matrix 把列表展开成 3 个独立的列表参数。
  • 两者配合,一行代码完成矩阵转置------简洁得令人发指,但第一次看根本看不懂

对比 JS :JS 需要写嵌套循环或 map 链,至少 3-5 行。


8.作用域for

python 复制代码
for i in students:
    if '老张' in i and '老李' in i:
        print(f'找到这个班级名单那了:{i}')
        third_class_tuple = tuple(i)  # 转换为元组

count_laozhang = third_class_tuple.count('老张')  # 统计次数
index_laoli = third_class_tuple.index('老李')      # 获取索引下标

# 按照预期格式打印结果
print(f'"老张"在元组中出现了 {count_laozhang} 次')
print(f'"老李"在元组中的索引下标是:{index_laoli}')

third_class_tuple明明在for循环里,难道没有作用域?在for循环结束还能使用?

Python 的 for 循环不会创建新的作用域。在 for 里定义的变量,和在外面定义的变量,处于同一个作用域

Python 的作用域规则:

  • 全局作用域(模块级)
  • 函数作用域(def / lambda 内部)
  • 类作用域(class 内部)
  • 推导式作用域(列表推导式、生成器表达式等,Python 3 特有)

注意:for、if、while、try 这些语句块,不会创建新的作用域。

对比一下,可见python的不一样的鬼畜

语言 for 是否创建新作用域 备注
Python ❌ 不创建 循环变量和循环体内定义的变量,都留在外层作用域
Java ✅ 创建 for (int i = 0; ...) 里的 i 只活在循环里
C/C++ ✅ 创建 C99 起支持 for (int i = ...)i 只在循环内有效
JavaScript ✅ 创建(let / const var 不创建,会提升到函数作用域
Go ✅ 创建 for i := ... 里的 i 只在循环内有效

💡 总结:这些"鬼畜"写法的本质

写法 核心逻辑 为什么"鬼畜"
切片赋值 用新数据替换旧切片,长度自动适应 赋值语法居然能改变列表长度
for-else 循环没被 break 才执行 else elseif 无关
链式比较 a < b > c 自动拆成多个比较 数学写法被"硬塞"进编程语言
海象 := 条件里同时赋值和使用 增加了新的运算符,改变了 Python 习惯
*/** 解包 调用时展开列表/字典 同一个符号在定义和调用时含义相反
_ 多重身份 占位符、忽略值、交互式历史、变量名 同一个符号 4 种用法
zip(*matrix) 一行矩阵转置 语法太密集,读起来像密码

这些写法之所以"鬼畜",是因为 Python 的设计哲学是"让代码像英语一样表达意图",而英语本身就是"倒装句 + 省略 + 多义词"的重灾区。 你习惯了就好,而且一旦熟悉了,写起来确实比 JS 省很多行。

如果你有哪一条想让我展开讲的(比如 zip 的底层原理,或者海象运算符的踩坑案例),我可以继续给你细拆。

相关推荐
夜雪一千1 小时前
如何使用Python的BeautifulSoup库来处理HTML
python
傻啦嘿哟1 小时前
某新闻平台爬虫:爬取各频道新闻,分析媒体传播规律
python
鹿角片ljp1 小时前
Prompt Cache、Token 成本与 Plan Compiler 的工程设计
java·python·算法
麻雀飞吧10 小时前
先判断工具用来学习、开发还是执行
人工智能·python
人邮异步社区10 小时前
学习Python的最佳学习路径是什么?
python·程序员
troy12813 小时前
Python 基础语法(九):Django/Flask/FastAPI 三大 Web 框架详细对比解析
python·jupyter·django·flask·github·fastapi
jzshmyt13 小时前
我用 Python 从零“生成“了一个宇宙,然后让它观察自己(v14)
人工智能·pytorch·python·numpy·matplotlib·空间计算·scipy
用户83562907805115 小时前
使用 Python 将 DOCX 转换为 Markdown
后端·python
小玮看世界15 小时前
[Python]ADAS工程实战(三):多传感器扇区统计疑难点全解——归一化、跨边界、去重与置信度
python