资讯详情

Python基础练习:注释与标识符的规范与避坑指南

📅 2026/10/10 12:09:35 | 华诺云谱 👁 阅读
Python基础练习:注释与标识符的规范与避坑指南
我见过太多初学者学Python第一个星期就开始啃列表、字典、函数结果一写项目就乱套变量名叫a、b、c代码里一句注释都没有过两周自己都看不懂自己写的什么。最后跑回来问我怎么回事其实根子不在知识量不够而在最开始的基础没打牢。所以我一直觉得学编程的前几课不应该急着去写功能而应该先搞清楚游戏规则。作为python基础练习系列的第一篇我选了注释和标识符这两个看似最简单的题目因为它们是代码质量的起点也是从会敲代码走向会写代码的第一道门槛。这一篇我会把这两块掰开揉碎讲清楚注释不只是给代码加说明文字它有四种完全不同的写法各自承担不同的职责标识符更不只是起名字它藏着Python这门语言对命名的一整套约束和审美。学完之后你会明白为什么有的代码一跑就报SyntaxError为什么有的变量名看着就别扭以及怎么命名才算是Pythonic。1. 为什么第一个练习要从注释和标识符开始1.1 这两个概念在整个Python学习中的定位很多人觉得注释和标识符太简单不值得单独拿一篇出来讲。恰恰相反它们是之后所有代码的地基。你想想看后面学变量、学函数、学类哪一样离得开命名你写的每一行代码都在用标识符而项目一旦超过几百行没有任何一个正常人能全靠记忆理解自己当初的思路——这时候注释就是你的外置大脑。从语言设计角度看Python本身也是一门非常强调可读性的语言。官方文档里有句著名的话代码的阅读次数远比编写次数多。所以从第一天开始就必须养成写给读者的习惯而不是写给机器的习惯。注释和标识符恰好就是Readable Code的左右手。我说得直白一点如果变量名起得足够清晰注释的量可以少一半如果注释写得到位别人接手你代码时能在十分钟内上手而不是花三天来考古。1.2 学完之后你该掌握什么这一篇的目标非常明确不需要贪多。学完你应当能做到四件事熟记Python注释的类型单行注释、多行注释、文档字符串、编码声明熟练运用标识符命名规则知道哪些名字合法、哪些不合法、哪些虽然合法但不推荐理解关键字保留字为什么不能作为标识符知道Python一共有多少个关键字能按PEP 8的命名规范为变量、常量、函数、类分别选择合适的命名风格。这些听起来不难但等你实际写代码的时候会发现低级错误比如变量名打了中文括号、用了class当变量名几乎每天都在编程社区的提问帖里出现。这篇文章要做的就是让你在起步阶段把这些雷全部排掉而不是等到项目写了一半再回头看语法报错。2. 注释写给未来的自己和别人的说明书2.1 Python里的四种注释写法Python的注释总共有四种典型形式很多教材只提了前两种但实际上后两种在工程实践里的使用频率更高而且有完全不同的语义。第一种单行注释用井号#。# 计算用户平均得分 average total_score / user_count井号后面的内容一直到行尾都算注释解释器会直接忽略掉。这种注释可以独占一行也可以跟在代码末尾像这样average total_score / user_count # 注意user_count不能为0我个人建议跟在代码后面的行尾注释不要写太长简短提示即可。如果内容超过一行就应该单独起一行写在代码上方。第二种多行注释用连续的三对引号或。 这段是给开发者看的说明 可以写多行 通常放在一段较复杂逻辑的上方。 def calculate_score(total_score, user_count): pass这里有个容易误解的细节Python里用三引号包起来的字符串如果你没有把它赋值给任何变量它确实会被解释器当作一条不产生效果的语句跳过所以能起到注释的效果。但它本质上仍然是字符串类型跟真正的#注释在机制上是不一样的。几年前有团队在线上环境踩过坑——某个模块顶部用了三引号注释结果这个字符串被某些框架扫描到引发了一个诡异的问题。所以我的建议是多行注释优先用连续多个#尽量别用三引号三引号的位置留给文档字符串。第三种文档字符串docstring用三引号写在模块、函数、类的内部第一行。def calculate_score(total_score, user_count): 根据总分和人数计算平均分。 参数: total_score: 总分 user_count: 用户人数 返回: 平均分 return total_score / user_count文档字符串和普通注释最大的区别在于它可以被Python的help()函数、自动生成文档的工具比如Sphinx、Doxygen读取。换句话说docstring是给工具和开发者共同看的正式文档而#注释是写给开发者看的随手笔记。这个定位差异很重要后面会遇到Doxygen风格注释、字段注释比如数据结构字段的说明它们的核心思路都是让注释变成可提取的结构化信息。第四种编码声明注释写在文件第一行或第二行。# -*- coding: utf-8 -*-在Python 3里源文件默认使用UTF-8编码所以这个声明绝大多数时候可以省略。但有些老项目、或者说需要支持Python 2的遗留代码里还会见到。你和别人协作时看到这一行知道它是编码声明即可不要觉得奇怪也不要手贱删掉。2.2 什么时候该写注释什么时候不该写有经验的开发者都知道注释应该解释为什么而不是解释是什么。一行代码在做什么代码本身就能说清楚只有代码背后的原因、背景、约束才需要注释。我举个例子。下面的注释就是典型的废话# 把x加1 x x 1这种注释没有任何信息量唯一的作用是增加噪音。而下面这段注释才是真正有价值的# 这里不能直接用pop(0)因为需要保留原始列表顺序供后续回溯使用 first_item items.pop(0)看到了吗注释解释的是一个反直觉的选择解释了背后的权衡和小心机。别人读代码时真正困惑的不是代码做了什么而是为什么这么做、为什么不用别的做法。这才是注释存在的意义。另外一个黄金法则是当你的代码复杂到必须写注释才能看懂通常意味着代码本身需要重构。与其写一大段注释来解释一团乱麻不如把逻辑拆成几个命名清晰的小函数让代码自己说话。好代码加注释是相辅相成不是互相救火。2.3 文档字符串docstring的特殊地位既然说到注释docstring值得单独展开。因为它在Python生态里不是可选的加分项而是非常重要的约定。PEP 257专门规范了docstring的写法主流IDE也会在你定义函数后自动生成docstring模板。一个团队项目里如果每个函数都有docstring那么很多工具可以直接从源码里提取API文档根本不需要额外维护一套文档站点。这也是为什么你会看到字段注释包注释doxygen注释这些热搜词——它们本质上是同一件事的不同实现方式让注释结构化、可提取、可自动生成文档。举例来说如果你写了一个工具模块里面有个函数用来把金额从分转成元def fen_to_yuan(fen: int) - float: 金额单位转换分转元。 参数: fen: 金额单位是分必须为正整数 返回: 金额单位是元 示例: fen_to_yuan(100) 1.0 return fen / 100以后任何人调用这个函数输入help(fen_to_yuan)就能看到完整的说明。如果函数写得足够多、模块足够完整用Sphinx可以一键生成漂亮的在线文档。这种代码即文档的思路Python社区非常推崇。这里再补充一个实操细节docstring的三引号最好用而不是这是PEP 257的建议。另外docstring的结尾三引号建议单独占一行这样后面如果追加内容diff记录更清晰代码审查时看起来也更舒服。2.4 关于编码声明那点事编码声明注释# -*- coding: utf-8 -*-在Python 3里其实可以完全不写因为Python 3的默认源码编码就是UTF-8。但我在整理这篇练习时还是把它列出来是因为你在网上仍会看到大量教程和旧项目里保留着它。如果跟着老教程读到这一行你至少要知道这不是给机器看的强制指令Python 2时代它确实是更不是某种魔法咒语。它只是一个历史遗留但无害的习惯。真正要注意的是无论有没有这行注释源文件本身的编码必须和解释器理解的一致。比如你用记事本把文件存成了GBK编码却在文件头写着coding: utf-8那代码跑起来照样会报编码错误甚至中文注释都会乱码。实操建议是用现代编辑器VS Code、PyCharm等时把默认编码设为UTF-8然后完全不用手写编码声明。如果哪天接手了老项目看到编码声明先确认文件实际编码和声明一致再动手改代码。3. 标识符每一个名字都必须合法合规3.1 Python标识符的硬性规则标识符Identifier就是你在代码里给变量、函数、类、模块起的名字。Python对标识符有一套硬性语法规则违反任何一条都会直接报错。别小看这些规则我在论坛上看到太多新人因为中文标点、数字开头、空格混入而反复碰壁。合法标识符必须同时满足以下条件第一只能由字母、数字、下划线组成不能有空格、标点、运算符。这个字母在Python 3里可以包含非ASCII字符比如中文但后面会专门说为什么我不建议你写中文标识符。像my var、my-var、my$var这些全都不合法。第二不能以数字开头。1var是错的var1是对的。原因很朴素Python解释器遇到以数字开头的东西会优先尝试把它解析成一个数字字面量比如1var会被拆成1和var这就会造成歧义所以语法上直接禁止。第三不能是Python的关键字保留字。比如if、for、while、class、def、import这些它们已经被语言本身征用了不能再当作变量名。后面第四部分会专门讲。第四标识符对大小写敏感。name、Name、NAME是三个完全不同的标识符。这点对很多以前写HTML、或者习惯随意大小写的人来说是个坎你会看到有人定义了变量user_name后面输入User_Name去访问结果报NameError就是因为大小写对不上。第五Python 3允许用中文等Unicode字符做标识符。比如年龄 18在语法上是合法的能吃但未必好吃。原因后面展开。3.2 命名规范是写给协作伙伴的硬性规则解决能不能用的问题命名规范解决好不好用的问题。Python官方有一份著名的风格指南PEP 8其中规定了不同类别对象的命名方式这是社区多年沉淀的共识。我在下面整理成一张表对象推荐风格示例说明普通变量全小写下划线snake_caseuser_name、total_score最常见最推荐常量全大写下划线MAX_RETRY_COUNT、PI表示值不应被修改函数全小写下划线calculate_average()动词开头更佳类大驼峰PascalCaseHttpClient、UserProfile单词首字母都大写模块/文件名全小写下划线data_utils.py避免使用连字符因为导入语句不支持私有变量/函数单下划线开头_internal_flag、_helper()约定俗成表示内部使用外部不应直接访问特殊方法双下划线开头和结尾__init__、__str__一般是Python内置的魔术方法从实操角度我给出的建议是变量名要短但不能短到失去信息。n不如countlst不如items。同时要避免和内置函数、常用库的命名冲突。比如你定义一个变量叫list之后想用list()构造列表就全乱了——这虽然合法但属于自找麻烦。还有一个贴近现实的经验团队协作中命名风格比个人偏好更重要。如果一个团队约定用snake_case你就别想着用camelCase显得特立独行。代码审查时最常见的争论往往就是命名问题。与其纠结哪种风格更美不如直接服从PEP 8因为GitHub上99%的Python项目都长这样你的代码风格越接近主流别人阅读成本越低。3.3 常见命名场景的推荐做法光记住规则不够你还需要知道真实项目里具体怎么取名。我总结了几个高频场景都是我实际写代码时验证过好用的套路。场景一布尔变量。建议用is_,has_,can_开头让变量名读起来像一个问题。比如is_valid、has_permission、can_retry。这样在if判断里代码非常自然if is_valid and has_permission: do_something()场景二函数名用动词或动词名词。函数是行为行为需要动词。get_user_by_id()永远比user_data()更像一个函数。如果函数会返回布尔值同样沿用is_、has_前缀。例如is_prime(n)、has_duplicate(items)。场景三临时变量。循环里的元素可以直接用item、value、k、v这类短名但前提是循环体很短范围一眼可见。一旦循环体超过5行短名的优势就消失了还是用有意义的全名比较稳妥。场景四下划线开头的作用。单下划线开头比如_private_data并不是Python语法强制禁止外部访问和Java的private不同它只是一个约定信号这个属性是内部实现细节外部代码别碰。双下划线开头的东西比如__secret会在类继承中触发名称修饰机制把名字改写成_ClassName__secret这个机制比较绕初学阶段只需要知道有双下划线开头的名字最好别碰即可。3.4 两个容易忽略的细节大小写与下划线这里展开两个我在实际调试中遇到最多的坑。坑一大小写不一致。前面说了Python对大小写敏感。很多新手习惯写代码时随手用userName但定义变量时用的是user_name运行时会报NameError。这类错误的特点是非常隐蔽——你在编辑器里看着两个名字好像差不多但解释器非常较真一点不差才算同一个标识符。排查方式很简单打开编辑器的区分大小写搜索功能定位所有出现的地方统一命名。坑二下划线被中文输入法吃掉。这是我在答疑时见过频率最高的低级错误。有些输入法在中文模式下按Shift组合键会把英文的_替换成中文的全角破折号或顿号肉眼几乎看不出来但Python解释器会立刻报错SyntaxError: invalid syntax。排查的时候把光标移到下划线附近按方向键移动如果感觉字符宽度不对劲多半就是中英文符号混用了。这类错误防不胜防唯一的好办法是刚学的时候尽量切换到纯英文输入法写代码包括标点符号、下划线、括号全部统一用半角。4. 关键字与内置函数不能踩的雷区4.1 关键字为什么不能当标识符关键字keyword是Python语言预留的特殊词它们每个都有被解释器特殊对待的语法含义。大家熟悉的if、elif、else、for、while、def、class、return、import、from、try、except、finally、with、and、or、not等等都属于这一类。从原理上讲解释器解析代码时会先把源码切分成一个个token词法单元。如果允许你用if 3那么解释器读到if这个token时就不知道该把它当作关键字来处理if分支逻辑还是当作变量名来赋值——这会造成语法上的二义性。所以语言设计者干脆规定这些词是保留的谁都不能拿来当标识符。Python 3里关键字一共有30多个具体版本之间略有差异。你不需要死记硬背完全可以当场验证import keyword print(keyword.kwlist) print(len(keyword.kwlist))运行后你会看到一份按字母排序的关键字列表。以后只要不确定某个词能不能当变量名跑一下这个检查就行。还有更简单的办法你直接在交互式环境里执行if 1解释器会立刻用SyntaxError: invalid syntax教你做人。4.2 一个小实验把关键字当作变量名会发生什么为了加深印象我们做个非常短的小实验。打开Python交互式环境终端里输入python回车依次输入下面的代码 class hello File stdin, line 1 class hello ^ SyntaxError: invalid syntax注意报错信息Python会把光标位置精准地指到class后面的空格处因为它在词法分析的阶段就发现了这里不该出现关键字。这种现象也侧面说明Python解释器的错误信息其实很友好往往直接指出问题位置你要学会看报错信息而不是凭感觉猜。再看看另一个高频错误——用了内置函数名做变量名 list [1, 2, 3] list((1, 2, 3)) Traceback (most recent call last): File stdin, line 1, in module TypeError: list object is not callable看到没这段代码在语法上完全合法不会报SyntaxError但运行时它把list这个名字覆盖成了列表对象导致原本的list()函数失效。这种错误比关键字更坑因为它不报编译错只在运行时引爆排查起来更费劲。我的建议是把list、dict、str、int、type、id、input、print这些高频内置函数名都当作准保留字一律不要用作变量名。如果你确实需要一个列表变量就叫items、values、numbers而不是list。4.3 别用内置函数名做变量名内置函数名被覆盖属于初学阶段最容易踩的雷。除了list还有几个典型内置函数踩坑后果print变量覆盖后打印功能失效代码静默无输出input后续无法再从命令行读输入id拿不到对象唯一标识type无法查看对象类型len无法计算容器长度str/int无法做类型转换这些覆盖行为在短脚本里可能碰巧没事但一旦代码变长早先的赋值语句覆盖了内置名后面的代码就会莫名其妙地TypeError。检查的办法也很简单在编辑器里按住Ctrl点击变量名PyCharm或VS Code都支持如果跳转到了Python内置模块的定义说明名字被正常解析为内置函数如果跳到了你自己的某一处赋值语句那就要小心了——你已经覆盖了它。这个雷之所以值得专门强调是因为它完全不符合新手对报错应该发生在出错那一行的直觉。你可能在文件第200行定义了list变量然后第20行的list(...)就遭殃了错误报在第20行排查时你大概率先怀疑第20行写错了半天想不起来第200行的存在。所以养成好习惯从第一天起就避开内置函数名比事后Debug省一百倍力气。5. 实战练习检验这15分钟的学习效果既然标题叫练习-01光看不练等于没学。我这几年带人的经验是基础阶段最忌讳眼睛会了手不会。下面三道题难度是递进的从找错误到判断合法性再到动手改造建议你认真把它们做完再翻参考答案否则练习效果会打对折。5.1 练习一给一段代码挑刺下面的代码存在多处和注释标识符相关的问题请逐行找出并说明理由# 计算平均分 1st_score 89 2nd_score 95 3rd_score 87 total_score 1st_score 2nd_score 3rd_score average total_score / 3 print(平均分是 average) # 输出结果先别急着跑直接读代码找问题。提示总共至少5处。5.2 练习二给变量名合法体检请判断下面的标识符哪些合法、哪些不合法并说明原因age _age age_1 1_age True true class_name class 用户名 user-name user name _is_valid_ for5.3 练习三改造一段坏味道代码下面这段代码能运行但读起来非常痛苦。请按照第二部分和第三部分讲的规范和风格重构它def f(a, b): # 计算两组数据的重叠部分长度 s1 set(a) s2 set(b) c len(s1 s2) return c list1 [1, 2, 3, 4, 5] list2 [4, 5, 6, 7, 8] result f(list1, list2) print(result)要求函数名改用动词短语变量名清晰表达含义注释重写说明为什么而不是是什么避免覆盖内置函数名。5.4 练习参考答案练习一1st_score、2nd_score、3rd_score以数字开头非法标识符解释器直接报SyntaxErrorprint(平均分是 average)average是浮点数不能直接和字符串用拼接运行时需要改成f平均分是{average}最后的行尾注释# 输出结果是典型的废话注释没有解释任何为什么建议删除或补充说明头部注释# 计算平均分如果只是为了说明代码作用可以保留但更好的做法是让代码本身通过变量名表达这个意图。练习二age合法_age合法单下划线开头表示私有约定age_1合法数字不在开头1_age不合法数字开头True不合法True是Python关键字表示布尔真值true合法因为大小写不同它不是关键字但尽量别用容易和True混淆class_name合法很常见class不合法关键字用户名合法Python 3支持Unicode标识符但不推荐在协作项目中使用user-name不合法连字符-会被当成减号标识符不允许user name不合法空格不允许出现_is_valid_合法但双下划线前后都有特殊约定魔术方法普通场景不建议这样命名for不合法关键字。练习三参考改法def count_overlap(first_items, second_items): 计算两组数据集合的交集元素个数。 参数: first_items: 可迭代对象例如列表 second_items: 可迭代对象例如列表 返回: 交集元素的个数 first_set set(first_items) second_set set(second_items) overlap_count len(first_set second_set) return overlap_count scores_a [1, 2, 3, 4, 5] scores_b [4, 5, 6, 7, 8] overlap_count count_overlap(scores_a, scores_b) print(overlap_count)几个改动点说明函数名f改成了count_overlap动词短语表意清晰参数a, b改成了first_items, second_items内部临时变量c改成了overlap_countlist1、list2改成了scores_a、scores_b避免覆盖list内置函数同时把注释升级成了docstring这样help()能看到文档。6. 新手最容易踩的四个坑6.1 中文输入法混入全角符号这个坑我在前面已经提过一次但值得再强调因为它几乎每个新手都会遇到而且极其隐蔽。典型场景你想给变量起名user_name输入下划线时如果中文输入法处于中文标点状态实际上输入的是中文的下划线占两个字符宽度。代码看着没区别但解释器一遇到就SyntaxError。我的排查技巧是在报错的代码行里按方向键移动光标如果光标移动的格数比字符数多说明有隐藏字符。更省事的是显示空白字符VS Code里勾选Render WhitespacePyCharm里设置Show whitespace非ASCII字符会显示成不同的颜色或宽度。总之一句话写代码时永远保持英文输入法在全半角正确状态特别是括号、引号、下划线这几个高危字符。6.2 复制粘贴导致的下划线丢失还有一类问题源于复制粘贴。从网页、PDF、聊天窗口复制代码时较长的下划线___有时候会被复制成三个短横---或者双下划线__被折叠成单下划线_。这在你定义__init__、__name__这类魔术方法时尤其致命——因为双下划线前后都有意义少一个下划线Python解释器就把你的方法当普通方法处理类实例化时根本不会调用到它。实操建议核心代码尽量手动敲不要整段从网页复制如果非要复制粘贴后先跑一次语法检查编辑器里的错误提示、或者python -m py_compile 文件名.py确认无误再进行下一步。6.3 注释不更新的僵尸注释这部分内容属于代码维护阶段的真实经验。写注释不难难的是让注释永远和代码保持同步。很多老项目里代码改了好几轮注释还停留在最初版本——这就成了僵尸注释比没有注释更误事。因为后来接手的人如果相信注释会按照错误的说明去理解代码轻则浪费半天时间重则把正确逻辑改坏。我个人的原则是改代码时必须同步看一眼相关注释。如果注释和代码对不上了要么改注释要么删注释不要留着一句过时的解释。这个习惯看起来琐碎但在长期维护的项目里它直接决定你的代码十年后还能不能被别人包括未来的你自己看懂。6.4 纠结命名时的完美主义新手容易走另一个极端起个变量名想了十分钟觉得这个不够准确那个不够优雅。我在实际项目里的经验是命名要用心但不要过度纠结。变量名只要满足见名知义、能读出来、不产生误解这三个标准就已经合格了。与其花十分钟想一个完美的名字不如快速用一个合格的名字然后继续往下写等代码写完了回头看整体结构时再统一优化命名。这里有个非常实用的技巧先用一个足够描述性但不完美的名字比如temp_data把逻辑跑通然后在重构阶段用编辑器的重命名功能批量修改。PyCharm和VS Code都支持对整个项目内的标识符做安全重命名比你一开始抠字眼高效得多。编程是迭代的艺术第一次写得不够漂亮完全可以接受关键在于你有意识地在后续循环里改进它。就我个人而言每次带新人入门我都会把这些坑提前摆出来让他们在第一天就建立代码是给人看的顺带让机器执行的认知。注释和标识符看似基础却是这份认知最直接的载体。下一篇系列练习我会接着讲变量和基础数据类型到时候你会发现这一篇打下的底子会让后面的一切顺利很多。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑