在这里插入图片描述

摘要

刚学Python的时候,很多人都会遇到一个很尴尬的问题:代码能跑,但是写得像流水账。比如要打印5次“我错了”,就真的复制粘贴5行print。这种写法不仅看着累,以后要改个字还得改5次。其实Python早就给我们准备好了“偷懒”的工具——循环和数据容器。这篇笔记就用一个运维/开发同学的日常视角,聊聊怎么用while、for和各种容器(字符串、列表)把重复劳动交给电脑,让自己早点下班。

引言

现在的业务场景里,不管是写自动化脚本,还是处理日志、批量操作用户数据,都离不开两样东西:一是让程序反复干活的循环,二是能一把抓一堆数据的容器。比如服务器监控要一直跑(循环),日志文件一行行读出来存到列表里(容器)。搞懂这两个,你写的就不叫脚本了,叫工具。

循环语句:让电脑替你干重复的活

什么是循环

说白了,循环就是让电脑“照着模板反复做”。
比如老师说“把这个词抄10遍”,你脑子里知道这是一件事,只是重复10次。程序也一样。

生活中的例子:

  • 抄单词10遍 → 我知道次数(用for)
  • 往杯子里倒水直到满 → 我不知道倒几次,看情况(用while)

如果不用循环,代码是这样的:

print('今天是我不对')
print('今天是我不对')
print('今天是我不对')
# ... 抄到第10遍手都酸了

用了循环,世界都清净了:

# 抄10遍
for i in range(10):
    print('今天是我不对')

在这里插入图片描述

while循环:不知道要跑多久的时候用它

while的核心逻辑很简单:只要条件成立,就一直干

执行逻辑:

  1. 先看条件
  2. 条件为真,干活
  3. 干完活回来再看条件
  4. 条件为假,收工
基础写法
# 从1数到5
i = 1
while i <= 5:
    print(f'这是第 {i} 次')
    i += 1  # 别忘了这一步,不然就死循环了
print('数完了')
实际场景一:模拟用户登录

真实场景里,我们不知道用户第几次能输对密码,所以用while。

# 模拟登录,直到密码正确
while True:
    pwd = input('请输入密码:')
    if pwd == 'admin':
        print('密码正确,登录成功')
        break  # 输对了就跳出循环
    else:
        print('密码错误,再试一次')

代码解读:

  • while True 代表一直循环。
  • 如果输对了,用 break 强制结束,不然它就一直问你要密码。
  • 这种方式非常适合“等待某个状态发生”的场景,比如等服务器启动、等文件出现。
实际场景二:定时任务提醒

比如写个脚本,每隔3秒提醒女朋友别生气(慎用,可能会被拉黑)。

import time

while True:
    print('别生气了,我错了')
    time.sleep(3)  # 程序暂停3秒

代码解读:

  • time.sleep(3) 是让CPU歇会儿,不然你的电脑风扇会狂转。
  • 这种“死循环”常用于监听消息、监控系统状态。

在这里插入图片描述

for循环:知道要干几次,或者有一堆东西要挨个处理

for循环在Python里有个外号叫“遍历神器”。它最适合干两件事:

  1. 干固定次数的活(for i in range(10))。
  2. 把一堆数据挨个拿出来处理(遍历列表、字符串)。
基础写法
# 遍历字符串
for ch in "itheima":
    print(ch)
# 输出:i t h e i m a
range函数的用法

range就是帮你生成一个数字队列。

  • range(5) -> 0,1,2,3,4 (注意:不含5)
  • range(1, 5) -> 1,2,3,4
  • range(1, 10, 2) -> 1,3,5,7,9 (步长为2)
实际场景三:批量处理用户数据

假设我们有10个用户ID,要给每个人发优惠券。

# 模拟给前5个用户发券
for user_id in range(1, 6):
    print(f'正在给用户 {user_id} 发放优惠券...')
print('发券完毕')
实际场景四:九九乘法表(经典练手)

这个例子能很好地理解双层循环。外层控制行,内层控制列。

# 打印九九乘法表
for row in range(1, 10):
    for col in range(1, row + 1):
        print(f'{col}×{row}={col*row}', end='\t')
    print()  # 打完一行换一行

代码解读:

  • 外层 row 决定现在是第几行。
  • 内层 col 决定这一行有几列。比如第3行,就有3列。
  • end='\t' 是为了不让print自动换行,用制表符隔开。

break和continue:循环的刹车和跳板

  • break:直接熄火,整个循环结束。
  • continue:本次算了,直接进入下一轮。
场景:寻找第一个能被7整除的数
i = 1
while True:
    if i % 7 == 0:
        print(f'找到了:{i}')
        break  # 找到就走人,不用再看后面的了
    i += 1
场景:跳过讨厌的数字

打印1到10,但是不想看到5。

for i in range(1, 11):
    if i == 5:
        continue  # 跳过5,后面的print这次就不执行了
    print(i)

数据容器:装数据的篮子

字符串:文本处理的万金油

字符串其实就是一串字符。在Python里,它是最常用的容器之一。

常用操作

去掉两边空格(处理用户输入必用):

username = input("用户名:")  # 用户不小心输了空格
username = username.strip()  # 把头尾空格干掉
print(f'欢迎 {username}')

大小写转换(验证码校验):

code = 'AbC3'
user_input = 'aBc3'
# 统一转小写再比较,防止用户大写小写混着输
if code.lower() == user_input.lower():
    print('验证码正确')

查找和替换(日志分析常用):

log = "ERROR: File not found"
# 看看日志里有没有ERROR
if log.find('ERROR') != -1:
    print('发现错误日志!')

# 把敏感词替换掉
text = "这傻逼真烦"
safe_text = text.replace('傻逼', '**')
print(safe_text)

切片(截取想要的部分):
字符串就像一根香肠,切片就是切香肠。

path = "/user/home/file.txt"
# 只要文件名
filename = path[-8:]  # 取最后8个字符
print(filename)

# 反转字符串(有时候挺有用)
word = "Python"
print(word[::-1])  # nohtyP

列表:最灵活的数据仓库

如果你有一堆同类型的东西(比如全班同学的名字),用变量一个个存太傻了,用列表。

定义和基本操作
# 定义列表
names = ['张三', '李四', '王五']
print(names[0])  # 张三(索引从0开始)

# 增加
names.append('赵六')  # 在末尾加
names.insert(1, '田七')  # 插到第二个位置

# 删除
names.remove('李四')  # 移除指定元素
del names[0]  # 删除第一个

# 修改
names[0] = '张三丰'

# 查询
if '王五' in names:
    print('王五在名单里')
实际场景一:黑名单IP拦截

写一个简单的防火墙逻辑,检查来访IP是否在黑名单里。

black_ips = ['192.168.1.100', '10.0.0.5', '172.16.0.8']
visit_ip = '10.0.0.5'

if visit_ip in black_ips:
    print(f'IP {visit_ip} 已被封禁,拒绝访问!')
else:
    print(f'IP {visit_ip} 允许访问。')
实际场景二:解析日志文件

假设我们有一段Nginx日志,想提取出所有的IP地址。

logs = """
192.168.1.1 - - [GET]
10.0.0.2 - - [POST]
192.168.1.1 - - [GET]
"""

ip_list = []
# 按行分割
for line in logs.strip().split('\n'):
    # 按空格分割,取第一个元素就是IP
    ip = line.split(' ')[0]
    ip_list.append(ip)

print(f'提取出的IP列表:{ip_list}')
# 统计访问次数
print(f'192.168.1.1 访问了 {ip_list.count("192.168.1.1")} 次')
列表的遍历
heroes = ['貂蝉', '大乔', '小乔']
for hero in heroes:
    print(f'正在加载英雄:{hero}')
列表嵌套

处理更复杂的数据结构,比如年级->班级->学生。

# 三层列表嵌套:年级 -> 班级 -> 学生
school = [
    ['张三', '李四'],  # 一班
    ['王五', '赵六'],  # 二班
    ['田七', '钱八']   # 三班
]

# 找二班的王五
print(school[1][0])  # 先拿第二个班(索引1),再拿班里第一个人(索引0)

# 遍历全校学生
for class_room in school:
    for student in class_room:
        print(f'学生姓名:{student}')

QA环节

Q:什么时候用while,什么时候用for?
A:简单记,数得清次数用for(比如循环10次、遍历一个列表);数不清次数用while(比如一直等用户输入、一直监控某个端口直到它打开)。

Q:字符串和列表有什么区别?
A:最大的区别是字符串一旦定下来就不能改(不可变),比如你把字符串里的’a’换成’b’,其实是生成了一个新的字符串。而列表是可以随便改的(可变),可以直接在原来的列表上加人减人。

Q:break和continue在多层循环里怎么生效?
A:它们只管自己这一层循环。比如你在内层循环写了break,只会跳出内层循环,外层循环还会继续跑。如果想一下子全停掉,可能需要配合标志位或者把循环封装成函数用return。

Q:range(5)为什么是0-4?
A:这是编程界的传统艺能了,叫“零基索引”。习惯了就好,主要是为了方便计算机底层计算偏移量。记住一句话:含头不含尾。

总结

今天我们聊了Python里的两个核心概念:循环和数据容器。

  • 循环(while/for)解决了“重复劳动”的问题,让我们能用几行代码搞定成千上万次的运算。
  • 数据容器(字符串、列表)解决了“数据打包”的问题,让我们能优雅地管理一堆杂乱的信息。

在实际工作中,这两者往往是组合使用的。比如用while一直盯着日志文件,用for循环逐行读取内容,再用字符串的方法提取IP,最后放进列表里做统计。把这些基础打牢,后面学爬虫、Web开发或者数据分析,都会轻松很多。

更多推荐