自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(39)
  • 收藏
  • 关注

原创 LNCS 模版下载

摘要部分简要概述论文内容,关键词用于描述文档的主要话题。

2024-04-12 16:21:23 395

原创 编写高质量Python (第35条) 不要通过 throw 变换生成器状态

​ 生成器函数可以用标准的 try/expect 复合语句把 yield 表达式包裹起来,如果函数执行到了这条表达式这里,而这次即将继续执行时,又发现外界通过 throw 方法给自己注入了异常,那么这个异常就会被 try 结构捕获下来,如果捕获之后不继续抛出异常,那么生成器函数就会推进到下一条 yield 表达式(更多异常处理,参见 第 65 条)。例如,要编写一个可以重置的计时器程序。如果确实遇到了这里讲到的这种需求,那么更应该通过可迭代的类实现生成器,而不要用 throw 方法注入异常。

2024-03-03 19:34:14 365

原创 编写高质量Python (第34条) 不要用 send 给生成器注入数据

所以,complex_wave_modulating 函数处理完前一个嵌套的生成器之后,会进入下一个嵌套的生成器,而这时就必须先把生成器的第一条 yield 语句运行过去,这就导致后面两个嵌套生成器会各自从 amplitudes 列表里浪费一个值,并使得每个嵌套生成器所拿到的第一个结果必定是 None,还会让最后那个嵌套生成器少执行两次。​ 最简单的方法,是把迭代器传给 wave 函数,让 wave 每次用到振幅的时候,通过 Python 内置的 next 函数推进这个迭代器并返回一个输入振幅。

2024-02-29 14:28:01 955

原创 编写高质量Python (第33条) 通过 yield from 把多个生成器连起来用

下面的函数用三个 for 循环来表示动画的三个环节,在每个环节里,它都通过 yield 把图片当前的位置与上一次的位置之差 delta 返回给调用者。这种形式,会先从嵌套进去的小生成器里面取值,如果生成器已经用完,那么程序的控制流程会回到 yield from 这个函数中,然后它有可能进入下一套 yield from 逻辑。Python 解释器看到 yield from 形式的表达式后,会自己想办法实现与带有普通 yield 语句的 for 循环相同的结果,而且这种实现方式要更快。

2024-02-29 13:47:32 578

原创 编写高质量Python (第32条) 考虑用生成器改写数据量较大的列表推导

程序在对生成器表达式求值时,并不会让它把包含输出结果的那个序列立刻构建出来,而是会把它当成一个迭代器,该迭代器每次可以根据表达式中的逻辑给出一项结果。​ 例如,我们要读取一份文件并返回每行的字符数。​ 这条表达式所形成的 roots 迭代器每次推进时,会引发连锁反应:它也推进内部迭代器 it 以判断当前是否还能在 it 上面继续迭代,如果可以,就把 it 所返回的值代入(x, x ** 0.5) 里面求出结果。例如,可以用刚才那条生成器表达式所形成的 it 迭代器作为输入,编写一条新的生成器表达式。

2024-02-28 17:03:23 340

原创 编写高质量Python (第31条) 谨慎地迭代函数所收到的参数

​ 明白了 ReadVisits 这种容器的工作原理后,我们就可以在编写函数和方法时先确认一下,收到的应该是像 ReadVisits 这样的容器,而不是普通的迭代器。​ 这种自定义容器的方案,最适合于既不想像 normalize_copy 函数一样,把迭代器提供的这套数据全部复制一份,同时又要多次遍历这套数据的情况。​ 为了求出这份数据,笔者编写了一个归一化函数 normalize ,它把列表的所有元素加起来求出游客总数,然后,分别用每个城市的游客数除以游客总数计算出该城市在总数据中所占的比例。

2024-02-28 17:02:24 450

原创 编写高质量Python (第30条) 不要让函数直接返回列表,应该让它逐个生成列表里的值

每找到一个新单词,它都要调用 append 方法,而调用这个方法时,必须写上 result.append 这样一串字符串,这就把我们想要强调的重点,也就是这个新单词在字符串中的位置(index + 1)淡化了。​ 这次的 index_words_list 函数,比刚才的那个函数好懂的多,因为它把设计到列表的操作全部都简化掉了。把刚才那份输入数据存放在 address.txt 文件,让这个函数去读取并用它返回的生成器构建一份列表,可以看到跟原来相同的效果(islice 函数的详细用法,参见第 36 条)。

2024-02-28 17:01:10 460

原创 编写高质量Python (第29条) 用赋值表达式消除推导中的重复代码

例如,我们决定每一批不是 8 个,而是 4 个,那么需要把 get_batches 的第二个参数从 8 改成 4,但是,万一我们忘了同步修改另一个地方,那么代码就会出现问题(它会把大于等于 4 但是小于 8 的情况给漏掉)。顾客下单后,我们要判断当前的库存能否满足这份订单,也就是说,要核查每种产品的数量有没有达到可以发货的最低限制(8 个为一批,至少要有一批,才能发货)。下面这种写法创建的是迭代器,而不是字典实例,该迭代器会给出一对数值,其中第一个元素为产品的名字,第二个元素为这种产品的库存。

2023-12-07 20:02:34 399 1

原创 Python 上下文管理器 with 相关用法

一个上下文管理器是一个对象它定义了运行时的上下文使用 with 语句来执行。

2023-12-06 18:49:39 386

原创 Python 实现抽象类

抽象类是一个不能被实例化的类。抽象方法是一个没有具体实现的方法。一个抽象类可以有或者没有抽象方法。Python 并没有直接支持抽象类,但提供了一个抽象模块(abc)允许定义抽象类。通过继承 abc.ABC 类定义一个抽象类。pass使用 @abstractmethod 来定义抽象方法。pass。

2023-12-06 18:46:46 399

原创 编写高质量Python (第28条) 控制推导逻辑的字表达式不要超过两个

这看起来有点儿复杂,因为它把小的推导逻辑 [x ** 2 for x in row] 嵌到了大的推导逻辑里面,不过,这行语句总体上不难理解。例如,如果要用原列表中大于 4 且是偶数的值来构建新列表,那么既可以连用两个 if,也可以只用一个 if,下面两种写法效果相同。​ 总之,在表示推导逻辑时,最多只应该写两个字表达式(例如两个 if 条件、两个 for 循环,或者一个 if 条件与一个 for 循环)。例如,要把矩阵转化为普通的一维列表,那么可以在推导时,使用两条 for 字表达式。

2023-12-05 14:55:55 357

原创 编写高质量Python (第27条) 用列表推导取代 map 与filter

​ 这种功能当然也可以用内置函数 map 实现,它能够从多个列表中分别取出当前位置上的元素,并把它们当成参数传给映射函数,以求出新列表在这个位置上的元素值。如果映射关系比较简单(假如只是把一个列表映射到另一个列表),那么用列表推导来写还是比用 map 简单一些,因为用 map 的时候,必须先把映射逻辑定义为 lambda 函数,这看上去稍微有点繁琐。假如我们要使用列表中每个元素的平方值构造一份新的列表。​ 上面那段代码可以改用列表推导来写,这样可以在迭代列表的过程中,根据表达式酸楚新列表的对应元素。

2023-12-04 16:55:34 376

原创 编写高质量Python (第26条) 用 functools.wraps 定义函数装饰器

​ Python 中有一个特殊写法,可以用装饰器来封装某个函数,从而让函数在执行这个函数之前与执行完这个函数之后,分别运行某些代码。这意味着,调用者传给参数的参数值、函数返回给调用者的值,以及函数抛出的异常,都可以由装饰器访问并修改。这是个很有用 的机制,能够保证用户以正确的方式使用函数,也能用来调试程序或实现函数注册功能,此外还有很多用途。​ 例如,假设我们要把函数执行时收到的参数与返回的值记录下来。

2023-12-02 22:27:41 970

原创 编写高质量Python (第25条) 用只能以关键字指定和只能按位置传入的参数来设计清晰的参数列表

​ 在函数的参数列表中,/ 符号左侧的参数是智能按位置指定的参数,* 符号右侧的参数则是只能按关键字形式指定的参数。这是个值得注意的问题。这意味着,这两个符号的参数,既可以按位置提供,又可以用关键字形式指定(其实,如果不特别说明 Python 函数的参数全都属于这种参数).在设计 API 时,为了体现某编程风格或者实现某些需求,可能会允许某些参数既可以按照位置传递,也可以用关键字形式指定,这样可以让代码易读。参数列表里的 * 符号把参数分成两组,左边是位置参数,右边是只能用关键字指定的参数。

2023-12-01 11:45:00 825

原创 编写高质量Python (第24条) 用 None 和 docstring 来描述默认值会变的参数

参数的默认值只会在系统加载这个模块的时候,而不会在每次执行时都重新计算,这通常意味着这些默认值在程序启动后,就已经定下来了。系统只会计算一次 default 参数(在加载这个模块的时候),所以每次调用这个函数时,给调用者返回都是一开始分配的那个字典,这就相当于是以默认值调用这个函数的代码都共用同一份字典。​ 要想在 Python 里实现这种效果,惯用的办法是把参数的默认值设为 None,同时在 docstring 文档里面写清楚,这个参数为 None时,函数怎么运作(参见 第84条)。

2023-12-01 00:24:47 397

原创 编写高质量Python (第23条) 用关键字来表示可选的行为

​ 关键字参数的第三个好处是,我们可以很灵活地扩充函数的参数,而不用担心会影响原有的函数调用代码。​ 定义函数时,如果想让这个函数接收任意数量的关键字参数,那么可以在参数列表里写上外能形参 **kwargs, 它会把调用者传进来的参数收集合在一个字典里面稍后处理(第26条 讲了一种特别适合这么做的情况)。​ 如果有一份字典,而且字典里面的内容能够用来调用 remainder 这样的函数,那么可以把 ** 运算符加在字典前面,这会让 Python 把字典里面的键值以关键字参数的形式传给函数。

2023-11-29 15:03:15 716

原创 编写高质量Python (第22条) 用数量可变的位置参数给函数设计清晰的参数列表

这意味着,如果调用函数时,把带 * 操作符的生成器传了过去,那么程序必须先把这个生成器的所有元素迭代完(以便形成元组),然后才能继续往下进行(相关知识,参见 第30条)。在 Python 里,可以给最后一个位置参数加上前缀 *,这样调用者就只需要提供不带星号的那些参数,然后可以不再指其他参数,也可以继续指定任意数量的位置参数。函数的主题代码不用改,只修改调用代码即可。​ 如果想想把已有序列(例如某列表)里面的元素当成参数传给像 log 这样的参数个数可变的函数,那么可以在传递序列的时采用 * 操作符。

2023-11-28 19:42:06 379

原创 编写高质量Python (第21条) 了解如何在闭包里面使用外围作用域的变量

如果当前作用域中不存在这个变量,那么即便外围作用域里有同名的变量,Python 也还是会把这次的赋值操作当成变量的定义来处理,这会产生一个重要的效果,也就是说,Python 会把包含赋值操作的这个函数当成新定义的这个变量的作用域。有一种跟它互补的语句,叫做 gloabl,用这个语句描述某个变量,叫做 global,用这种语句描述某个变量后,在给这个变量赋值时,系统会直接把它放到模块作用域(或者说全局作用域)中。​ 有时,我们要给列表里面的元素排序,而且要优先把某个群组之中的元素放在其他元素的前面。

2023-11-28 19:40:41 332

原创 编写高质量Python (第20条) 遇到意外状况时应该抛出异常,不要返回 None

然而,Python 采用的是动态类型与静态类型相搭配的 graudal 类型系统,我们不能在函数的接口指定函数可能抛出哪些异常(有的编程语言支持这样的受检异常(checked exception),调用方必须应对这些异常)。在这种情况下,只要除数不为 0,函数返回的结果就应该是0.问题是,这个函数的返回值有时可能会用在 if 条件语句里面,那时可能会根据值本身是否相当于 False 来做判断,而不是像刚才那样明确判断这个值是否为 None(第 5 条 也列举了这样的一个例子)。

2023-11-27 20:20:19 354

原创 编写高质量Python (第19条) 不要把函数返回的多个数值拆分到三个以上的变量

假如要拆分的值确实很多,那最好还是定义一个轻便的类或 nametuple (参见 第37条),并让函数返回这样的实例。​ 函数返回的其实是个元组(tuple),同时返回的那两个值就是元组的两个元素。(参见 第 13 条 )。该函数会把比值放在列表中返回,但我们在接收的时候,可以只接收最长与最短的那两条鳄鱼的比值,而把中间那些鳄鱼的比值用带星号的写法总括。第二个问题就是,调用函数并拆分返回值的那行代码会写的特别长,所以按照 PEP 8 风格指南,需要折行(参见 第 2 条),这样让代码看着别扭。

2023-11-27 20:18:47 331

原创 编写高质量Python (第18条) 学会利用 __ missing __ 构造依赖键的默认值

首先,即便图片的路径名已经在字典里面了,程序还是得调用内置的 open 函数创建文件句柄,于是导致这个程序要给眼睛创建过 handle 的那份文件再度创建 handle (两者可能相互冲突)。另外,如果 try 块抛出异常,那我们可能无法判断这个异常是 open 函数导致的,还是 setdefault 方法导致的,因为这两次调用全都写在同一行代码里(其他类似字典的实现方案或许可以做到,参见 第 43 条)。下面定义一个新的类,让它利用刚才写的那个辅助函数来实现 __ missing __方法。

2023-11-27 20:17:51 751

原创 编写高质量Python (第17条) 用 defaultdict 处理内部状态缺失的元素,而不要用 setdefault

​ 好在 Python 内置的 collections 模块提供了 defaultdict 类,它能够轻松地实现出刚才那套逻辑,因为它会在键缺失的情况下,自动添加这个键以及键所对应的默认值。另外,这种写法也不够高效,因为每次调用 add 方法时,无论 country 参数所指定的国家名称是否在字典里,都必须构造新的 set 实例。​ 无论字典中有没有这个国家名称,都可以通过 setdefault 方案来把新的城市添加到对应的集合里,这要比利用 get 方法与赋值表达式来实现的方案短很多。

2023-11-27 20:17:00 360

原创 编写高质量Python (第16条) 用 get 处理键不在字典里面的情况,不要使用 in 与 KeyError

​ 这样写的问题时,根本没必要调用 setfault,因为不管字典有没有这个键,我们都要递增它对应的值,在字典没有这个键的情况下,这种写法会先通过 setdefault 把默认值赋给这个键,然后再通过 counters[key] = count + 1 把递增之后的值更新到字典中,这其实是完全没有必要。​ 在这个方案中,无论 votes.get(key) 的结果是不是 None,都要先把这个结果赋给 names 变量,只不过在结果是 None 的时候,还需要在 if 块中做一些处理。

2023-11-27 20:15:19 917

原创 编写高质量Python (第15条) 不要过分依赖给字典添加条目时所用的顺序

Python 不是静态的语言,大多数代码都以鸭子类型(duck typing)机制运作(也就是说,对象支持什么样的行为,就可以当作什么样的数据来使用,而不用执着于它在类体系中的地位)。​ 在 Python3.5 与之前的版本中,迭代字典(dict)时所看到的顺序好像是任意的,不一定与当初把这些键值对添加到字典时的顺序时相同。这个类的功能跟字典一样,而且会按照字母顺序迭代其中的内容。​ 创建字典时,先添加的时 ‘cat’,后添加的是’dog’,但在打印的时候,'dog’却出现在了 ‘cat’ 的前面。

2023-11-27 20:13:43 929

原创 编写高质量Python (第14条) 用 sort 方法的 key 参数来表示复杂的排序逻辑

于是,在 sort 方法的排序结果中,它们之间的先后次序就跟在第一轮结束的次序相同。例如,下面的这个 places 列表中存放着表示地点的字符串,如果想在排序的时候忽略大小写,那我们可以用 lower 方法把待排序的字符串处理一下(因为对于字符串来说,自然顺序就是它们在词典里面的顺序,而词典中的大写字母在小写字母之前。key 所表示的函数本身应该带有一个参数,这个参数指代列表中有待排序的对象,函数返回的应该是个可比较的值(也就是具备自然顺序的值),以便 sort 方法以该值为标准值给这些对象排序。

2023-11-27 20:11:57 1025

原创 编写高质量Python (第13条) 通过带星号的 unpacking 操作来捕获多个元素,不要用切片

源自 Effective Python 第二版

2023-10-20 21:25:21 49 1

原创 编写高质量Python(第12条) 不要在切片中同时指定上标和下标

源自 Effective Python 第二版

2023-10-20 21:08:58 43 1

原创 Python标准库 —— math库

本文介绍了 Python math库的全部内容,math库主要用于数字计算。

2023-10-10 13:20:35 2273 1

原创 编写高质量Python(第11条) 学会对列表切片

源自 Effective Python 第二版

2023-10-09 21:37:28 48 1

原创 编写高质量Python(第10条) 用赋值表达式减少重复代码

源自 Effective Python(第二版)

2023-10-09 21:35:38 55 1

原创 编写高质量Python(第9条) 不要在 for 与 while 后面写 else 块

源自Effective Python第二版

2023-10-09 13:35:17 43 1

原创 编写高质量Python(第8条) 用zip函数同时遍历两个迭代器

源自Effective Python(第二版)

2023-10-09 13:30:05 81 1

原创 编写高质量Python(第7条) 尽量用enumerate取代range

源自Effective Python(第二版)

2023-10-05 12:54:39 48

原创 编写高质量Python(第6条) 把数据结构拆分到多个变量里,不要专门通过下标访问

源自Effective python(第二版)

2023-10-05 10:03:37 61

原创 编写高质量Python(第5条)用辅助函数取代复杂的表达式

源自Effective python(第二版)

2023-10-05 10:03:04 38

原创 编写高质量Python(第4条)用支持插值的 f-string 取代 C 风格的格式字符串与 str.format 方法

源自Effective python(第二版)

2023-09-30 20:57:34 50

原创 编写高质量Python (第3条) 了解 bytes 与 str 的区别

源自Effective python(第二版)

2023-09-30 20:52:40 35

原创 编写高质量Python(第2条)遵循 PEP 8 风格指南

源自Effective python(第二版)

2023-09-30 20:42:56 38

原创 编写高质量python(第1条)查询自己使用的 Python 版本

源自Effective python(第二版)

2023-09-30 20:40:37 60

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除