
编写高质量python代码的59个有效方法
文章平均质量分 56
良知即吾心
这个作者很懒,什么都没留下…
展开
-
每日10行代码126: 编写高质量python代码的方法25:用super 初始化父类
初始化父类的传统方式,是在子类里用子类实例直接调用父类的 __init__ 方法。class MyBaseClass(object): def __init__(self, value): self.value = valueclass MyChildClass(MyBaseClass): def __init__(self): MyBaseClass.__init__(self, 5)这种办法对于简单的继承体系是可行的,但是在这么多情况下会出问题。原创 2021-03-10 09:35:26 · 153 阅读 · 0 评论 -
每日10行代码124: 编写高质量python代码的方法50:用包来安排模块,并提供稳固的API
程序的代码量变大之后,我们自然就需要重新调整其结构。我们会把大函数分割成小函数,会把某些数据结构重构为辅助类(参见该书第22条),也会把功能分散到多个相互依赖的模块之中。到了一定的阶段,我们就会发现,模块的数量实在太多了,于是,我们就需要在程序之中引进一种抽象层,舍不得代码更加便于理解。Python 的包 package 就可以充当这样的抽象层。包,是一种含有其他模块的模块。在大多数情况下,我们会给目录中放入名为 __init__.py 的空文件,并以些来定义包。只要目录里面有 __init__.py原创 2021-02-23 16:30:09 · 127 阅读 · 0 评论 -
每日10行代码123: 编写高质量python代码的方法49:为每个函数、类和模块编写文档字符串
由于Python 是一门动态语言,所以文档显得极其重要。Python 对文档提供了内置的支持,使得开发者可以把文档与代码块关联起来。与其他许多编程语言不同,Python程序在运行的时候,能够直接访问源代码中的文档信息。例如:在为函数编写了def 语句之后,我们可以紧接着提供 docstring, 以便将一段开发文档与该函数关联起来:def palindrome(word): """Return True if the given word is a palindrome.""" retu原创 2021-02-20 15:15:13 · 220 阅读 · 0 评论 -
每日10行代码122: 编写高质量python代码的方法47:在重视精确度的场合,应该使用 decimal
Python 语言很合适用来编写与数值型数据打交道的代码。Python 的整数类型,可以表达任意长度的值,其双精度浮点数类型,也遵循 IEEE 754 标准。此外,Python 还提供了标准复数类型,用来表示虚数值。然而这引起数值类型,并不能覆盖每一种情况。例如,要根据通话时长和费率,来计算打电话费。假如用户打了3分42秒,打国际长途,每分钟1.45元,那么通话费是多少呢?rate = 1.45seconds = 3*60 + 42cost = rate*seconds / 60print(cos原创 2021-02-18 16:40:02 · 155 阅读 · 0 评论 -
每日10行代码121: 编写高质量python代码的方法24:以@classmethod 形式的多态去通用地构建对象
在 Python 中,不仅对象支持多态,类也支持多态。那么,类的多态是什么意思?它又有什么样的好处?多态,使得继承体系中的多个类都能以各自所独有的方式来实现某个方法。这些类,都满足相同的接口和继承自相同的抽象类,但却有着各自不同的功能(关于多态的范例,参考该书第28条)。例如,为了实现一套 MapReduce 流程,我们需要定义公共基类来表示输入的数据。下面这段代码就定义了这样的基类,它的read方法必须由子类来实现:...原创 2021-02-18 11:32:34 · 195 阅读 · 5 评论 -
每日10行代码120: 编写高质量python代码的方法23:简单的接口应该接受函数,而不是类的实例
python 有许多内置的 API ,都允许调用者传入函数,以定制其行为。API在招待的时候,会通过这些挂钩(hook)函数, 回调函数内的代码。例如,list 类型的 sort 方法接受可选的 key 参数,用以指定每个索引位置上的值之间该如何排序。 下面这段代码,用 lambda 表达式充当key挂钩,以便根据每个名字的长度来排序:names = ['Socrates', 'Archimedes', 'Plato', 'Aristotle']names.sort(key=lambda x:len(x原创 2021-02-16 22:12:40 · 195 阅读 · 2 评论 -
每日10行代码119: 编写高质量python代码的方法22:尽量用辅助类来维护程序的状态,而不要用字典和元组
python内置的字典类型可以很好地保存某个对象在其生命周期里的动态内部状态。所谓动态(dynamic),是指这些待保存的信息,其标志符无法提前获知。例如,要把许多学生的成绩记录下来,但这些学生的名字,我们事先并不知道。于是,可以定义一个类,把学生名字字典里面,这样就不用把每个学生都表示成对象了,也无需在每个对象中预设一个存放其名字的属性。...原创 2021-02-13 10:52:12 · 218 阅读 · 1 评论 -
每日10行代码118: 编写高质量python代码的方法21:用只能以关键字形式指定的参数来确保代码明晰
按关键字传递参数,是python函数的一项强大特性,参见:(https://blog.csdn.net/weixin_44981444/article/details/113738138)由于关键字参数很灵活,所以在编写代码时,可以把函数的用法表达得更加明确。例如,要计算两数相除的结果,同时 要对计算时的特殊情况进行小心的处理。有时我们想忽略 ZeroDivisionError异常并返回无穷。有时又想忽略 OverflowError异常并返回0.def safe_division(number, di原创 2021-02-10 16:15:16 · 103 阅读 · 1 评论 -
每日10行代码117: 编写高质量python代码的方法20:用None和文档字符串来描述具有动态默认值的参数
有时我们想采用一种非静态的类型,来做关键字参数的默认值。例如,在打印日志消息的时候,要把相关事件的记录时间也标注在这条消息中。默认情况下,消息里面所包含的时间,应该是调用log函数那一刻的时间。如果我们以为参数的默认值会在每次执行函数时得到评估,那可能会写出下面这种代码:from datetime import datetimefrom time import sleepdef log(message, when=datetime.now()): print('%s: %s' %(when,原创 2021-02-10 11:26:24 · 153 阅读 · 1 评论 -
每日10行代码116: 编写高质量python代码的方法19:用关键字参数来表达可选的行为
与其他编程语言一样,调用python函数时,可以按位置传递参数。def remainder(number, divisor): return number % divisorassert remainder(20,7) ==6 python中所有的位置参数,都可以按关键字传递。关键字参数的顺序不限,但位置参数必须在关键字参数之前。remainder(20,divisor = 7)remainder(number =20,divisor=7)remainder(divisor=7,nu原创 2021-02-07 15:54:38 · 123 阅读 · 0 评论 -
每日10行代码115: 编写高质量python代码的方法18:用数量可变的位置参数减少视觉杂讯
令函数接受可选的位置参数(由于这种参数习惯上写为 *args, 所以又称为star args,星号参数),能够使代码更加清晰,并能减少视觉干扰。例如,要定义log(日志, 不是对数)函数,以便把某些调试信息打印出来。假如该函数的参数个数固定不变,那它就必须接受一段信息及一份含有待打印值的列表。def log(message,values): if not values: print(message) else: values_str = ', '.join原创 2021-02-05 11:21:55 · 106 阅读 · 0 评论 -
每日10行代码107:python读取文本中存储多行数据的最佳实践
有时候我们可能会经常需要处理一些文本文件,这些文件里每一行 就是一条数据,我们在写程序时,很自然的会想把这些数据读出来放到一个列表里来使用。常规的写法可能是这样的:f = open('pachong.py',encoding='utf-8')lines = f.readlines()print(lines)>>>['from\n', '\n', 'driver = webdrivern\n',...]这样的代码有一个问题,就是每一行后有一个换行,但换行又不是我们数据的一部分,原创 2021-01-23 12:05:21 · 390 阅读 · 2 评论 -
每日10行代码106: 编写高质量python代码的方法17:在参数上面迭代时,要多加小心
如果函数接受的参数是个对象列表,那么很有可能要在这个列表上多次迭代。例如,要分析美国texas旅游的人数。 假设数据集是由每个城市的游客数量构成的。现在要统计每个城市旅游的人数,占总游客数的百分比。为此,可以编写一个函数,它会把所有的输入值加总,以求出每年的游客总数。然后,用每个城市的游客数除以总数,以求出该城市所占的比例。def normalize(numbers): total = sum(numbers) result = [] for value in numbers: percent原创 2021-01-21 09:06:00 · 111 阅读 · 0 评论 -
每日10行代码105: 编写高质量python代码的方法16:考虑用生成器来改写直接返回列表的函数
如果函数要返回一系列结果,那么最简单的做法就是把这些结果都放在一个列表里返回。例如,我们要查出字符串中每个单词的首字母的位置。下面这段代码是可能的一种实现:def index_words(text): result = [] if text: result.append(0) for index,letter in enumerate(text): if letter == ' ': result.append(index+1) return resultaddress = 'F原创 2021-01-19 16:32:17 · 105 阅读 · 0 评论 -
每日10行代码104: 编写高质量python代码的方法15:了解如何在闭包里使用外围作用域中的变量
本条内容比较多,我分了两篇来写:上一篇在这:https://editor.csdn.net/md/?articleId=112461408上一篇内容主要是不能在内部函数中直接给外部函数的的变量附值,如果要附值可以用nolocal的方法。但是nolocal方法也有问题,由他产生的bug难以调试。一是,过度的用nolocal可能会在不必要的时候修改了外部变量;二是在外部定义变量的位置、nolocal定义位置、变量使用位置三者的跨度会很大,导致代码难以理解阅读。所以nolocal的代码要保持简单,如果已经越原创 2021-01-18 10:40:14 · 150 阅读 · 0 评论 -
每日10行代码101:不能在内部函数中给外部函数的的变量附值
numbers = [8,3,1,2,5,4,7,6]group = {2,3,5,7}#sort_priority(numbers, group)#print(numbers)def sort_priority2(numbers, group): found = False def helper(x): if x in group: found = True return (0,x) return (1,x) numbers.sort(key=helper) ret原创 2021-01-11 09:25:45 · 86 阅读 · 0 评论 -
每日10行代码100:python在排序时把某些元素人为排在最前或者最后
假如有一份列表,其中的元素都是数字,现在要对其排序,但排序时,要把出现在某个群组岗位的数字,放在群组外的那些数字之前。这种用法在绘制用户界面时候可能会遇到,我们可以用这个办法把重要的消息或意外的事件优先显示在其他内容前面。实现该功能的一种常见方法,是在调用列表的sort方法时,把辅助函数传给key参数。这个辅助函数的返回值,将会用来确定列表中各元素的顺序。辅助函数可以判断受测元是否处在重要群组中,并据此返回相应的排序关键字(sort key).def sort_priority(values, grou原创 2021-01-11 08:48:41 · 845 阅读 · 0 评论 -
每日10行代码99:为什么编程语言要有异常处理?
以前对异常的认识不是很深,最近通过学习,对异常处理有了一定的理解:举个例子:假如有一个会做菜的机器人,为他编写一个程序让他做菜。某天一位客人点了许多个菜,生成了一个菜单,正常情况下这个机器人可能会按这个菜单依次去做菜,并且可以做好。但是这里有太多的情况会影响到做菜了,比如:某道菜的某个配菜没了没有调料了没有盛菜用的盘子了世界大战了机器人本身没电了外星人入侵地球了假如没有异常处理,那就只能用if来处理一些特殊的情况,一些能遇见的情况,可以用if来处理,但是还有很有情况无法预料,这时就需要异原创 2021-01-10 22:49:51 · 196 阅读 · 0 评论 -
每日10行代码98: 编写高质量python代码的方法14:尽量用异常来表示特殊情况,而不要返回None
编写工具函数(utility function)时,python程序员喜欢给None这个返回值赋予特殊意义。这么做有时是合理的。例如,要编写辅助函数,计算两数相除的商。在除数为0的情况下,计算结果是没有明确含义的(undefinde,未定义的),所以似乎应该返回None.def divide(a,b): try: return a/b except ZeroDivisionError: return None函数的调用者,可以对这种特殊的返回值做出相应的解读。result = divi原创 2021-01-05 16:46:37 · 153 阅读 · 0 评论 -
每日10行代码97: 编写高质量python代码的方法8:不要使用含有两个以上表达式的列表推导
除了基本的用法之外,列表推导也支持多重循环。例如,要把矩阵(也就是二维列表)简化成一维列表,使原来的每个单元格都成为新列表中的普通元素。这个功能采用包含两个for表达式的列表推导即可实现,这些for表达式会按照从左至右的顺序来评估。matrix = [[1,2,3], [4,5,6], [7,8,9]]flat = [x for row in matrix for x in row]print(flat)>>>[1,2,3,4,5,6,7,8,9]上面这个例子简单易易懂,这就原创 2021-01-04 09:39:21 · 117 阅读 · 0 评论 -
每日10行代码96:编写高质量python代码方法13——合理利用try/except/else/finally结构中的每个代码块
python程序的异常处理可能要考虑四种不同的时机。这些时机可以用try , except, else和finally块来表述。复合语句中的每个块都有特定的用途,它们可以构成多中有用的组合方式。finally块如果既要将异常向上传播,又要在异常发生时执行清理工作,那就可以用try/finally结构。这种结构有一项常见的爱得得体,就是确保程序能够可靠地关闭文件句柄。handle = open('tmp/random_data.txt') # May raise IOErrortry:原创 2021-01-03 17:45:07 · 131 阅读 · 0 评论 -
每日10行代码95:编写高质量python代码方法12——不要在for和while循环后面写else块
注:本章内容不太重要,因为我们一般也确实不用else块,所以写简略点。python提供了一种很多编程语言都不支持的功能,那就是可以在循环内部的语句块后面直接编写else块。for i in range(3): print('Loop %d'%i)else: print('Else block!')输出结果:Loop 0Loop 1Loop 2Else block!else块会在整个循环完之后立刻执行,但是我假如直接写到for循环后,还是不是会立即执行吗? 既然如此,那这原创 2021-01-03 16:43:31 · 145 阅读 · 0 评论 -
每日10行代码94:编写高质量python代码方法11——用zip函数同时遍历两个迭代器
在编写python代码时,我们通常要面对很多列表,而这些列表里的对象,可能也是相互关联的。通过列表推导,很容易就能根据某个表达式从源列表推算出一份派生类表。names = ['Cecilia', 'Lise', 'Marie']letters = [len(n) for n in names]对于本例中的派生列表来说,相同索引处的两个元素之间有着关联。如果想平等地迭代这两份列表,那么可以根据names源列表的升序来执行循环。for i in range(len(names)): count原创 2021-01-03 08:03:36 · 203 阅读 · 2 评论 -
每日10行代码93:编写高质量python代码方法10——尽量用enumerate取代range
这一章的内容写的有些啰嗦,我适当精简下。假如有一个列表,遍历的时候同时想遍历到内容和索引。一般情况下我们可能会这样做:for i in range(len(flavor_list)): flavor = flavor_list[i] print('%d: %s'%(i+1, flavor))这种代码不便于理解,也不够优雅,python中有个函数专门解决这个问题,那就是enumerate(). enumerate 可以把各种迭代器包装为生成器,以便稍后输出值。生成器每次 产生一对输出值原创 2021-01-02 23:27:38 · 182 阅读 · 0 评论 -
每日10行代码92:编写高质量python代码方法9——用生成器表达式来改写数据量较大的列表推导
列表推导的缺点是:在推导过程中,对于输入的每个值来说,可能都要创建仅含一项元素的全新列表。当输入的数据比较少时,不会出问题,但如果输入的数据非常多,那么可能消耗大量的内存,并导致程序崩溃。例如,人读取一份文件并返回每行的字符数。若采用列表推导来做,则需把文件每一行的长度都保存在内存中。如果这个文件特别大,或是通过无休止的network socket(网络套接字)来读取,那么这种列表推导就会出问题。下面的这段列表推导代码,只适合处理少量的输入值。value = [len(x) for x in open(原创 2021-01-02 23:08:08 · 148 阅读 · 0 评论 -
每日10行代码90:编写高质量python代码方法7——用列表推导来取代map和filter
python提供了一种精练的写法,可以根据一份列表来制作另外一份。这种表达式称为list comprehension(列表推导)。例如,要用列表中每个元素的平方值构建成另一份列表。如果采用列表推导式来实现,那么就是如下这样的:...原创 2020-12-27 16:57:43 · 171 阅读 · 0 评论 -
每日10行代码71:编写高质量python代码方法6——在单次切片操作内,不要同时指定start, end和stride
除了基本的切片操作之外,Python还提供了somelist[start????stride]形式的写法,以实现步进式切割,也就是从每n个元素里取1个出来,例如,可以指定步进值,把列表中位于偶数索引处和奇数索引处的元素分成两组:a = ['red', 'orange', 'yellow', 'green', 'blue', 'purple']odds = a[::2]evens = a[1::2]print(odds)print(evens)输出结果:['red', 'yellow', 'b原创 2020-11-21 10:58:14 · 194 阅读 · 0 评论 -
每日10行代码52:编写高质量python代码方法4——用辅助函数来取代复杂的表达式
今天看了effective python第4条,有所启发。from urllib.parse import parse_qs# 要从url中解码查询字符串,在下例中,每个参数表示一个整数值:my_values = parse_qs('red=5&blue=0&green=',keep_blank_values=True)print(my_values)print(repr(my_values))print('Red: ',my_values.get('red'))prin原创 2020-10-15 23:55:18 · 257 阅读 · 0 评论 -
每日10行代码68:编写高质量python代码的方法3——了解bytes,str与unicode的区别
这是《ffective Python》的第3个方法,核心内容就是介绍了bytes和str的区别,至于unicode介绍的不是很详细。书中主要内容:用辅助函数来处理编码。def to_str(bytes_or_str): if isinstance(bytes_or_str, bytes): value = bytes_or_str.decode('utf-8') else: value = bytes_or_str return value原创 2020-11-14 10:21:42 · 105 阅读 · 0 评论 -
每日10行代码55:编写高质量python代码的方法2——遵循PEP8风格指南
编写高质量python代码的方法2:遵循PEP8风格指南PEP8指《Python Enhancement Proposal #8》 (8号Python增强提案),它是针对Python代码格式而编订的风格指南。采用一致的风格来可以令代码更加易懂、更加易读。下面是书中列出的几条绝对应该遵守的规则:空白:Python中空白会影响代码的含义。Python程序员使用空白的时候尤其在意,因为它们还会影响代码的清晰程度。使用space(空格)来表示缩进,而不要用tab(制表符)。和语法相关的每一层缩进都用4个原创 2020-10-18 21:25:18 · 174 阅读 · 0 评论 -
每日10行代码54:编写高质量python代码方法1——确认自己所用的python版本
确定自己所有python版本的三种方法:直接在命令窗口里输入python用sys库输出>>> import sys>>> print(sys.version_info)sys.version_info(major=3, minor=6, micro=8, releaselevel='final', serial=0)在命令窗口输入python --version要点:有两个版本的python处理活跃状态,它们是:python2和python原创 2020-10-16 23:52:03 · 200 阅读 · 0 评论 -
每日10行代码53:编写高质量python代码方法5——了解切割序列(分片)的方法
今天继续看effective python第5章# 切片可以在list,str,bytes上进行切割,用法是 somelist[start:end] 其中start(起始索引)所指的元素涵盖在切割范围中,而end(结束索引)所指的元素不在切割范围中。a = ['a', 'b','c', 'd', 'e', 'f', 'g', 'h']print('First four:', a[:4])print('Last four:', a[-4:])print('Middle two:', a[3:-3]原创 2020-10-16 23:36:19 · 145 阅读 · 0 评论