• Python 小贴士(1)


    1. 查询当前使用的 python 版本:

    在命令行中查询的方法是:

    1. $ python --version
    2. Python 3.9.0rc2
    3. $ python -V
    4. Python 3.9.0rc2

    在执行代码过程中,也可以查询:

    1. >>> print(sys.version_info)
    2. sys.version_info(major=3, minor=9, micro=0, releaselevel='candidate', serial=2)
    3. >>> print(sys.version)
    4. 3.9.0rc2 (tags/v3.9.0rc2:2bd31b5, Sep 17 2020, 00:37:38) [MSC v.1927 32 bit (Intel)]

    2. PEP 8 风格指南:

    空格相关:

    • 用空格表示缩进,而不要用制表符。
    • 和语法相关的每一层缩进都用 4 个空格表示。
    • 每行不超过 79 个字符。
    • 对于占据多行的长表达式来说,除了首行之外的其余各行都应该在通常的缩进级别之上再加 4 个空格。
    • 在同一个文件中,函数与类之间用两个空行隔开。
    • 在同一个类中,方法与方法之间用一个空行隔开。
    • 使用字典时,键与冒号之间不加空格,写在同一行的冒号和值之间应该加一个空格。
    • 给变量赋值时,赋值符号的左边和右边各加一个空格,并且只加一个空格。
    • 给变量的类型做注解时,不要把变量名和冒号隔开,但在类型信息前应该有一个空格。

    命名相关:

    • 函数、变量及属性用小写字母来拼写,各单词之间用下划线相连。
    • 受保护的实例属性,用一个下划线开头。
    • 私有的实例属性,用两个下划线开头。
    • 类(包括异常)命名时,每个单词的首字母均大写。
    • 模块级别的常量,所有字母都大写,各单词之间用下划线相连。
    • 类中的实例方法,应该把第一个参数命名为 self,用来表示该对象本身。
    • 类方法的第一个参数,应该命名为 cls,用来表示这个类本身。

    表达式和语句相关:

    • 采用行内否定,即把否定词直接写在要否定的内容前面,而不要放在整个表达式的前面。
    • 不要通过长度判断容器或序列是不是空的,而要使用 if not ... 这种格式,因为 Python 会把空值自动评估为 False。
    • 如果要判断容器或序列里面有没有内容,也不应该通过长度来判断,而是采用 if somelist 语句,因为 Python 会把非空的值自动判定为 True。
    • 不要把 if 语句、for 循环、while 循环及 except 复合语句挤在一行,应该分成多行来写,这样更加清晰。
    • 如果表达式一行写不下,可以用括号括起来,而且要适当地添加换行与缩进以便于阅读。
    • 多行的表达式,应该用括号括起来,而不是用 \ 符号续行。

    引入相关:

    • import 语句总是放在文件开头。
    • 引入模块时,总是应该使用绝对名称,而不应该根据当前模块路径来使用相对名称。
    • 如果一定要用相对名称来编写 import 语句,那就应该明确地写成 from . import foo。
    • 文件中的 import 语句应该按顺序划分成三个部分:首先引入标准库里的模块,然后引入第三方模块,最后引入自己的模块。

    3. bytes 与 str 的区别:

    bytes 和 str 都可以表示字符序列。

    bytes 实例包含的是原始数据,即 8 位的无符号值(通常按照 ASCII 编码标准来显示)。

    1. >>> a = b'h\x65llo'
    2. >>> print(list(a))
    3. [104, 101, 108, 108, 111]
    4. >>> print(a)
    5. b'hello'

    str 实例包含的是 Unicode 码点,这些码点与人类语言之中的文本字符相对应。 

    1. >>> a = 'a\u0300 propos'
    2. >>> print(list(a))
    3. ['a', '̀', ' ', 'p', 'r', 'o', 'p', 'o', 's']
    4. >>> print(a)
    5. à propos

    要把 Unicode 数据转换成二进制数据,必须调用 str 的 encode 方法;要把二进制数据转换成 Unicode 数据,必须调用 bytes 的 decode 方法。

    两个好用的辅助函数,在两种情况之间进行转换:

    1. def to_str(bytes_or_str):
    2. if isinstance(bytes_or_str, bytes):
    3. value = bytes_or_str.decode('utf-8')
    4. else:
    5. value = bytes_or_str
    6. return value
    1. def to_bytes(bytes_or_str):
    2. if isinstance(bytes_or_str, str):
    3. value = bytes_or_str.encode('utf-8')
    4. else:
    5. value = bytes_or_str
    6. return value

    可以用 + 操作符将 bytes 添加到 bytes,str 也可以这样。但不能将 bytes 添加到 str,反之亦然。bytes 可以用二元操作符与 bytes 进行比较,str 与 str 之间也可以,但 bytes 与 str 不行。这两种实例不能在某些操作符(例如 >、==、+、%)上面混用。从文件中读取二进制数据(或写入二进制数据到文件),应该使用 'wb' 或 'rb' 这样的二进制模式打开文件。如果要从文件中读取的是 Unicode 数据,必须注意系统默认的文本编码方案,若无法肯定,可通过 encoding 参数明确指出。

    4. f-string:

    这种语法要求在格式字符串的前面加上字母 f 作为前缀。

    1. >>> key = 'my_var'
    2. >>> value = 1.234
    3. >>> formatted = f'{key} = {value}'
    4. >>> print(formatted)
    5. my_var = 1.234

    可以通过 ! 符号把值转化成 Unicode 及 repr 形式的字符串:

    1. >>> formatted = f'{key!r:<10} = {value:.2f}'
    2. >>> print(formatted)
    3. 'my_var' = 1.23

    5. 用辅助函数取代复杂的表达式:

     要把 URL 中的查询字符串拆分成键值对,只需要使用 parse_qs 函数就可以了:

    1. >>> from urllib.parse import parse_qs
    2. >>> my_values = parse_qs('red=5&blue=0&green=', keep_blank_values=True)
    3. >>> print(repr(my_values))
    4. {'red': ['5'], 'blue': ['0'], 'green': ['']}

    可以发现,有的参数可能带有多个值,有的参数可能只有一个值,有的参数可能是空白值,也会遇到根本没提供这个参数的情况。如果能把参数缺失与参数为空白值这两种情况都默认当成 0 就更好了。

    1. def get_first_int(values, key, default=0):
    2. found = values.get(key, [''])
    3. if found[0]:
    4. return int(found[0])
    5. return default

    6. 把数据结构直接拆分到多个变量里,不要专门通过下标访问:

    tuple 可以用不可变的序列把许多元素依次保存起来。

    1. >>> snack_calories = {
    2. 'chips': 140,
    3. 'popcorn': 80,
    4. 'nuts': 190,
    5. }
    6. >>> items = tuple(snack_calories.items())
    7. >>> print(items)
    8. (('chips', 140), ('popcorn', 80), ('nuts', 190))

    可以用整数作下标,通过下标访问元组里边对应的元素:

    1. >>> item = ('Peanut butter', 'Jelly')
    2. >>> first = item[0]
    3. >>> second = item[1]
    4. >>> print(first, 'and', second)
    5. Peanut butter and Jelly

    还可以使用一种更好的方法,叫作“拆分”。这种方法可以把元组中的元素分别赋给多个变量。

    1. >>> first, second = item
    2. >>> print(first, 'and', second)
    3. Peanut butter and Jelly

    通过拆分来赋值要比通过下标访问元组内的元素更清晰,而且这种写法所需的代码量通常比较少。赋值操作的左边除了可以罗列单个变量,也可以写成列表、序列或任意深度的可迭代对象(iterable)。也可以原地交换两个变量,而不需要创建临时变量。

    1. def bubble_sort(a):
    2. for _ in range(len(a)):
    3. for i in range(1, len(a)):
    4. if a[i] < a[i-1]:
    5. a[i-1], a[i] = a[i], a[i-1]

    拆分机制还有一个重要的用法,就是可以在 for 循环(或类似的结构)中把复杂的数据拆分到相关的变量之中:

    1. >>> snacks = [('bacon', 350), ('donut', 240), ('muffin', 190)]
    2. >>> for rank, (name, calories) in enumerate(snacks, 1):
    3. print(f'#{rank}: {name} has {calories} calories')
    4. #1: bacon has 350 calories
    5. #2: donut has 240 calories
    6. #3: muffin has 190 calories

    拆分机制可以用在许多方面,例如构建列表(13)、给函数设计参数列表(22)、传递关键字参数(23)、接受多个返回值(19)等。

    7. 尽量用 enumerate 取代 range:

    enumerate 是 Python 的 内置函数,它能把任意一种迭代器(iterator)封装成惰性生成器。这样每次循环的时候只需要从 iterator 里获取下一个值就行了,同时还会给出本轮循环的序号,即生成器每次产生的一对输出值。

    1. >>> flavor_list = ['vanilla', 'chocolate', 'pecan', 'strawberry']
    2. >>> it = enumerate(flavor_list)
    3. >>> print(next(it))
    4. (0, 'vanilla')
    5. >>> print(next(it))
    6. (1, 'chocolate')
    7. >>> for i, flavor in enumerate(flavor_list):
    8. print(f'{i+1}: {flavor}')
    9. 1: vanilla
    10. 2: chocolate
    11. 3: pecan
    12. 4: strawberry
    13. >>> for i, flavor in enumerate(flavor_list, 1):
    14. print(f'{i}: {flavor}')
    15. 1: vanilla
    16. 2: chocolate
    17. 3: pecan
    18. 4: strawberry

    8. 用 zip 函数同时遍历两个迭代器: 

    zip 函数可以把两个或更多的 iterator 封装成惰性生成器。每次循环时,它会分别从这些迭代器里获取各自的下一个元素,并把这些值放在一个元组里面。

    1. longest_name = None
    2. max_count = 0
    3. for name, count in zip(names, counts):
    4. if count > max_count:
    5. longest_name = name
    6. max_count = count
    7. >>> print(longest_name)
    8. Cecilia
    9. >>> print(max_count)
    10. 7

    如果迭代器的长度不一致,只要其中任意一个迭代器处理完毕,就不再继续处理了。这时可以用 itertools.zip_longest 函数。

    9. 不要在 for 和 while 循环后面写 else 块:

    只有在整个循环没有因为 break 提前跳出的情况下,else 块才会执行。

    10. 用赋值表达式减少重复代码:

    使用海象表达式 :=

    比如有几种水果要做成果汁,顾客点柠檬汁之前,要先确认现在还有没有柠檬可以榨汁,所以要先查出柠檬的数量,然后判断是不是非零的值:

    1. if count := fresh_fruit.get('lemon', 0):
    2. make_lemonade(count)
    3. else:
    4. out_of_stock()

    如果是苹果汁,每杯果汁需要 4 颗苹果,可以这么写:

    1. if (count := fresh_fruit.get('apple', 0)) >= 4:
    2. make_lemonade(count)
    3. else:
    4. out_of_stock()
  • 相关阅读:
    C++ pair的基本用法
    鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统
    Matlab进阶绘图第28期—带回归趋势线的密度散点图
    相信我,使用 Stream 真的可以让代码更优雅
    如何快速新建多个不同名称文件夹?
    lab1-3 使用通用脱壳工具
    计算机毕业论文java毕业设计选题源代码基于SSM的会议室预约系统
    小熊家务帮day13-day14 门户管理(ES搜索,Canal+MQ同步,索引同步)
    PTA 7-81 统计工龄
    Skywalking 部署
  • 原文地址:https://blog.csdn.net/yspg_217/article/details/125444727