Python基础全梳理:从注释到函数,这些细节你都掌握了吗?
今天我们不从头讲语法而是顺着这份笔记的脉络挑出几个高频使用但极易踩坑的细节结合真实场景重新梳理一遍。读完你可能会发现原来我一直用的sort()居然会改原列表replace()竟然不生效*args和**kwargs到底怎么优雅传参一、注释除了“解释代码”还能做文档笔记里简单写了三种形式# 单行注释 多行注释三双引号 多行注释三单引号 必须说清楚和本质上是字符串字面量只是当它们孤立存在、不被赋值或操作时解释器会忽略它们起到了“注释”的效果。但如果你这样写x 我是字符串那它就不是注释了。实用场景函数内部的文档字符串docstring通常用包裹help()能读取它def add(a, b): 返回两个数的和 return a b help(add) # 会显示 返回两个数的和踩坑提醒如果你用注释掉一大段代码而这段代码本身又包含会触发SyntaxError。此时要么改用#逐行注释要么用编辑器快捷键批量加#。二、数据类型一张表理清 Python 内置九大类笔记列出了整数、浮点数、字符串、布尔值、列表、元组、字典、集合、None。类型例子是否可变是否有序整数10不可变-浮点数3.14不可变-字符串hello不可变有序索引布尔值True/False不可变-列表[1,2,3]可变有序元组(1,2,3)不可变有序字典{name:lgl,age:18}可变有序3.7集合{1,2,3}可变无序NoneNone不可变-重点元组的“不可变”是指元素的指向不可变但如果元组内包含列表列表内容可以变t (1, [2,3]) t[1].append(4) # 合法t 变成 (1, [2,3,4])但你不能t[0] 5这会报错。None常被用作“空值”占位比如函数默认返回值就是None。判断时推荐if x is None而非if not x因为后者会把0、[]等也判为 True。三、输出与输入那些你可能没玩过的花样1.print()的进阶用法print(100) # 直接输出值 print(hello world) # 输出字符串 a 10 print(fa{a}) # f-string推荐清晰高效笔记还提到\t制表符、\n换行和end。实际项目里end常用来构建动态刷新效果import time for i in range(101): print(f\r进度{i}%, end, flushTrue) time.sleep(0.05) print() # 换行\r让光标回到行首end阻止自动换行flushTrue强制立即输出——这样你就看到一行进度条在变化。2.input()的“类型陷阱”a int(input(请输入一个整数))这样写没问题但若用户输入abc会抛出ValueError。实战中务必加异常处理try: a int(input(请输入整数)) except ValueError: print(这不是整数请重试)另外input()返回的一律是字符串别忘转型。四、随机数别再死记硬背了import random print(random.randint(1, 100)) # 闭区间 [1,100]包含两端 print(random.uniform(1, 100)) # 浮点数范围 [1,100)文档是 [a,b] 或 [a,b)注意random.uniform(a,b)的端点取决于a和b的大小关系但返回的是a N b若 ab或b N a总之是闭区间。笔记说“不包含1和100”是错误的——实际上uniform是包含两端理论上浮点数精度可能碰巧等于端点但概率极低。大家使用时以官方文档为准。更常用的随机选择random.choice([红,蓝,绿])、random.shuffle(list)等这些笔记没提但实战频繁。五、运算符与布尔逻辑短路效应是关键print(2 ** 3) # 8指数运算 a False b not a # True c a and b # False d a or b # Trueand和or返回的不是布尔值而是最后一个被求值的操作数print(0 and 10) # 0因为 0 为假短路返回 0 print(3 or 0) # 3因为 3 为真短路返回 3这个特性常用于简化逻辑比如x y or 默认值但小心y0时也会被当成假。字符串拼接c Hello World # 用 c Ha * 3 # HaHaHa*可以快速重复字符串但不要用在循环里拼接大量字符串因为字符串不可变每次都会创建新对象效率极低。推荐用.join(list_of_str)。六、控制流if、elif与for的细节if condition: # 缩进 4 个空格 elif other: # ... else: # ...缩进是 Python 的灵魂混用 Tab 和空格会报错现代编辑器都能自动转空格。for循环笔记里写了range(10)表示 09range(1,10)表示 19。range是惰性序列节省内存常与list()搭配转成列表。但for循环可以直接迭代字符串、列表、元组、字典、集合for ch in hello: print(ch) # 迭代字符 for key in d: print(key, d[key]) # 迭代字典键 for value in d.values(): print(value) # 迭代值 for k, v in d.items(): print(k, v) # 同时迭代键值对七、字符串操作不可变别忘赋值笔记里写了切片、replace、split、join。s hello world print(s[0]) # h print(s[1:5]) # ello左闭右开 print(s[1:5:2]) # el步长2 new_s s.replace(l, L) # 返回新字符串 heLLo worLd print(s) # 原字符串不变 parts s.split( ) # [hello, world] joined .join(parts) # hello world金句字符串是“钢铁直男”——任何操作都生成新对象绝不改变自己。永远记得把结果赋值回去。实战场景清洗文本时常用strip()去首尾空白replace去除换行符split按分隔符切分 CSV 数据。八、列表增删改查排序有坑lst [1,2,3] lst.append(4) # 末尾追加 lst.insert(1, 99) # 在下标 1 前插入 99 - [1,99,2,3,4] lst.pop(2) # 删除下标 2 的元素并返回 lst.remove(99) # 删除第一个值为 99 的元素 lst.clear() # 清空排序的陷阱lst [3,1,2] lst.sort() # 修改原列表返回 None # 如果想保留原列表用 sorted() new_lst sorted(lst) # 返回新列表排序支持key和reverse比如按字符串长度排序words [apple, pie, banana] words.sort(keylen, reverseTrue)取下标lst[0]获取第一项lst[-1]获取最后一项。如果下标越界会报IndexError安全方式是用try或先判断长度。九、元组不可变的“列表”用在哪t (1, 2, 3) # t[0] 100 # 报错元组不可变因此哈希可计算可作为字典的键而列表不行。另外函数返回多个值时本质就是元组def get_stats(): return 1, 2, 3 # 自动打包为元组 x, y, z get_stats() # 解包注意单元素元组必须加逗号(1,)否则被当作整数。十、集合去重利器但别指望顺序s {1,2,3,3} # 自动去重 - {1,2,3} s.add(4) s.remove(2) # 集合支持交集、并集等 a {1,2,3} b {2,3,4} print(a b) # {2,3} print(a | b) # {1,2,3,4}集合无序因此不能通过下标访问。如果需要有序去重用dict.fromkeys()或sorted(set(lst))。十一、字典键值对的“瑞士军刀”d {name: lgl, age: 18} print(d.keys()) # dict_keys([name,age]) print(d.values()) # dict_values([lgl,18]) print(d.items()) # dict_items([(name,lgl), (age,18)]) del d[age] # 删除键值对 d.clear() # 清空字典迭代时删除会导致运行时错误安全做法for key in list(d.keys()): if key age: del d[key]或者用字典推导式创建新字典d {k:v for k,v in d.items() if k ! age}默认值d.get(gender, 未知)如果键不存在返回默认值不报错。十二、函数定义、参数、作用域def func(p1, p2, p3): # 函数体 return 结果 pass # 占位什么都不做全局变量在函数内修改全局变量需global声明x 10 def change(): global x x 20 change() print(x) # 20但滥用全局变量会破坏封装建议尽量通过参数和返回值传递。1.*args和**kwargs的正确使用姿势笔记提到了“可变参数”但实战中它们能极大提升灵活性。*args接收任意个位置参数打包成元组。**kwargs接收任意个关键字参数打包成字典。def demo(*args, **kwargs): print(位置参数, args) print(关键字参数, kwargs) demo(1,2,3, namelgl, age18) # 输出 # 位置参数 (1,2,3) # 关键字参数 {name:lgl,age:18}高阶用法将已有的列表/字典“解包”传递params {name:lgl, age:18} def show(name, age): print(f{name} is {age}) show(**params) # 等价于 show(namelgl, age18) nums [1,2,3] def add(a,b,c): return abc add(*nums) # 等价于 add(1,2,3)注意参数名必须匹配否则TypeError。十三、综合实战把笔记里的代码串起来笔记末尾有一段示例代码a 10 print(a) print(fa{a}) a int(input(请输入一个整数)) print(a) print(type(a)) import random print(random.randint(1,100)) print(random.uniform(1,100))我们可以把这些揉进一个随机数猜谜游戏涵盖输入、类型转换、条件、循环、随机数和函数import random def guess_game(): target random.randint(1, 100) attempts 0 while True: try: guess int(input(猜一个 1~100 的整数)) except ValueError: print(请输入有效整数) continue attempts 1 if guess target: print(太小了) elif guess target: print(太大了) else: print(f恭喜用了 {attempts} 次猜中) break if __name__ __main__: guess_game()这个例子用到了random.randint、input、int转型、try-except、if-elif-else、while、break、函数定义、if __name__保护——几乎覆盖了笔记所有核心语法。最后你的基础是否经得起“拷问”我们重新走了一遍笔记但重点始终放在那些“你以为你知道实际可能错”的细节上。下面整理一份快速自查清单你可以逐条过一遍我是否清楚是字符串而非真正的注释我是否会在input后立即转型而不做异常处理我是否知道random.uniform是闭区间理论我是否明白and/or返回的是操作数而非布尔值我是否习惯用.join()而不是拼接大量字符串我是否把s.replace()的结果重新赋值了我是否知道sort()返回None且修改原列表而sorted()返回新列表我是否能在循环中安全删除字典元素我是否会用*args和**kwargs解包传参我是否清楚元组不可变但内部列表可变的特性如果每一项你都能自信点头那么恭喜——你的基础真正“毕业”了。如果有一些模棱两可不妨回头再翻翻对应章节。技术之路不怕慢就怕“我以为”。笔记是死的但代码是活的。多写、多调试、多复盘把每一个“知道”变成“做到”才是进阶的唯一捷径。