
多数刚开始学习的人具备编写代码的能力, 然而知晓怎样去规划应用结构, 从而保证项目易于维护并防止最终生成的代码杂乱无章的人却很少。在这个案例里, 你会学到专业开发者所运用的实践方式, 打造出结构干净整洁、方便调试、特别容易扩展的项目。案例说明在下面的那个名为 sales.csv 的文件里, 挑选出其中 是 North 的那些记录, 将其保存成 .csv 文件。sales.csv:.csv:第一步像书店分类整理图书一样组织代码保持代码良好的组织结构能够带来诸多优势代码规范组织的好处• 可读性更高 —— 你能快速理解代码实现的功能。• 便于排查漏洞 —— 更容易发现并修复程序错误。• 方便迭代更新 —— 新增功能时不会让代码变得杂乱。• 减少重复编写 —— 复用已有代码无需重复造轮子。• 利于团队协作 —— 其他人能够更快读懂并接手你的代码。• 节省开发时间 —— 不用在杂乱的代码里反复搜寻内容。• 程序更加稳定 —— 结构清晰的代码出错概率更低。编程语言的主要组成单元• 代码行• 函数• 模块第二步借助注释把任务转化为代码开启项目存在一种简便方式, 首先以注解形式罗列出项目所要达成的各项关键任务。main.py# load the data# filter the data# write data to a report随后为每一项任务编写对应的函数 :defload_data:print(load_data)deffilter_data:print(filter_data)defwrite_report:print(write_report)# load the dataload_data# filter the datafilter_data# write data to a reportwrite_report优化初始代码结构 :我们将主代码放入名为 的函数中让代码更加整洁defload_data:print(load_data)deffilter_data:print(filter_data)defwrite_report:print(write_report)defreport_flow:# load the dataload_data# filter the datafilter_data# write data to a reportwrite_report# runs this firstreport_flow第三步在运行代码前捕获错误十分实用它能帮助你更顺畅地编写 代码减少代码出错。使用 的优势• 边编码边发现错误在运行程序前高亮标出代码问题。• 代码智能提示提供自动补全建议提升编码速度。• 问题解读提示错误原因通常还会给出修复方案。• 支持代码跳转可以快速定位函数、变量的定义位置。降低排查错误所耗时间, 以此提升开发效率, 进而让更多精力得以投入到编写代码之中。简要总结如同一位能贴心提供助力之人, 于你着手编写代码之际, 时刻对代码展开检查, 助力你在较早之时察觉错误。安装 :轻触侧边栏那儿的扩展面板, 其快捷键是Ctrl加Shift加X, 接着开展搜索, 之后再去点击安装按钮。注意 安装 之后你可能需要重启 Code 。将在代码出现错误的地方添加上下划线, 借由这样的方式标记出常见的错误, 举例说明, 当我们把函数的定义加以注释之后:它还会于【问题】面板那儿呈现出当下全部的错误, 其快捷键是Ctrl Shift M。第四步灵活传递数据提升程序可扩展性即便函数只设计用来完成单一特定任务依旧需要访问程序数据。别去依赖那全局变量, 我们能够把数据当作参数也就是输入传递给函数, 并且将更新之后的数据以返回值也就是输出的形式传出来。数据传参方式的优势行为具备可预测性, 且不存在副作用, 仅需查看函数的输入以及输出, 便能够清晰地了解函数的功能, 不必担忧程序中其他位置会出现不明显的数据改动。一、便于调试: 该函数输出结果若是异常情况, 此情形下仅仅需要检查所传入的参数就行, 并非要对整个程序的运行状态进行层层排查。能够轻松进行测试, 只要传入带有模拟性质的测试数据, 接着校验所输出的结果, 如此便能够对函数展开测试, 而无需去搭建那种复杂的全局程序环境。这段代码具备可复用的特性 函数没有绑定特定的全局变量 , 所以在代码的任何位置 , 你能够在传入别样参数的情况下 , 安全地使用该函数进行调用 , 最终结束调用呢。我们能够先去定义函数相互之间传入、传出的数据框架, 随后再增添一些示例数据着手用于测试。如此会确保在继续展开开发之前就能知道代码能够正常运行。import pandas as pddefload_data:# sample datadata {region: [North, North, South],sales: [100, 200, 300]}# create a dataframe from this datareturn pd.DataFrame(data)deffilter_data(df):filtered_df dfreturn filtered_dfdefwrite_report(df):print(fdataframe is: \n {df})defreport_flow:# load the datadf load_data# filter the datafiltered_df filter_data(df)# write data to a reportwrite_report(filtered_df)report_flow使用类型提示 Type Hints 于其中, 我们能够凭借类型提示去指明参数以及返回值理应具备的数据类型。这能够极大程度地显著提升代码具有的易于理解那种素质与此同时凭借着, 像VS Code这类的集成开发环境, 会在你把鼠标放置上去处于悬停状态或者调用函数这个行为发生的时候, 借助悬浮提示框这种工具来展示类型信息。函数返回值的类型提示写法使用 - 后紧跟数据类型。defload_data - pd.DataFrame:如果函数没有返回值则使用 None 标注defwrite_report - None:参数的类型提示的写法是这般, 在参数的名称的后面加上冒号, 然后紧跟着写明数据的类型。defwrite_report(df: pd.DataFrame):下面我们为代码加上类型提示进行更新import pandas as pddefload_data - pd.DataFrame:# sample datadata {region: [North, North, South],sales: [100, 200, 300]}# create a dataframe from this datareturn pd.DataFrame(data)deffilter_data(df: pd.DataFrame) - pd.DataFrame:filtered_df dfreturn filtered_dfdefwrite_report(df: pd.DataFrame) - None:print(fdataframe is: \n {df})defreport_flow - None:# load the datadf load_data# filter the datafiltered_df filter_data(df)# write data to a reportwrite_report(filtered_df)report_flow最后, 我们会去编写项目的主要部分代码, 具体而言, 是那种能够达成数据读取, 以及筛选, 还有数据输出功能的代码。import pandas as pdimport osos.chdir(rE:\TestData)defload_data - pd.DataFrame:df pd.read_csv(sales.csv)return dfdeffilter_data(df: pd.DataFrame) - pd.DataFrame:filtered_df df[df[region] North]return filtered_dfdefwrite_report(df: pd.DataFrame) - None:df.to_csv(reports.csv,index False)defreport_flow - None:# load the datadf load_data# filter the datafiltered_df filter_data(df)# write data to a reportwrite_report(filtered_df)report_flow第五步使用断言防范运行时错误所说断言能够被理解成这样子给程序下达一种指令, 即, “那个条件应当始终都是成立的”, 要是并不成立的话, 那就表示程序出现了异常情况。基础语法assert condition举个例子下面这个条件成立20 大于 18 。age 20assert age 18因此不会产生任何提示程序继续运行。如果条件为假age 16assert age 18会终止程序运行并抛出错误。AssertionError简单实用示例设想你正在编写一个用于两个数字相除的函数什么时候使用断言在查找用于开发阶段才会出现的程序缺陷之时, 一般会运用断言, 得以验证我们预先设定的众多条件到底是不是具备成立情形, 可以判断是否成立。一旦断言条件不满足我们希望能立刻收到提醒。常规的用户错误处理场景之内, 像是用户输入非法这般的情况, 还有文件不存在这种场景之时, 断言是不合适去用来进行处理的。这类的情况应该要使用异常机制, 比如说通过条件判断去捕获错误, 又或是采用try语句的形式。简易记忆区分• “ 这种情况绝对不应该发生。 ”若尝试加上引发, 就意味着用户存在有触发这类问题的可能性, 而出现这种情况就得进行妥善处理。添加断言后的更新代码defreport_flow:# load the data from csvdf load_data_salesassertlen(df) 7, dataframe should have 7 records after loading# filter the datafiltered_df filter_data(df)assertlen(filtered_df) 2, dataframe should have 2 records after filtering# write the reportwrite_report(filtered_df)第六步代码分层整洁代码架构方案分层使各模块职责单一方便阅读与维护。分层优势• 变更隔离局部修改不影响其他代码• 测试便捷支持单独测试模块• 逻辑复用核心代码多处共用• 并行开发多人同时开发不同层级具有易于理解的特性, 当开发人员打算修复单个问题之际, 并不需要去掌握那整套系统于运行时所依据的原理。如何在代码中实现分层落实到实操层面我们遵循几条简单规范来对代码分层依照主题进行归类, 把那些功能存在关联的函数, 放置在同一份文件里, 也就是同一个模块之中。·函数要有单一职责, 要让函数专门去完成一项特定的任务, 而不要在同一时间去处理那些彼此之间没有关联的工作。确保划定清晰边界, 让各层级仅仅处理自身范畴之内的事务比如说和数据库相关的代码专门负责数据处理, 但和网页相关的代码专门负责界面交互。在不同层级之间传递数据 , 要使用简易数据对象 , 像字典 、数据类这样的 , 以此来传递简洁数据载体。• 将内部实现细节予以隐藏, 其他层级仅仅只需调用函数, 并不需要去关心函数底层究竟是怎样达成功能的。改造代码实现分层架构1)main.py:from manager import report_flowreport_flow2).py:from data_loader import load_data_salesfrom report import write_reportfrom filters import filter_datadefreport_flow:# load the data from csvdf load_data_sales# filter the datafiltered_df filter_data(df)assertlen(filtered_df) 2, dataframe should have 2 records# write the reportwrite_report(filtered_df)if __name__ __main__:report_flow3).py:import pandas as pdimport osos.chdir(rE:\TestData)defload_data_sales - pd.DataFrame:df pd.read_csv(rsales.csv)return df4 ) .py:import pandas as pdimport osos.chdir(rE:\TestData)defwrite_report(df: pd.DataFrame):df.to_csv(rreport.csv, indexFalse)5 .py:import pandas as pddeffilter_data(df: pd.DataFrame) - pd.DataFrame:filtered_df df[df[region] North]return filtered_df运行后即可得到.csv。实际情况中, 再然后还有一步所要做的便是让代码变得更易于阅读, 换而言之也就是去增添一个常量模块.py, 然而呢我觉着这有没有它都行, 是依据自身的喜好来进行考量的。当然了, 将所有的常量专门摆放在一个模块里, 这也算得上是一种不错的方法。