小心 Python 函数默认参数的陷阱

Python 的函数参数支持默认值,这是本人一直喜欢的特性,Python 不支持方法重载,但默认参数可起到类似的效果,还不用写多个函数。现在支持默认参数的语言普遍的,像 C++, C#, Ruby, Groovy, PHP, Scala, JavaScript 等,Java 还不行。

但是特别要小心,Python 的函数默认值与其他的语言是不同的,直接违反了最直观的常识 -- 默认参数应该是省略就每次用同样的默认值,传的话就用传入的值。

当我在 IntelliJ IDEA 中写类似如下的代码

我的 SonarLint 插件就要抱怨了

说是

SonarLint: Change this default value to "None" and initialize this parameter inside the function/method
Default argument value is mutable

阅读全文 >>

类别: Python. 标签: . 阅读(17). 评论(0) »

Flask 应用集成 Swagger UI

成熟的 Web  API 框架总有一款 API 文档与之伴随,当前最知名的莫过于支持 Open API 的 Swagger 了。Python 的 Flask 框架支持 Swagger UI 也有几条路子

  1. Flasgger : 好像是 flask-swagger 的 fork
  2. flask-swagger: 许久未更新了,不用考虑
  3. flask-restful-swagger: 到目前也两年未更新了
  4. Flask-RESTPlus 的 Swagger 特性: 真需要用到 Flask-RESTPlus 就可以用它

单纯用 Flask 构建 API 的话,细数起来也就 Flasgger 比较合适,如果甩开 Flask 而用 FastAPI 的话,就不用操心 Swagger 了,因为 FastAPI 原生的支持 Swagger。

本文中我们将体验如何使用 Flasgger, 关于使用方法,在它源码的 README.md 已经描述的很清楚了。Flasgger 提供了以下几种主要的使用方式 阅读全文 >>

类别: Flask. 标签: , . 阅读(98). 评论(0) »

创建和发布自己的 Python 包到 PyPI 上

像 Java 可发布包到 Maven 仓库,NodeJS 发布包到 NPM 一样,我们也可以创建自己的 Python 包并发布到 PyPI 仓库中去。或者内部使用的包,只须发布到私有的 Nexus 服务器上。

本文中的例子将创建一个 Python 包 bounded-executor, 并发布到 PyPI 上。为什么创建这个包呢?原因是直接用 Python 的 ThreadPoolExecutor 或  ProcessPoolExecutor 来提交任务的话,任务的等待队列是没有边界的,这就会造成因提交任务过快而使得内存爆满。本包最为合适的名称应该是 bounded-pool-executor, 可是名字已被他人使用,但此外的实现有所不同,ThreadPoolExecutor 用 Queue(maxsize) 来控制,而 ProcessPoolExceutor 用 BoundedSemaphore 来控制。

我们以经典的 Python 工程目录结构为例,构建的核心是执行 setup.py 中的 setup 函数,由此来理解 setup 的最主要配置与关键命令做了些什么。这样有助于我们理解其他的 Python 包管理工具的底层行为,从中我们可以对比 poetry 的 build, install, 和 publish 命令。 阅读全文 >>

类别: Python. 标签: , , . 阅读(125). 评论(0) »

创建 Python 的 list, set, tuple 和 dict

本文主要探讨一下在 Python 各种创建 list, set, tuple 和 dictionary 的方式。首先看

最常用的创建方式

以上相当于是针对右边的值调用了相应的构造函数,如 list([1, 2]), set({1, 2}), tupe((1, 2)), dict({'k1': 1, 'k2': 2})

创建 set 和 dictionary 都是用大括号 {}, 对于 tuple 如果是单个元素时,要附加一个逗号

如果省略逗号,会怎样呢? 阅读全文 >>

类别: Python. 标签: . 阅读(77). 评论(0) »

希尔(Shell) 排序 - 增强版插入排序算法

前面讲过的几种排序多是以排序逻辑来命名的,例如冒泡,选择和插入排序,以及其他如归并排序,当然还有觉得自己足够牛 X 快速排序命名。而本文要学习的排序算法叫做希尔排序是以其设计者 Donlad Shell 命令的排序算法,该算法在 1959 年公布,能以作者来命名的算法应该是很不错的,令设计者引以为傲的。最初写出冒泡和选择排序的就没以作者来命名,可能不好意说,更可能是公共思维。

那么什么是希尔排序呢?它实际上是插入排序算法的增强版本,又称递减增量排序算法。它对待排序列表进行间隔式分段插入处理,从而总体上减少了元素的移动次数而达到性能的大大提升。那么理解希尔排序之前一定要先了解插入排序。那么为什么说希尔排序既是递减又是增量呢? 阅读全文 >>

类别: Algorithm. 标签: , . 阅读(284). 评论(0) »

插入排序算法解析

前面说过最原始的复杂度为 O(n2) 的冒泡和选择排序,也跳跃到了复杂度为  O(n log n) 的快速排序,现在又再看一个复杂度同样为 O(n2) 的插入排序。从排序名称结合代码我们理解了为什么叫做冒泡或是选择,快速排序自认高名,那么何以这又谓之插入排序呢?是怎么插入,从左边往右边插,还是从右边往左边插,这得搞清它的排序原理:

它在列表较低的一端维护一个有序的子列表(从最左端一个元素开始),并逐个将每个新元素(高端的)"插入"这个子列表。插入的时候遍历低端列表,找准位置插入便是,插入点后的元素需后移,当所有高端的元素插入完成了,整个列表就变得有序了。

整个排序操作示意图如下: 阅读全文 >>

类别: Algorithm. 标签: , , . 阅读(184). 评论(0) »

理解 Python 类的变量,方法与属性

熟悉了传统的 C++/Java 类定义的风格,来感受一下 Python 是如何定义类的。本篇是阅读 《The Quick Python Book》第二版关于类定义的笔记,由原书内容进一步引申,不过是依照本人的思考顺序来组织的。在理解 Python 类定义的同时头脑中应该闪现出 JavaScript/Java 如何定义类的情景。

最简单的类定义

class MyClass:
    pass

由于 class MyClass 后面要有个冒号,而冒号后总得有点东西才能表示该类定义结束了,于是放个 pass 当占位符。Python 也像 Java 一样,有一个根类,叫做 object,例如上面的定义

我们能看到它隐式的基类是 object, 而不用显式的声明为 class MyClass(object)。看到 __bases__ 属性是一个 Tuple, 意识到  Python 是支持多重继承的。 阅读全文 >>

类别: Python. 标签: , . 阅读(89). 评论(1) »

Python 函数声明先后顺序的问题

在 Python 中如果把函数定义写在调用的下方可能会出错,例如下面的代码

foo()

def foo():
    print("hello")

执行时会报出错误

NameError: name 'foo' is not defined

这时候要把 foo() 调用代码放到该函数的声明后面

def foo():
    print("hello")

foo()

这样执行就一切正常了。这仿佛像是 C 语言中的函数调用需要提前声明一般,例如在 C 语言中要调用后头的定义的函数要写成 阅读全文 >>

类别: Python. 标签: , . 阅读(843). 评论(3) »

开启 Python 组件 Boto3 在 IDE 中的智能提示

在用 Python 编写 AWS 服务时,要用到 Boto 3 组件,而像 boto3.client('s3') 获得的对象只能被 IDE 识别为一个 BaseClient, 具体包含什么操作方法是在运行时由参数 s3 指示的基于 JSON 文件所描述的。因此 IDE 对 s3 = boto3.client('s3')s3 对象无法提供有效的智能提示,每次用 Boto 3 时不得不打开 Boto 3 的在线 API 文档来对照。长此以往,总觉麻烦且效率低下,有种一直摸着石头过河的感觉。那么,是否有办法让 IDE 智能提示出各种 boto3.client('<service>') 的实际操作呢?网上找了找,确实有这个需求,解决办法有

  1. botostubs: 与 boto3 API 保持更新(每三天),并支持众多 IDE, 试过在 IntelliJ IDEA 和 Visual Studio Code 中可用
  2. pyboto3: 上次更新在两年前, https://github.com/wavycloud/pyboto3, 只在 Python 2.7 下测试过
  3. autoboto: 需有智能提示,但改变了应用 Boto 3 组件的方式,不建议使用

本文重点推荐 botostubs, 下面会叙说具体理由,在进入正是之前,不妨来回顾一下直接使用 Boto 3 时没有好的智能提示的问题 阅读全文 >>

类别: AWS, Python. 标签: , , . 阅读(317). 评论(0) »

让 Python 的数据库查询返回字典记录

在使用  Python 进行数据库查询,通常情况下 cursor 的 fetchall, fetchmany 返回的是元组(Tuple) 的列表,所以对查询到的结果只能用索引下标来访问,而无法通过字段名来获取值。对 Java JDBC 的 ResultSet 操作,我们有两种获取值的方式,resultSet.getString(1) 和 resultSet.getString('name')。

其实只要能用数字索引访问到字段值也就足够了,查询后字段名可以由 cursor.description 获得。通过字段名来访问值唯一的好处估计是出错的概率小些罢了,比如 result['firstname'], result['lastname'] 总是比 result[1], result[2] 更不容易搞混,错误定位也会更轻松。

假如有下面的数据库表与两条记录 阅读全文 >>

类别: Python. 标签: , . 阅读(2,329). 评论(1) »