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

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. 转: zabbix3.2.1安装graphtrees插件

    转自 : http://blog.csdn.net/liang_baikai/article/details/53542317 graphtree介绍 由于zabbix的图像显示一块不太友好,图像没法 ...

  2. paxos算法学习总结

    核心思想 分布式系统架构下如何让整体尽快达成一致观点,也就是多个不同观点收敛到一个观点的过程. 难点 可能会发生少数节点故障,但绝不是大面积故障,不然系统也没法正常工作. 由于存在单点故障,因此不可能 ...

  3. hiho一下:Beautiful String

    hiho一下:Beautiful String 记不清这是 hiho一下第几周的题目了,题目不难,不过对于练习编程,训练思维很有帮助.况且当时笔者处于学习算法的早期, 所以也希望刚接触算法的同学能多去 ...

  4. python基础-基本概念

    python概念介绍 python是一门动态解释型的强类型定义语言,创始人吉多·范罗苏姆(Guido van Rossum) #编译型语言 编译型:一次性将所有程序编译成二进制文件 缺点:开发效率低, ...

  5. CSS 学习笔记——CSS Selector

    CSS1 中定义的选择器 类型选择器 用于选择指定类型的元素(其实他就是 html 标签选择器),常见用法如下: body { /*对 body 元素定义样式*/ } body,div { /*同时选 ...

  6. 基于vue开发的在线付费课程应用

    最近在弄一个付费课程的应用,主要有微信登录,支付和自定义分享,在开发过程中遇到的坑,这里做一下记录 文章主要有以下几点 使用库简介 微信登录解决 微信支付解决 微信自定义分享解决 页面前进后退数据状态 ...

  7. 前后端分离下的跨域CAS请求

    最重要的两点: ajax请求跨域的时候,默认不会携带cookie. 请求分为普通请求(HttpRequest)和Ajax请求(XMLHttpRequest) 先屡一下跨域CAS认证的流程: 前端发起a ...

  8. 一个轻量级的基于 .NET Core 的 ORM 框架 HSQL

    HSQL 是一种轻量级的基于 .NET Core 的数据库对象关系映射「ORM」框架 HSQL 是一种可以使用非常简单且高效的方式进行数据库操作的一种框架,通过简单的语法,使数据库操作不再成为难事.目 ...

  9. DvaJS入门课

    不管是Vue还是React,他们都没解决组件间的通信和数据流问题.当然,这个说法不是很准确,准确的说法是他们都没很好的处理这些问题.我们是可以用一些烂手段去解决这个问题,但是当应用比较大.数据多的时候 ...

  10. Python卸载

    前言 自己瞎折腾下载Python3.8.2,把之前下载好的python3.7.3覆盖掉.在运行之前Python环境的程序多次未果后.找到原因,Python3.7.3的包不支持Python3.8.2.于 ...