有些位置可能翻译理解的不到位,各位看官如有疑问,欢迎留言赐教。

Pythonic Thinking

大家经常用Pythonic来形容python语法风格的编程方式:简单优美,没有之一;通过import this查看Python之禅。

使用python之前需要明确使用的是python2 or python3。推荐使用python3。


PEP8编码风格指南

缩进留白Whitespace

  • python通过强制缩进的方式,控制字代码块;每次缩进使用4个空格符;

  • 单行代码不宜超过79个字符,当使用\分行显示时,换行的部分应该缩进4个空格位。

  • 文件中,函数和类之间空2行;类中,方法之间空1行;

  • 列表索引访问、函数调用、关键字参数赋值时不应该使用空格;变量赋值间应该空一格;

命名

  • 函数名、变量名、类的属性名采用:小写字母加下划线的方式;

  • 保护对象属性命名采用:下划线开头加小写字母加下划线的方式;

  • 私有对象属性命名采用:双下划线开头加小写字母加下划线的方式;

  • 类名、异常命名采用:驼峰体的方式;

  • 常量命名采用:全大写字母的方式;

  • 类中对象自己使用 self, 类自己使用 cls

表达式&声明

  • 判断对象是否不相等使用 if a is not b 而不使用 if not a is b

  • 判断对象是否为空使用 if not a, 而不使用 if len(a) == 0

  • 判断对象不为空使用 if a

  • 当子代码块只有一行时,不要在写在一块

if True: print('hello world')   # 不推荐,建议换行
  • 导入模块时,在文件顶部导入;导入时应该使用完成的导入路径
from bar import foo
import foo # 不推荐
  • 导入模块的顺序:标准库,三方库,自己的库;在每一等级内都按字母顺序导入

区别:bytes & str & unicode

  • Python3中,bytes指的是包含8-bit的二进制数据;str指的是Unicode字符。bytes和str是两个完全独立的对象;

  • Python2中,str指的是包含8-bit的二进制数据;unicode指的是Unicode字符;str和unicode处理7-bit的ASCII时是相同的。

# Python3中,定义函数将bytes or str转换成str
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 # Instance of str # Python3中,定义函数将bytes or str转换成bytes
def to_bytes(bytes_or_str):
if isinstance(bytes_or_str, str):
value = bytes_or_str.encode(‘utf-8’)
else:
value = bytes_or_str
return value # Instance of bytes
  • Python3中,文件操作时,文本文件用t模式,二进制文件用b模式;

函数优于复杂的表达式

切片Slice

a = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’]
# a[start:end]
a[:] # [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’]
a[:5] # [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]
a[:-1] # [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’]
a[4:] # [‘e’, ‘f’, ‘g’, ‘h’]
a[-3:] # [‘f’, ‘g’, ‘h’]
a[2:5] # [‘c’, ‘d’, ‘e’]
a[2:-1] # [‘c’, ‘d’, ‘e’, ‘f’, ‘g’]
a[-3:-1] # [‘f’, ‘g’]
  • 切片的使用遵循 '顾头不顾尾'的基本原则;

  • startend不指定表示从头切或切到尾;都不指定则表示全部拷贝一份,切片属于浅拷贝;

  • 使用切片不会出现索引越界的问题,如a[:20]表示切前20个元素;

  • start或end为负数,表示倒数第几个,同样遵循 '顾头不顾尾'的基本原则;

  • 如果想要从头切不要提供start,切到尾时不要提供end,如a[:5],切前5个

  • 切片用于赋值时,表示切片的那些位置用新的值覆盖

a[2:7] = [99, 22, 14]	# a = [‘a’, ‘b’, 99, 22, 14, ‘h’]

注意:列表切片赋值修改的是列表内元素的绑定关系,列表对象的内存地址没变。(旧瓶子换了新酒)

b = a
a[:] = [101, 102, 103]
print (a is b) # True
  • 切片时尽可能避免同时使用三个参数:a[start:end:step],这样很很容易让人头晕(我也是醉了)a[2:5:-2]

  • step表示间隔几个切一片,是步长的意思。步长为负数表示倒着切;最好不好使用倒着切;


列表生成式 List Comprehensions

a = [x for x in range(10)]
aquares = [x**2 for x in a]
  • 尽量使用列表生成式而不是用map()和filter()内置函数。因为map()和filter()一般要配合匿名函数的使用,不简洁。
squares = map(lambda x: x ** 2, a)
even_squares = [x**2 for x in a if x % 2 == 0]
alt = map(lambda x: x**2, filter(lambda x: x % 2 == 0, a)) # 表达式很繁琐
assert even_squares == list(alt)
  • 字典和集合等也有对应的生成式。

  • 列表生成式可以多层嵌套,可以后接判断条件;当列表生成式出现超过两层嵌套或者多个条件判断时,不建议使用,建议改写成包含iffor的函数。

  • 数据量过大时,使用表达式生成器(generator expressions )替换列表生成式的使用,减少内存消耗。

  • 多使用 enumerate 少使用 range

for i in range(len(flavor_list)):	# 需要获取列表长度
flavor = flavor_list[i] # 通过索引取值
print(‘%d: %s’ % (i + 1, flavor)) for i, flavor in enumerate(flavor_list, 1):
print(‘%d: %s’ % (i, flavor))
  • 同时并行循环两个列表使用zip

  • 避免在while或者 for循环体外后接else代码块(pep8规范)

  • 充分捕获异常:try|except|else|finally


函数

函数返回值不推荐使用None

  • 函数返回值有具体意义时,不推荐返回None;因为调用函数的对象使用判断时无法区分出None、0、[];应该采用在函数体中捕获异常替代None。

闭包函数只读外部函数作用域变量

  • 闭包函数可以引用它定义时外部函数作用域的变量a,但不可以修改赋值修改该变量,因为修改的操作会在闭包函数的局部作用域内增加一个新的变量而不是修改器外部函数作用域内的变量。
  • 但非要将在闭包寒素内修改外部作用域的变量也可以,但不推荐(容易出难以排查的bug)。
  • python3中通过nonlocal 语法声明接下来要操作的边外部函数作用域的a;python2没有nonlocal语法,是通过将变量定义成可变数据类型,比如列表,在闭包函数里通过a[0]修改。

推荐使用生成器而不是直接返回一个列表

  • 当数据序列数据量庞大时,使用列表粉肠消耗内存,而生成器只是保存序列的算法,每次调用时返回一个。

使用不定长度的位置参数*args优化函数传参调用时的简洁性

  • 函数定义时使用*args可以接收多个位置参数,args以元组的形式保存传进来的多个数据;
  • 函数调用时可以通过*operator解压可迭代对象operator中的序列数据,按位置参数赋值给形参;
  • 调用函数传实参时*operator,operator避免使用生成器否则可能会消耗大量内存导致程序崩溃;
  • 使用*args的缺点是:函数未来增加新位置行参时很容易出bug且很难排查。

建议使用关键字参数传参给形参

  • 关键字传参可以不按照位置顺序,只要每个形参都有被赋值即可;可以同时使用位置传参和关键字传参,但关键字传参要放在位置传参后面,且每个形参只能被赋值一次;
  • 关键字传参好处一:每个参数表示的意义清晰明了;第二个好处:导致出现了函数定义时的默认形参;
  • 第三个好处:向下兼容性,更新函数功能后(新增了默认参数)不会影响老用户使用该函数的调用接口;老用户使用默认的值,新用户可以使用默认参数指定新的值;
def flow_rate(weight_diff, time_diff, period=1, units_per_kg=1):
return ((weight_diff / units_per_kg) / time_diff) * period
# 老用户使用时不知道函数定义代码已经修改了,依然使用可以旧的两个参数传参
# 而新用户知道新增的两个参数表示意思,需要时指定自定义值即可
pounds_per_hour = flow_rate(weight_diff, time_diff, period=3600, units_per_kg=2.2)
  • 这种向下兼容性对于使用*args接收参数的函数很重要;
  • 默认参数最好使用关键字传参而不用位置参数传参。

使用None和文档注释的方式为函数参动态的参数

  • 默认参数只会在函数定义时赋值一次,如果默认参数等于{}或[],这将导致后面所有的函数调用者访问的都是同一个字典或列表的内存地址;
  • 使用默认值为None,再加文档注释的方式实现动态参默认参数
# 记录消息的打印时间
def log(message, when=datetime.now()):
print(‘%s: %s’ % (when, message)) log(‘Hi there!’)
sleep(0.1)
log(‘Hi again!’)
>>>
2014-11-15 21:10:10.371432: Hi there!
2014-11-15 21:10:10.371432: Hi again! # 两次的时间是相同的
# 这是因为when这个默认参数在函数定义的瞬间就被赋值了,以后每次调用使用的都是一个相同的值;
# 如果想要时时获得打印消息的时间,使用默认参数为None的方式
def log(message, when=None):
"""
Log a message with a timestamp.
Args:
message: Message to print.
when: datetime of when the message occurred.
Defaults to the present time.
"""
when = datetime.now() if when is None else when
print(‘%s: %s’ % (when, message))

限制函数调用者使用关键字参数为函数传参

  • python3中函数定时,参数列表中添加 * ,其后的参数必须使用关键字传参,否则会报TypeError 的错误;
  • python2中没有该语法,若非要这样做可以使用**kwargs加手动抛出TypeError的错误。

update to 20200323

大佬总结的很好,直接引用学习了

Effective Python读书笔记的更多相关文章

  1. Web Scraping with Python读书笔记及思考

    Web Scraping with Python读书笔记 标签(空格分隔): web scraping ,python 做数据抓取一定一定要明确:抓取\解析数据不是目的,目的是对数据的利用 一般的数据 ...

  2. Effective STL 读书笔记

    Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...

  3. Effective STL读书笔记

    Effective STL 读书笔记 本篇文字用于总结在阅读<Effective STL>时的笔记心得,只记录书上描写的,但自己尚未熟练掌握的知识点,不记录通用.常识类的知识点. STL按 ...

  4. effective c++读书笔记(一)

    很早之前就听过这本书,找工作之前读一读.看了几页,个人感觉实在是生涩难懂,非常不符合中国人的思维方式.之前也有博主做过笔记,我来补充一些自己的理解. 我看有人记了笔记,还不错:http://www.3 ...

  5. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

  6. Effective java读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...

  7. Effective Python2 读书笔记3

    Item 22: Prefer Helper Classes Over Bookkeeping with Dictionaries and Tuples For example, say you wa ...

  8. Effective Python2 读书笔记2

    Item 14: Prefer Exceptions to Returning None Functions that returns None to indicate special meaning ...

  9. Effective Python2 读书笔记1

    Item 2: Follow the PEP 8 Style Guide Naming Naming functions, variables, attributes lowercase_unders ...

随机推荐

  1. mode|平均数|方差|标准差|变异系数|四分位数|几何平均数|异众比率|偏态|峰态

    应用统计学 数据的概括性度量 集中趋势 Mode众数是唯一描述无序类别数据,由图可知众数便是图形中的峰. 对于类别变量,众数就是某一种类别. 中位数和平均数都可能不是样本中的值. 中位数不受极值影响, ...

  2. 关于JS对象原型prototype与继承,ES6的class和extends · kesheng's personal blog

    传统方式:通过function关键字来定义一个对象类型 1234567891011 function People(name) { this.name = name}People.prototype. ...

  3. win10 安装VMware Workstation Pro提示无法在windows上运行

    win10 安装vm无法在windows上运行 之前还可以用 网上搜了一下  要安装最新15.5.0就不会报错了 没毛病!! 不想注册下载 百度网盘(2019年9月19日版本) https://pan ...

  4. 使用Google BBR加速 VPS

    0X00 预备知识 在使用Google BBR之前,我们首先要了解它是什么. 了解计算机网络的人都知道,在TCP连接中,由于需要维持连接的可靠性,引入了拥塞控制和流量管理的方法.Google BBR就 ...

  5. 改了改之前那个很糙的XXX

    将就着用X度去爬吧 <?php echo "***************************************\r\n"; echo "* SubDom ...

  6. ansible使用指北(二)

    前言在上一篇文章里我们了解了ansible的常用模块,今天我们来了解下ansible-playbook,ansbile-playbook是一系统ansible命令的集合,其利用yaml 语言编写,an ...

  7. CALL/APPLY、一些编程基础以及一些基础知识、正则

    call.apply.bind 求数组的最大值和最小值: 数组排序(SORT的原理->localeCompare实现汉字比较),取头取尾 假设法 利用APPLY传参传递的是一个数组的机制,借用M ...

  8. LiteOS内核教程01-IoT-Studio介绍及安装

    1. 物联网一站式开发工具 -- IoT Studio IoT Studio 是支持 LiteOS 嵌入式系统软件开发的工具,提供了代码编辑.编译.烧录 及调试等一站式开发体验,支持 C.C++.汇编 ...

  9. 【基础篇】hexo博客搭建教程

    [基础篇]搭建hexo博客(一) 作者:Huanhao bilibili:Mrhuanhao 前言 你是否想拥有属于自己的博客?你是否无奈与自己不会写网站而烦恼? 不要担心,本系列教程将会实现你白嫖的 ...

  10. powershell加KeePass实现,加密服务器密码清单文件

    powershell加KeePass实现,加密服务器清单文件   powershell传教士翻译,改写. 2020-02-27   原文: https://www.altaro.com/msp-doj ...