一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Python基础全梳理:从注释到函数 这些细节你都掌握了吗?

时间:2026-07-19 09:03:49 编辑:袖梨 来源:一聚教程网

今天我们不从头讲语法,而是顺着这份笔记的脉络,挑出几个高频使用但极易踩坑的细节,结合真实场景重新梳理一遍。读完你可能会发现:原来我一直用的 sort() 居然会改原列表?replace() 竟然不生效?*args 和 **kwargs 到底怎么优雅传参?

Python基础全梳理:从注释到函数,这些细节你都掌握了吗?


一、注释:除了“解释代码”,还能做文档

笔记里简单写了三种形式:

 复制代码# 单行注释
"""
多行注释(三双引号)
'''
多行注释(三单引号)
'''

必须说清楚""" 和 ''' 本质上是字符串字面量,只是当它们孤立存在、不被赋值或操作时,解释器会忽略它们,起到了“注释”的效果。但如果你这样写:

 复制代码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(f'a={a}')                 # f-string,推荐!清晰高效

笔记还提到 t(制表符)、n(换行)和 end=''。实际项目里,end 常用来构建动态刷新效果:

 复制代码import time
for i in range(101):
    print(f'r进度:{i}%', end='', flush=True)
    time.sleep(0.05)
print()  # 换行

r 让光标回到行首,end='' 阻止自动换行,flush=True 强制立即输出——这样你就看到一行进度条在变化。

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(若 a<=b)或 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      # True

and 和 or 返回的不是布尔值,而是最后一个被求值的操作数

 复制代码print(0 and 10)  # 0,因为 0 为假,短路返回 0
print(3 or 0)    # 3,因为 3 为真,短路返回 3

这个特性常用于简化逻辑,比如 x = y or '默认值',但小心 y=0 时也会被当成假。

字符串拼接:

 复制代码c = 'Hello' + ' ' + 'World'   # 用 +
c = 'Ha' * 3                  # 'HaHaHa'

* 可以快速重复字符串,但不要用 + 在循环里拼接大量字符串,因为字符串不可变,每次 + 都会创建新对象,效率极低。推荐用 ''.join(list_of_str)


六、控制流:ifelif 与 for 的细节

 复制代码if condition:
    # 缩进 4 个空格
elif other:
    # ...
else:
    # ...

缩进是 Python 的灵魂,混用 Tab 和空格会报错,现代编辑器都能自动转空格。

for 循环笔记里写了 range(10) 表示 09,range(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)        # 同时迭代键值对

七、字符串操作:不可变,别忘赋值

笔记里写了切片、replacesplitjoin

 复制代码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(key=len, reverse=True)

取下标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, name='lgl', age=18)
# 输出:
# 位置参数: (1,2,3)
# 关键字参数: {'name':'lgl','age':18}

高阶用法:将已有的列表/字典“解包”传递:

 复制代码params = {'name':'lgl', 'age':18}
def show(name, age):
    print(f'{name} is {age}')
show(**params)  # 等价于 show(name='lgl', age=18)nums = [1,2,3]
def add(a,b,c):
    return a+b+c
add(*nums)  # 等价于 add(1,2,3)

注意:参数名必须匹配,否则 TypeError


十三、综合实战:把笔记里的代码串起来

笔记末尾有一段示例代码:

 复制代码a = 10
print(a)
print(f'a={a}')a = int(input('请输入一个整数:'))
print(a)
print(type(a))import random
print(random.randint(1,100))
print(random.uniform(1,100))

我们可以把这些揉进一个随机数猜谜游戏,涵盖输入、类型转换、条件、循环、随机数和函数:

 复制代码import randomdef 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} 次猜中')
            breakif __name__ == '__main__':
    guess_game()

这个例子用到了 random.randintinputint 转型、try-exceptif-elif-elsewhilebreak、函数定义、if __name__ 保护——几乎覆盖了笔记所有核心语法。


最后:你的基础,是否经得起“拷问”?

我们重新走了一遍笔记,但重点始终放在那些“你以为你知道,实际可能错”的细节上。下面整理一份快速自查清单,你可以逐条过一遍:

  • 我是否清楚 """ 是字符串而非真正的注释?
  • 我是否会在 input 后立即转型而不做异常处理?
  • 我是否知道 random.uniform 是闭区间(理论)?
  • 我是否明白 and / or 返回的是操作数而非布尔值?
  • 我是否习惯用 ''.join() 而不是 + 拼接大量字符串?
  • 我是否把 s.replace() 的结果重新赋值了?
  • 我是否知道 sort() 返回 None 且修改原列表,而 sorted() 返回新列表?
  • 我是否能在循环中安全删除字典元素?
  • 我是否会用 *args 和 **kwargs 解包传参?
  • 我是否清楚元组不可变但内部列表可变的特性?

如果每一项你都能自信点头,那么恭喜——你的基础真正“毕业”了。如果有一些模棱两可,不妨回头再翻翻对应章节。

技术之路,不怕慢,就怕“我以为”。  笔记是死的,但代码是活的。多写、多调试、多复盘,把每一个“知道”变成“做到”,才是进阶的唯一捷径。

热门栏目