前面说过最原始的复杂度为 O(n2) 的冒泡和选择排序,也跳跃到了复杂度为 O(n log n) 的快速排序,现在又再看一个复杂度同样为 O(n2) 的插入排序。从排序名称结合代码我们理解了为什么叫做冒泡或是选择,快速排序自认高名,那么何以这又谓之插入排序呢?是怎么插入,从左边往右边插,还是从右边往左边插,这得搞清它的排序原理:
它在列表较低的一端维护一个有序的子列表(从最左端一个元素开始),并逐个将每个新元素(高端的)"插入"这个子列表。插入的时候遍历低端列表,找准位置插入便是,插入点后的元素需后移,当所有高端的元素插入完成了,整个列表就变得有序了。
整个排序操作示意图如下: Read More
熟悉了传统的 C++/Java 类定义的风格,来感受一下 Python 是如何定义类的。本篇是阅读 《The Quick Python Book》第二版关于类定义的笔记,由原书内容进一步引申,不过是依照本人的思考顺序来组织的。在理解 Python 类定义的同时头脑中应该闪现出 JavaScript/Java 如何定义类的情景。最简单的类定义
class MyClass:
由于
passclass MyClass后面要有个冒号,而冒号后总得有点东西才能表示该类定义结束了,于是放个pass当占位符。Python 也像 Java 一样,有一个根类,叫做 object,例如上面的定义1>>> MyClass.__bases__ 2(<class 'object'>,) 3>>> import inspect 4>>> inspect.getmro(MyClass) 5(<class '__main__.MyClass'>, <class 'object'>)
我们能看到它隐式的基类是object, 而不用显式的声明为class MyClass(object)。看到__bases__属性是一个 Tuple, 意识到 Python 是支持多重继承的。 Read More
在 Python 中如果把函数定义写在调用的下方可能会出错,例如下面的代码
1foo() 2 3def foo(): 4 print("hello")执行时会报出错误
NameError: name 'foo' is not defined
这时候要把
foo()调用代码放到该函数的声明后面1def foo(): 2 print("hello") 3 4foo()这样执行就一切正常了。这仿佛像是 C 语言中的函数调用需要提前声明一般,例如在 C 语言中要调用后头的定义的函数要写成 Read More

在用 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>') 的实际操作呢?网上找了找,确实有这个需求,解决办法有- botostubs: 与 boto3 API 保持更新(每三天),并支持众多 IDE, 试过在 IntelliJ IDEA 和 Visual Studio Code 中可用
- pyboto3: 上次更新在两年前, https://github.com/wavycloud/pyboto3, 只在 Python 2.7 下测试过
- autoboto: 需有智能提示,但改变了应用 Boto 3 组件的方式,不建议使用
本文重点推荐 botostubs, 下面会叙说具体理由,在进入正是之前,不妨来回顾一下直接使用 Boto 3 时没有好的智能提示的问题 Read More
在使用 Python 进行数据库查询,通常情况下cursor的fetchall,fetchmany返回的是元组(Tuple) 的列表,所以对查询到的结果只能用索引下标来访问,而无法通过字段名来获取值。对 Java JDBC 的 ResultSet 操作,我们有两种获取值的方式,resultSet.getString(1) 和 resultSet.getString('name')。
其实只要能用数字索引访问到字段值也就足够了,查询后字段名可以由cursor.description获得。通过字段名来访问值唯一的好处估计是出错的概率小些罢了,比如 result['firstname'], result['lastname'] 总是比 result[1], result[2] 更不容易搞混,错误定位也会更轻松。
假如有下面的数据库表与两条记录 Read More
作为一个 Java 为母语的程序员来讲,学习起其他新的语言就难免任何事都与 Java 进行横向对比。Java 7 引入了能省去许多重复代码的
try-with-resources特性,不用每回 try/finally 来释放资源(不便之处有局部变量必须声明在 try 之前,finally 里还要嵌套 try/catch 来处理异常)。比如下面的 Java 代码1try(InputStream inputStream = new FileInputStream("abc.txt")) { 2 System.out.println(inputStream.read()); 3} catch (Exception ex) { 4}它相应的不使用 try-with-resources 语法的代码就是 Read More

上一篇 Python 的模块搜索路径,介绍了 Python 的模块搜索路径,最终起作用的是
sys.path路径列表。如果要自定义自己的搜索路径,就是要怎么定制sys.path的内容。可以简单的用PYTHONPATH环境变量前向添加,这儿将要说的是用.pth文件的方式。也可由此进一步理解 Python 依赖管理工具,像virtualenv等的工作原理。.pth文件名是什么,无所谓,Python 只认扩展名。.pth文件中每行指定一个路径 -- 绝对或相对路径(相对于本.pth文件所在的目录),另外还可以空行或#开始的注释行,还能有import语句,大概只用来校验是否能导入成功,程序代码中还是需要显示的 import 模块。.pth文件放在哪里.pth文件创建好后应该放到哪里去呢?不是sys.prefix指示的位置,也不是sys.path中任意一个目录,而是sys.path中属于 site.packages 的某一个目录中。可以用1>>> import site 2>>> site.getusersitepackages() 3>>> site.getsitepackages()查看到, 看我在 Ubuntu Linux 中看到的内容(为便于阅读,显示列表内容时进行了换行处理) Read More

一种语言要使用到外部库(模块) 时必然会涉及到从哪里以及按何顺序加载依赖,就像 LD_LIBRARY_PATH, CLASSPATH 那样,Python 也有其默认的模块搜索顺序, 依序找到想要的模块即停止。Python 中
sys.path返回的列表包含了模块搜索的顺序,我们可以程序中修改该列表,或用PYTHONPATH环境变量前插路径,甚至是用.pth文件来附加路径。简单的,可以执行命令
python3 -c "import sys; print(str(sys.path).replace(',', '\n'))"来查看 python3 交互 shell 下的模块搜索路径,类似结果如下:[''
'/usr/lib/python36.zip'
'/usr/lib/python3.6'
'/usr/lib/python3.6/lib-dynload'
'/home/yanbin/.local/lib/python3.6/site-packages'
'/usr/local/lib/python3.6/dist-packages'
'/usr/lib/python3/dist-packages'
'/usr/lib/python3.6/dist-packages']注意,第一个元素是个空字符串,代表进入 python3 shell 时的当前目录。
如果在通过一个 py 脚本文件来打印
sys.path的话显示稍微有所差异。比如在目录/home/yanbin/Developers/下创建test.py文件,内容为 Read More
阅读到 Strings 中关于转换对象为字符串的内容,介绍了
repr函数,趁着还没有真正了解 Python 面向对象的生疏与热度,感性上理解一下repr与str这两个函数的区别。Python 的全局方法
repr和str会映射到对象的__repr__和__str__的方法调用,还有str(obj)时会调用哪个方法,以及print(obj)和调试 Python 代码时的对象显示会调用哪个方法呢?这就是本文想要印证的内容。恰如 Java 的
System.out.println(obj)或"hello" + obj都会调用 Java 对象的toString()方法,那么 Python 中是怎么一回事呢?来自某本 Python 入门书的解释
repr和str:repr: formal string representation of a Python objectstr: informal string representation of a Python object,或者说 printable string representation
首先
repr是 representation 的意思,一个是正式,另一个是非正式,看起来repr比str显得重要些。 Read More
本文只是我个人的掌握 Python 的快速入门笔记, 所以混乱不堪, 并不适合于每一个想要学习 Python 的读者
Python 命令进到它的 shell, ctrl+d 或 exit() 退出 python. help(str) 可以查看 str 函数的帮助, q 退出帮助. 对象的方法可用 dir 来查看,dir([]),dir(""), 进而help([].append),help(dir([]))
Python 是用严格的缩进来格式化代码块的, Google 的 Python 代码规范是用 4 个空格来缩进. Google 建议 Java 是用两个空格.
Python 是动态类型的, 所以可以 a = 1; a = "string" 随意赋值为不同类型. Python 也能用分号把多条语句写在同一行里, 但基本没人用分号的.
Python 的基本类型有 整数, 长整数, 浮点数和复数, 以及字符串
字符串可以用单引号和双引号, 它们像 Javascript, 是完全一样的
''' 或 "”” 三引号的字符串是 here doc, 多行字符串
转义符也是用 \, 如 ''What\’s your name\n?
自然字符串: 即不转义, 用 R 或 r 来指定, 如 r"Newlines are indicated by \n”, 会输出 "\n"" 字面值. 可用于书写正则表达式
放在一起的字符串就会被 Python 自动连接, 如 print ''What\'s' ''your name?’, 输出为 "What’s your name?”
Python 的命名规则有几个必须知道的: 类名和 Java 一样; 模块, 方法, 变量名用小写字母下划线分隔, 常量用大写加下划线. 单或双下划线开头是特殊用途. 命名规则请参考 Google Python Style Guide#Naming
Python 是纯面向对象的, 任何东西都是对象, 函数也是
Python 可以用 \ 来连接语句行, 像 Bash 一样, 如 Read More