编写代码是数据科学家或剖析师角色的一部分。另一方面,编写俊秀整洁的Python代码完备是另一回事。作为一个精通剖析或数据科学领域(乃至软件开拓)的程序员,这很可能会改变你的形象。
那么,我们如何编写这种所谓俊秀的Python代码呢?
欢迎学习Python风格教程
数据科学和剖析领域的许多人来自非编程背景。我们先从学习编程的根本知识开始,接着理解机器学习背后的理论,然后开始征服数据集。
在这个过程中,我们常常不练习核心编程,也不把稳编程老例。
这便是本Python风格教程将要办理的问题。我们将回顾PEP-8文档中描述的Python编程约定,你将成为一个更好的程序员!
有几个缘故原由使格式化成为编程的一个主要方面,尤其是对付数据科学项目:
可读性好的代码格式将不可避免地提高代码的可读性。这不仅会使你的代码更有条理,而且会使读者更随意马虎理解程序中正在发生的事情。如果你的程序运行了数千行,这将特殊有用。
你会有很多的数据帧、列表、函数、绘图等,如果不遵照精确的格式准则,你乃至会很随意马虎失落去对自己代码的跟踪!
如果你在一个团队项目上互助,大多数数据科学家都会这样做,那么好的格式化就成了一项必不可少的任务。
这样可以确保代码被精确理解而不产生任何麻烦。此外,遵照一个通用的格式模式可以在全体项目生命周期中保持程序的同等性。
Bug修复当你须要修复程序中的缺点时,拥有一个格式良好的代码也将有助于你。缺点的缩进、不恰当的命名等都很随意马虎使调试成为一场噩梦!
因此,最好因此精确的编写风格来开始编写你的程序!
考虑到这一点,让我们快速概述一下本文将先容的PEP-8样式教程!
PEP-8或Python增强建议是Python编程的风格教程。它是由吉多·范罗森、巴里·华沙和尼克·科格兰写的。它描述了编写俊秀且可读的Python代码的规则。
遵照PEP-8的编码风格将确保Python代码的同等性,从而使其他读者、贡献者或你自己更随意马虎理解代码。
本文先容了PEP-8辅导原则中最主要的方面,如如何命名Python工具、如何布局代码、何时包含注释和空格,末了是一些很主要但很随意马虎被大多数Python程序员忽略的一样平常编程建议。
让我们学习编写更好的代码!
官方PEP-8文档可以在这里找到。
https://www.python.org/dev/peps/pep-0008/
理解Python命名约定莎士比亚有句名言:“名字里有什么?”. 如果他当时碰着了一个程序员,他会很快得到一个答复——“很多!
”.
是的,当你编写一段代码时,你为变量、函数等选择的名称对代码的可理解性有很大的影响。看看下面的代码:
# 函数 1def func(x): a = x.split()[0] b = x.split()[1] return a, bprint(func('Analytics Vidhya'))# 函数 2def name_split(full_name): first_name = full_name.split()[0] last_name = full_name.split()[1] return first_name, last_nameprint(name_split('Analytics Vidhya'))
# 输出('Analytics', 'Vidhya')('Analytics', 'Vidhya')
这两个函数的浸染是一样的,但是后者供应了一个更好的直觉让我们知道发生了什么,纵然没有任何注释!
这便是为什么选择精确的名称和遵照精确的命名约定可以在编写程序时可以产生巨大的不同。话虽如此,让我们看看如何在Python中命名工具!
这些技巧可以运用于命名任何实体,并且该当严格遵守。
遵照相同的模式thisVariable, ThatVariable, some_other_variable, BIG_NO
避免利用长名字,同时也不要太节俭的名字
this_could_be_a_bad_name = “Avoid this!”t = “This isn\’t good either”
利用合理和描述性的名称。这将有助于往后你记住代码的用场
X = “My Name” # 防止这个full_name = “My Name” # 这个更好
避免利用以数字开头的名字
1_name = “This is bad!”
避免利用分外字符,如@、!
、#、$等
phone_ # 不好
变量命名变量名应始终为小写
blog = "Analytics Vidhya"
对付较长的变量名,请利用下划线分隔单词。这提高了可读性
awesome_blog = "Analytics Vidhya"
只管即便不要利用单字符变量名,如“I”(大写I字母)、“O”(大写O字母)、“l”(小写字母l)。它们与数字1和0无法区分。看看:
O = 0 + l + I + 1
全局变量的命名遵照相同的约定函数命名遵照小写和下划线命名约定利用富有表现力的名字
# 避免def con(): ...# 这个更好def connect(): ...
如果函数参数名与关键字冲突,请利用尾随下划线而不是缩写。例如,将break转换为break_u而不是brk
# 避免名称冲突def break_time(break_): print(“Your break time is”, break_,”long”)
类名命名遵照CapWord(或camelCase或StudlyCaps)命名约定。每个单词以大写字母开头,单词之间不要加下划线
# 遵照CapWordclass MySampleClass: pass
如果类包含具有相同属性名的子类,请考虑向类属性添加双下划线
这将确保类Person中的属性age被访问为 _Person\age。这是Python的名称混乱,它确保没有名称冲突
class Person: def __init__(self): self.__age = 18obj = Person() obj.__age # 缺点obj._Person__age # 精确
对非常类利用后缀“Error”
class CustomError(Exception): “””自定义非常类“””
类方法命名实例方法(不附加字符串的基本类方法)的第一个参数应始终为self。它指向调用工具类方法的第一个参数应始终为cls。这指向类,而不是工具实例
class SampleClass: def instance_method(self, del_): print(“Instance method”) @classmethod def class_method(cls): print(“Class method”)
包和模块命名只管即便使名字简短明了应遵照小写命名约定对付长模块名称,首选下划线避免包名称利用下划线
testpackage # 包名称sample_module.py # 模块名称
常量命名常量常日在模块中声明和赋值常量名称应全部为大写字母对较长的名称利用下划线
# 下列常量变量在global.py模块PI = 3.14GRAVITY = 9.8SPEED_OF_Light = 3108
Python风格教程的代码布局
现在你已经知道了如何在Python中命名实体,下一个问题该当是如何用Python布局代码!
诚笃说,这是非常主要的,由于如果没有适当的构造,你的代码可能会出问题,对任何评审职员来说都是最大的障碍。
以是,不用再多费吹灰之力,让我们来理解一下Python中代码布局的根本知识吧!
它是代码布局中最主要的一个方面,在Python中起着至关主要的浸染。缩进见告代码块中要包含哪些代码行以供实行。短缺缩进可能是一个严重的缺点。
缩进确定代码语句属于哪个代码块。想象一下,考试测验编写一个嵌套的for循环代码。在各自的循环之外编写一行代码可能不会给你带来语法缺点,但你终极肯定会碰着一个逻辑缺点,这可能会在调试方面耗费韶光。
遵照下面提到的缩进风格,以得到同等的Python脚本风格。
始终遵照4空格缩进规则# 示例if value<0: print(“negative value”)# 另一个例子for i in range(5): print(“Follow this rule religiously!”)
建议用空格代替制表符
建议用空格代替制表符。但是当代码已经用制表符缩进时,可以利用制表符。
if True: print('4 spaces of indentation used!')
将大型表达式拆分成几行
处理这种情形有几种方法。一种方法是将后续语句与起始分隔符对齐。
# 与起始分隔符对齐。def name_split(first_name, middle_name, last_name)# 另一个例子。ans = solution(value_one, value_two, value_three, value_four)
第二种方法是利用4个空格的缩进规则。这将须要额外的缩升级别来区分参数和块内其他代码。
# 利用额外的缩进。def name_split( first_name, middle_name, last_name): print(first_name, middle_name, last_name)
末了,你乃至可以利用“悬挂缩进”。悬挂缩进在Python高下文中是指包含圆括号的行以开括号结束的文本样式,后面的行缩进,直到括号结束。
# 悬挂缩进ans = solution( value_one, value_two, value_three, value_four)
缩进if语句可能是一个问题
带有多个条件的if语句自然包含4个空格。如你所见,这可能是个问题。随后的行也将缩进,并且无法区分if语句和它实行的代码块。现在,我们该怎么办?
好吧,我们有几种方法可以绕过它:
# 这是个问题。if (condition_one and condition_two): print(“Implement this”)
一种方法是利用额外的缩进!
# 利用额外的缩进if (condition_one and condition_two): print(“Implement this”)
另一种方法是在if语句条件和代码块之间添加注释,以区分这两者:
# 添加注释。if (condition_one and condition_two): # 此条件有效 print(“Implement this”)
括号的闭合
假设你有一个很长的字典。你将所有的键值对放在单独的行中,但是你将右括号放在哪里?是在末了一行吗?还是跟在末了一个键值对?如果放在末了一行,右括号位置的缩进是多少?
也有几种方法可以办理这个问题。
一种方法是将右括号与前一行的第一个非空格字符对齐。
# learning_path = { ‘Step 1’ : ’Learn programming’, ‘Step 2’ : ‘Learn machine learning’, ‘Step 3’ : ‘Crack on the hackathons’ }
第二种方法是把它作为新行的第一个字符。
learning_path = { ‘Step 1’ : ’Learn programming’, ‘Step 2’ : ‘Learn machine learning’, ‘Step 3’ : ‘Crack on the hackathons’}
在二元运算符前换行
如果你试图在一行中放入太多的运算符和操作数,这肯定会很麻烦。相反,为了更好的可读性,把它分成几行。
现在很明显的问题是——在操作符之前还是之后中断?老例是在操作符之前断行。这有助于识别操作符和它所浸染的操作数。
# 在操作符之前断行gdp = (consumption + government_spending + investment + net_exports )
利用空行
将代码行聚在一起只会使读者更难明得你的代码。使代码看起来更整洁、更都雅的一个好方法是在代码中引入相应数量的空行。
顶层函数和类该当用两个空行隔开#分离类和顶层函数class SampleClass(): passdef sample_function(): print("Top level function")
类中的方法该当用一个空格行分隔
# 在类等分离方法class MyClass(): def method_one(self): print("First method") def method_two(self): print("Second method")
只管即便不要在具有干系逻辑和函数的代码段之间包含空行
def remove_stopwords(text): stop_words = stopwords.words("english") tokens = word_tokenize(text) clean_text = [word for word in tokens if word not in stop_words] return clean_text
可以在函数中少用空行来分隔逻辑部分。这使得代码更随意马虎理解
def remove_stopwords(text): stop_words = stopwords.words("english") tokens = word_tokenize(text) clean_text = [word for word in tokens if word not in stop_words] clean_text = ' '.join(clean_text) clean_text = clean_text.lower() return clean_text
行最大长度一行不超过79个字符
当你用Python编写代码时,不能在一行中压缩超过79个字符。这是限定,该当是保持声明简短的辅导原则。
你可以将语句拆分为多行,并将它们转换为较短的代码行# 分成多行num_list = [y for y in range(100) if y % 2 == 0 if y % 5 == 0]print(num_list)
导入包
许多数据科学家之以是喜好利用Python,部分缘故原由是由于有太多的库使得处理数据更加随意马虎。因此,我们假设你终极将导入一堆库和模块来完成数据科学中的任何任务。
该当始终位于Python脚本的顶部应在单独的行上导入单独的库import numpy as npimport pandas as pddf = pd.read_csv(r'/sample.csv')
导入应按以下顺序分组:标准库导入干系第三方入口本地运用程序/库特定导入在每组导入后包括一个空行
import numpy as npimport pandas as pdimport matplotlibfrom glob import globimport spaCy import mypackage
可以在一行中从同一模块导入多个类
from math import ceil, floor
熟习精确的Python注释
理解一段未注释的代码可能是一项费力的事情。纵然是代码的原始编写者,也很难记住一段韶光后代码行中到底发生了什么。
因此,最好及时对代码进行注释,这样读者就可以精确地理解你试图用这段代码实现什么。
一样平常提示注释总是以大写字母开头注释该当是完全的句子更新代码时更新注释避免写显而易见之事的注释注释的风格描述它们后面的代码段与代码段有相同的缩进从一个空格开始# 从用户输入字符串中删除非字母数字字符。import reraw_text = input(‘Enter string:‘)text = re.sub(r'\W+', ' ', raw_text)
内联注释这些注释与代码语句位于同一行应与代码语句至少分隔两个空格以常日的#开头,然后是空格不要用它们来陈述显而易见的事情只管即便少用它们,由于它们会分散把稳力
info_dict = {} # 字典,用于存储提取的信息
文档字符串用于描述公共模块、类、函数和方法也称为“docstrings”它们之以是能在其他注释中脱颖而出,是由于它们是用三重引号括起来的如果docstring以单行结尾,则在同一行中包含结束符“””如果docstring分为多行,请在新行中加上结束符“””
def square_num(x): """返回一个数的平方.""" return x2def power(x, y): """多行注释。 返回xy. """ return xy
Python代码中的空格
在编写俊秀的代码时,空格常常被忽略为一个微不足道的方面。但是精确利用空格可以大大提高代码的可读性。它们有助于防止代码语句和表达式过于拥挤。这不可避免地帮助读者轻松地浏览代码。
关键避免将空格立即放在括号内# 精确的方法df[‘clean_text’] = df[‘text’].apply(preprocess)
不要在逗号、分号或冒号前加空格
# 精确name_split = lambda x: x.split()
字符和左括号之间不要包含空格
# 精确print(‘This is the right way’)# 精确for i in range(5): name_dict[i] = input_list[i]
利用多个运算符时,只在优先级最低的运算符周围包含空格
# 精确ans = x2 + bx + c
在分片中,冒号充当二进制运算符
它们该当被视为优先级最低的运算符。每个冒号周围必须包含相等的空格
# 精确df_valid = df_train[lower_bound+5 : upper_bound-5]
应避免尾随空格函数参数默认值不要在=号周围有空格
def exp(base, power=2): return basepower
请始终在以下二进制运算符的两边用单个空格括起来:赋值运算符(=,+=,-=,等)比较(=,<,>!
=,<>,<=,>=,输入,不在,是,不是)布尔值(and,or,not)
# 精确brooklyn = [‘Amy’, ‘Terry’, ‘Gina’, 'Jake']count = 0for name in brooklyn: if name == ‘Jake’: print(‘Cool’) count += 1
Python的一样平常编程建议
常日,有很多方法来编写一段代码。当它们完成相同的任务时,最好利用推举的编写方法并保持同等性。我在这一节已经先容了个中的一些。
与“None”之类的进行比较时,请始终利用“is”或“is not”。不要利用相等运算符# 缺点if name != None: print("Not null")# 精确if name is not None: print("Not null")
不要利用比较运算符将布尔值与TRUE或FALSE进行比较。虽然利用比较运算符可能很直不雅观,但没有必要利用它。只需编写布尔表达式
# 精确if valid: print("Correct")# 缺点if valid == True: print("Wrong")
与其将lambda函数绑定到标识符,不如利用泛型函数。由于将lambda函数分配给标识符违背了它的目的。回溯也会更随意马虎
# 选择这个def func(x): return None# 而不是这个func = lambda x: x2
捕获非常时,请命名要捕获的非常。不要只利用一个光秃秃的例外。这将确保当你试图中断实行时,非常块不会通过键盘中断非常来粉饰其他非常
try: x = 1/0except ZeroDivisionError: print('Cannot divide by zero')
与你的返回语句保持同等。也便是说,一个函数中的所有返回语句都该当返回一个表达式,或者它们都不应该返回表达式。其余,如果return语句不返回任何值,则返回None而不是什么都不返回
# 缺点def sample(x): if x > 0: return x+1 elif x == 0: return else: return x-1# 精确def sample(x): if x > 0: return x+1 elif x == 0: return None else: return x-1
如果要检讨字符串中的前缀或后缀,请利用“.startswith()”和“.endswith()",而不是字符串切片。它们更干净,更不随意马虎出错
# 精确if name.endswith('and'): print('Great!')
自动格式化Python代码
当你编写小的程序时,格式化不会成为一个问题。但是想象一下,对付一个运行成千行的繁芜程序,必须遵照精确的格式规则!
这绝对是一项艰巨的任务。而且,大多数时候,你乃至不记得所有的格式规则。
我们如何办理这个问题呢?好吧,我们可以用一些自动格式化程序来完成这项事情!
自动格式化程序是一个程序,它可以识别格式缺点并将其修复到位。Black便是这样一种自动格式化程序,它可以自动将Python代码格式化为符合PEP8编码风格的代码,从而减轻你的包袱。
BLACK:https://pypi.org/project/black/
通过在终端中键入以下命令,可以利用pip轻松安装它:
pip install black
但是让我们看看black在现实天下中有多大的帮助。让我们用它来格式化以下类型缺点的程序:
现在,我们要做的便是,前往终端并键入以下命令:
black style_script.py
完成后,black可能已经完成了变动,你将收到以下:
一旦再次考试测验打开程序,这些变动将反响在程序中:
正如你所看到的,它已经精确地格式化了代码,在你欠妥心违反格式化规则的情形下它会有帮助。
Black还可以与Atom、Sublime Text、visualstudio代码,乃至Jupyter Notebook集成在一起!
这无疑是一个你永久不会错过的插件。
除了black,还有其他的自动格式化程序,如autoep8和yapf,你也可以考试测验一下!
我们已经在Python风格教程中谈论了很多关键点。如果你在代码中始终遵照这些原则,那么你将终极得到一个更干净和可读的代码。
其余,当你作为一个团队在一个项目中事情时,遵照一个共同的标准是有益的。它使其他互助者更随意马虎理解。开始在Python代码中加入这些风格技巧吧!