尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python变量与运算符深度解析:从内存绑定到实战避坑
如果你跟着这个系列一路走到了Day2说明本地环境多半已经装好了也至少敲过几行print(Hello, world)。今天要聊的“变量”和“运算符”不是说其实比打印字符串重要得多——它们是程序表达逻辑的最小单元几乎所有代码都在做的无非是把数据存进变量再用运算符把它们组合起来。很多人学到后面觉得Python“玄”回头想想多半是这一天没有真正钻透。所以这一篇我尽量把底层逻辑、常用写法、还有我这些年踩过的坑都揉碎了一起讲希望能帮你把这个地基打牢一点。1. 变量到底是什么从内存到标签1.1 变量是名字不是盒子我见过太多新手朋友一开始就抱着“变量是一个盒子里面装着值”的想法去学Python。这个类比在C语言里勉强能用但在Python里会害人。Python的变量更准确的说法是“贴到对象上的标签”或者“指向对象的名字”。举个例子当你写下a 42实际发生的事情是Python先创建了一个整数对象42然后把名字a绑定到它身上。如果你接着执行a helloPython不是把原来的数字改成字符串而是新创建了一个字符串对象hello然后把a这个标签撕下来贴到新对象上。原来的整数42如果没有别的标签引用会被垃圾回收机制在合适的时候清理掉。理解这一点有什么好处你会很自然地理解为什么Python不需要声明变量的类型因为变量本身没有类型它只是名字是对象才有类型。你也会理解为什么说“变量是动态类型”因为同一个名字可以先后绑定到不同类型的对象上。1.2 用id()和type()看穿赋值动手验证一下会非常直观。打开终端敲这几行 a 42 id(a) 140736522489360 a hello id(a) # 这个地址和上面完全不同 140736521823280 type(a) class strid()返回的是对象在内存中的唯一标识可以粗略理解为地址。连续两次id(a)不一样说明两次a指向的根本是两个不同对象。这就是“绑定标签”模型和“盒子”模型最本质的区别。再来看一个常见的困惑x [1, 2, 3] y x y.append(4) print(x) # [1, 2, 3, 4]如果在“盒子”视角下你会觉得我在复制一个列表给y改y不该动x。但在“标签”视角下x和y两个名字指向同一个列表对象通过y修改列表内容x看到的当然也是修改后的列表。1.3 赋值语句不会复制对象说到底Python的就是绑定不是拷贝。如果你真的想复制一个列表要用y x.copy()或者y x[:]把“复制”这件事显式表达出来。很多Bug的根源都出在这个地方——你以为你复制了其实只是多贴了个标签。后面你还会碰到可变对象和不可变对象的概念到时候再回头看这一节会有更深的体会。现在只需要记牢两句话变量是标签赋值是绑定。2. 变量命名的门道与“潜规则”2.1 合法命名规则一句话记住变量名只能由字母、数字和下划线组成不能以数字开头不能是Python关键字。大小写敏感Name和name是两个完全不同的变量。新手常犯的错误就是“以数字开头”比如1var 10 # 语法错误还有一类错误是用关键字做变量名class math # 语法错误想快速查看所有Python关键字在终端输入python -c import keyword; print(keyword.kwlist)你会发现居然有35个左右版本不同略有差异包括if、for、while、True、False、None等。看到True和False也是关键字就知道不能把它们当变量名了。2.2 命名规范不只是为了好看合法只是底线真正写起来还要考虑可读性。Python官方风格指南PEP 8建议变量名用小写字母加下划线即snake_case风格。比如student_name好于studentnameis_valid好于validnum_students好于ns大多数Python程序员都遵守这套规范你写出来的代码别人看起来会很舒服自己过两个月再回来看也不会一头雾水。另外要特别注意“不要覆盖内置名称”。Python内置了一堆常用名字比如list、dict、str、int、input。如果一个人写了list [1, 2, 3]接下来他再写list(abc)想创建列表的时候就会报TypeError: list object is not callable因为list这个名字已经指向了一个列表对象指向原来内置函数的那条标签已经被覆盖了。我自己的习惯是如果确实需要一个列表变量尽量起items、numbers、names这类名字别直接用list。同样的道理也别用sum、min、max这些内置函数名。这算是一条用“花式报错”换来的血泪经验。3. 变量赋值一个“”里面有文章3.1 链式赋值与多元赋值Python支持把多个赋值放在一行最基础的是链式赋值a b c 0这行代码的本质是先把0创建出来然后依次让a、b、c都绑定到它身上。从标签模型来看非常好理解一张便利贴不够就多贴几张。更常用的是多元赋值x, y 10, 20逗号分隔变量的语法看起来很简单但背后其实是元组解包。(10, 20)是元组Python会把这个元组拆开把第一个元素给x第二个给y。因此你可以写出非常优雅的交换变量操作a 1 b 2 a, b b, a print(a, b) # 2 1不用临时变量一行搞定。这种方式在C这种语言里想都不敢想在Python里却非常自然。注意这里的执行顺序Python会先计算右边的表达式也就是(b, a)这个元组然后再做解包赋值所以不存在“先改了a导致b拿不到”的问题。3.2 增量赋值的可变对象陷阱a 1其实就是a a 1的简写这个说法在“数字、字符串”这种不可变对象上完全正确。但在“列表”这类可变对象身上两条语句有微妙差别。看一个经典例子a [1, 2] b a a [3] print(a) # [1, 2, 3] print(b) # [1, 2, 3] b也变了但如果换成a [1, 2] b a a a [3] print(a) # [1, 2, 3] print(b) # [1, 2] b没有变怎么回事因为对于列表这个可变对象执行的是就地修改extend它没有改变a这个标签指向的对象还是原来那个列表。而a a [3]会先创建一个新的列表对象然后把a重新绑定到新对象上因此b仍然指向旧对象。这个知识点是很多面试题的最爱也是平时写代码容易踩的隐含坑。知道原理之后遇到“为什么我临时保存的列表被改了”这种问题你就有排查方向了。4. 运算符的超全拆解与应用场景4.1 算术运算符不只是四则运算Python常用的算术运算符有这么几个、-、*、/、//、%、**。除了加减乘有几个地方需要特别留意。首先是除法。在很多语言里7 / 2会得到3整数除以整数得整数但Python不是只要用了/结果一定是浮点数print(7 / 2) # 3.5 print(4 / 2) # 2.0 # 注意即使能整除也是浮点数如果我想得到整数结果用//整除。但这里有一个不少新手会算错的细节向下取整还是向零取整。Python的//是向下取整也就是结果偏向负无穷print(7 // 2) # 3 print(-7 // 2) # -4 # 不是-3因为 -3.5 向下取整为 -4再看取余数%。大多数人知道7 % 3是1但负数取余的结果容易懵print(-7 % 3) # 2为什么是2因为%的结果必须满足被除数 除数 * 商 余数而且Python规定余数的符号和除数符号一致。-7 3 * (-3) 2所以余数是2。没有这个意识写日期计算或者循环偏移量的时候会莫名出Bug。幂运算符是**比如2 ** 10得到1024。它比乘法优先级高得多后面细说。4.2 比较运算符链式比较是个宝藏比较运算的主要有、!、、、、。它们做的事情很直观但有两个点值得展开。一是字符串比较是按字典序逐字符比较通常是基于ASCII或Unicode码点。比如apple banana # True因为 a 在 b 前面 a B # False因为小写字母的码点比大写字母大在整理用户输入、做排序逻辑时要意识到大小写会影响比较结果。二是Python支持链式比较score 85 print(60 score 100) # True这个写法展开就是60 score and score 100但更简洁也更符合自然语言习惯。很多其它语言不支持这种写法Python里可以放心用。4.3 逻辑运算符的“短路求值”逻辑运算符and、or、not有一个非常重要的行为短路求值。还记得条件表达式吗and从左到右计算只要遇到假值就停下来不再计算后面的or遇到真值就停下来。这意味着写0 and 5 // 0不会报除零错误因为0已经是假值后面的5 // 0根本不会执行。同理1 or 5 // 0也不会报错。更实用的是or在默认值设置中的用法name input(请输入昵称) or 匿名用户如果用户什么都没输入input()返回空字符串空字符串是假值所以or会返回后面的匿名用户。这就是一种很Pythonic的写法。还有一点要记牢and和or返回的是参与运算的对象而不是布尔值。比如print(2 and 3) # 3 print(0 or x) # x只有not才总是返回布尔值比如not 2是False。很多人在初学阶段会被“3”这个结果吓到其实只要记住“短路到哪儿就返回哪儿”这句话就够了。4.4 成员运算符与身份运算符in和not in用来判断一个元素是否在某个容器里print(3 in [1, 2, 3]) # True print(e in hello) # True print(x not in {a: 1}) # True因为字典默认判断键is和is not判断的是两个名字是否指向同一个对象而判断的是两个对象的值是否相等。注意区分用途a [1, 2, 3] b [1, 2, 3] print(a b) # True print(a is b) # False内容相同但不是同一个对象不过在Python的小整数缓存机制下会出现一个经典现象a 256 b 256 print(a is b) # True因为小整数对象被缓存了 a 257 b 257 print(a is b) # False不同的对象所以我的建议是永远不要用is来比较数值或字符串内容只用is来判断单例比如x is None。5. 运算符优先级与表达式的综合性理解5.1 优先级速记与括号主义一个表达式里同时有算术、比较、逻辑运算符时Python按照一套固定的优先级来解析。从高到低可以粗略记为**幂运算x、-x一元正负号*、/、//、%、-、!、、、、、is、innotandor比如这个表达式result not 5 3 or 2 * 4 8 and a in abc按照优先级先算5 3得到True、2 * 4得到8、a in abc得到True。于是变成not True or 8 8 and True再算8 8得到True变成not True or True and True。and先算得到True再算not True得到False最后False or True得到True。看着头晕对吧我给你的建议不是把这张表背下来而是重要表达式加括号别让读代码的人猜。比如上面这个完全可以写成result (not (5 3)) or ((2 * 4 8) and (a in abc))效果一样但可读性不知道高到哪里去了。写代码本来就该尽量让逻辑一目了然而不是炫耀对优先级的记忆力。5.2 中括号不是可选项要用括号的地方一定要写。最常见的悲剧就是“按位与”和“逻辑与”混用。是按位运算符and是逻辑运算符优先级不同。比如a 3 b 5 print(a b) # 1 # 按位运算 print(a and b) # 5 # 逻辑运算签名不同结果也完全不同。初学阶段我会建议你先别碰位运算专注于逻辑运算符。等到后面做权限标记、图像处理时再回头学位运算也来得及。6. 动手实战用变量和运算符写三个小工具6.1 温度转换器需求很简单输入摄氏温度输出华氏温度。公式是F C * 9 / 5 32。celsius float(input(请输入摄氏温度: )) fahrenheit celsius * 9 / 5 32 print(f对应的华氏温度为: {fahrenheit:.2f})这里有几个关键点。第一input()拿到的一定是字符串不能直接和数字相乘所以要用float()转成浮点数。第二9除以5在Python里得到的是1.8所以celsius * 9 / 5没问题。如果你想用整数写法可以写celsius * 9 // 5 32但负数场景下不行因为//是向下取整所以老老实实用除法最稳。第三f-string里的:.2f表示保留两位小数输出更干净。一个小坑如果用户输入了abcfloat()会直接抛出ValueError初学者经常在这里崩溃。可以先不处理异常后面学到try / except再回来补。6.2 计算商品折扣价假设一件商品原价price店铺折扣是discount比如0.8表示八折满100减20简易计算最终价格price float(input(请输入商品原价: )) discount float(input(请输入折扣如0.8表示八折: )) final_price price * discount if final_price 100: final_price final_price - 20 print(f最终应付: {final_price:.2f})这里开始用到比较运算符和if语句恰好把变量和运算符串起来了。要注意final_price final_price - 20这种“拿新值覆盖旧值”的写法非常常见不要嫌啰嗦更不要写成final_price - 20那只是算了个结果却没保存。顺便说一句如果你希望满100减20的逻辑满足“每满100减20”而不是“只要满100就只减一次”那就需要更复杂的运算符组合和循环了。留给读者自己思考一下把它当作一个扩展练习。6.3 计算BMI指数BMI的公式是体重除以身高的平方体重单位千克身高单位米。代码长这样weight float(input(请输入体重kg: )) height float(input(请输入身高m: )) bmi weight / (height ** 2) print(f你的BMI指数是: {bmi:.1f}) if bmi 18.5: print(偏瘦) elif bmi 24: print(正常) elif bmi 28: print(偏胖) else: print(肥胖)这里用到了幂运算符**。注意height ** 2的优先级高于除法和乘法所以理论上weight / height ** 2直接写也没问题但为了不产生歧义我加了括号这种习惯在复杂表达式里能给未来的自己省不少事。判断区间时我从最左边开始逐层收缩这种写法比写成18.5 bmi 24再24 bmi 28更简洁也避免前后不一致。实际项目里经常能见到这种“从小到大判断”的模式。7. 常见报错与实战避坑指南7.1 NameError名字都没定义最常见的报错是NameError: name x is not defined。出现这个报错的原因很简单名字还没绑定到对象上就被使用了。可能是变量名拼错了也可能是赋值语句没执行到。排查顺序我一般是这样先看变量名有没有拼写错误再看是不是在函数内部使用了函数外部的局部变量作用域问题最后看是不是赋值语句缩进错了导致根本没有执行。新手十有八九是拼写错误比如前面定义的是uname后面用成了user_name两个名字没有任何关系。7.2 TypeError运算符和数据类型不匹配TypeError是初学者频发的高频错误。最常见的一段代码是age input(请输入年龄: ) print(明年你 age 岁)报错信息大概是TypeError: can only concatenate str (not int) to str重点在于“字符串只能拼接字符串不是整数”。你输入进来的age是字符串而明年你是字符串岁也是字符串中间的age也必须先转成字符串。解决方案是print(明年你 str(age) 岁)或者干脆用f-stringprint(f明年你{age}岁)反过来如果你试图让字符串和整数做算术运算也会得到类似的错误。Python不会自动帮你把123转成123这点和JavaScript完全不同。遇到TypeError先检查类型用type()打印一眼你就有数了。7.3 ZeroDivisionError被零除的灾难除数是0在算术上不合法Python会直接报ZeroDivisionError。代码里如果存在用户输入的值你没有做任何校验就直接做除法很容易踩雷。可以通过if判断来避免total int(input(请输入总数: )) count int(input(请输入数量: )) if count 0: print(数量不能为0) else: avg total / count这种“先判断再运算”的习惯在写任何可能触发异常的逻辑时都值得培养。7.4 运算符混淆重灾区与的混淆可能是所有初学Python的人都会经历的阶段。是赋值是把右边的值绑定给左边的名字是比较是判断两边是否相等。写if x 1:会直接报语法错误这算是一种保护吧。但写成if x 1就对了。/与//的混淆也很常见。在只有两个整数需要整除的场景下忘写一个/得到的结果可能是3而不是3.5丢掉了小数部分。同理在某些业务里“取整”到底该向下取整还是向零取整必须想清楚不能瞎用//。and与、or与|的混淆在进阶阶段会碰到之前已经说过了。总之看到结果出乎意料先想想自己用的运算符是不是真正想用的那一个。8. 一些练习思路和后续扩展把这一天的内容吃透光看是不够的。我建议你可以做以下几组练习每组的侧重点都不同。第一组练习变量交换和多元赋值。把任意两个数值交换位置分别用临时变量法和Python特有的一行交换法各实现一次然后打印id()看看前后发生了什么变化。第二组练习字符串和数字的混合运算。写一个“加法计算器”让用户输入两个数字输出它们的和、差、积、商、整除结果和余数。注意一定要用float()转换输入然后观察各种运算符的结果差异。第三组练习逻辑判断。写一个“闰年判断器”闰年的规则是“能被4整除但不能被100整除或者能被400整除”。这个规则正好可以用到%、and、or和比较运算符是最经典的练习题之一。完成后你再回头看这一篇会发现所有知识点都串起来了。变量和运算符就是Python大厦的砖头和水泥把它们搞明白后面学if、for、函数、类都会顺畅得多。如果你在练习时发现了什么有意思的坑或者对某个运算符的行为有疑惑建议先动手写几行代码验证一遍比看十遍教程都管用。编程这东西最终还是要靠手上见真章。
RELATED

相关推荐

智谱GLM-5发布:开源最强,中国芯适配,编程对齐Claude Opus 4.5,TaoToken统一Key接入实测

智谱GLM-5发布:开源最强,中国芯适配,编程对齐Claude Opus 4.5,TaoToken统一Key接入实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/10 0:09:09
C++手写DBMS内核:从B+树到TPC-C的完整实现路径

C++手写DBMS内核:从B+树到TPC-C的完整实现路径

简介:本资源是全国大学生计算机系统能力大赛数据库管理系统赛道的完整参赛项目,面向系统软件方向本科生与数据库内核学习者,聚焦关系型数据库从零实现的核心能力训练。项目基于RMDB框架构建支持TPC-C基准测试的全功能RDBMS,覆盖存…

📅 2026/10/10 0:09:09
顺序、并行、辩论、会商:OpenMAIC 四种交互模式背后的编排逻辑

顺序、并行、辩论、会商:OpenMAIC 四种交互模式背后的编排逻辑

顺序、并行、辩论、会商:OpenMAIC 四种交互模式背后的编排逻辑 【免费下载链接】OpenMAIC Open Multi-Agent Interactive Classroom — Get an immersive, multi-agent learning experience in just one click 项目地址: https://gitcode.com/GitHub_Trending/op/…

📅 2026/10/10 0:09:09
MORE NEWS

更多资讯

📰

AI让数学再也回不去那个旧世界了。

昨天早上,可能会是人类时代的一个分水岭。 以至于这篇文章,在我即使有提前做了大量功课,有一定的知识储备的情况下,还是写了整整一天的时间,完稿时间是今天的凌晨6点15,无他,还是因为这个事件的…

📰

Python Java PHP底层对比:内存并发性能全解析

1. 为什么突然想聊这个话题最近在群里看到不少朋友争论“到底该学 Python 还是 Java”,还有人问 PHP 是不是真的不行了。说实话,这类问题很难用一句话回答,因为三个语言背后的设计思路差别挺大。今天不打算站队,就单纯从底层实现的…

📰

P1185 绘制二叉树【洛谷算法习题】

P1185 绘制二叉树 网页链接 P1185 绘制二叉树 题目描述 二叉树是一种基本的数据结构,它要么为空,要么由根结点,左子树和右子树组成,同时左子树和右子树也分别是二叉树。 当一颗二叉树高度为 m−1m-1m−1 时,共有…

📰

一次性贴身服饰的三层洁净工艺:水洗、灭菌与面料抑菌的技术实现

一次性贴身服饰的三层洁净工艺:水洗、灭菌与面料抑菌的技术实现 一次性内裤、一次性内衣这类贴身服饰,很多人简单认为 “灭菌 洁净”。实际在生产现场,洁净度是一套多工序协同的结果。一次性产品和普通纺织品最大区别:普通衣物的…

📰

BSP 调试#01:点亮 LED

调试前 调试前需要大概了解下面几点知识: (1)Linux系统 在 Linux 系统中,绝大多数硬件设备都拥有成熟的驱动框架; 驱动工程师基于这些框架开发适配特定硬件板卡的驱动程序,从而建立硬件与 Linux 内核之间的…

📰

高级表单能力

6.6 高级表单能力高级表单能力是面向复杂业务场景的表单扩展技术体系,覆盖富文本内容创作、动态字段配置、无障碍可访问性三个核心维度,解决基础表单无法满足的内容编辑、动态业务、普惠可访问等高阶需求,是工业级复杂表单的标准能力集合。6.…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬