前言
看别人的源码时总感觉高大上,看自己写的代码,总感觉有点廉价感,总是不那么顺眼,那该如何提高自己的编程质量,让代码看起来更优雅呢?那我们除了掌握基础知识,还需要掌握一些高阶用法。
基础知识
变量常见用法
变量解包
变量解包是Python里的一种特殊赋值操作,允许我们把一个可迭代对象(比如列表)的所有成员,一次性赋值给多个变量,像这样
ini
usernames = ['honey', 'jack']
author, reader = usernames
如果有多层嵌套数据,我们可以添加小括号(),像这样
scss
usernames = [['honey', 90], ['jack', 100]]
(author, author_score), (reader, reader_score) = usernames
动态解包,用星号表达式(*variables)作为变量名,它便会贪婪地捕获多个值对象,并将捕获到的内容作为列表赋值给variables,像这样
ini
usernames = ['honey', 90, 100, 'jack']
author, *score, reader = usernames
print(score) # [90, 100]
单下划线变量名_
它常作为一个无意义的占位符出现在赋值语句中。_这个名字本身没什么特别之处,这算是大家约定俗成的一种用法。像这样
ini
usernames = ['honey', 90, 100, 'jack']
author, *_, _ = usernames
给变量注明类型
在Python 3.5版本以后,可以用类型注解功能来直接注明变量类型。像这样
python
from typing import List
def remove_invalid(items: List[int]):
"""移除无效元素"""
......
当然,"类型注解"只是一种有关类型的注释,不提供任何校验功能。要校验类型正确性,需要使用其他静态类型检查工具(如mypy等)
变量命名
Python制定了官方的编码风格指南:PEP 8。其中变量的命名规范如下:
-
对于普通变量,使用蛇形命名法,比如max_value;
-
对于常量,采用全大写字母,使用下划线连接,比如MAX_VALUE;·
-
如果变量标记为"仅内部使用",为其增加下划线前缀,比如
_local_var
; -
当名字与Python关键字冲突时,在变量末尾追加下划线,比如class。
除变量名以外,PEP 8中还有许多其他命名规范,比如类名应该使用驼峰风格(FooClass)、函数应该使用蛇形风格(bar_function),等等。
小技巧
匹配类型:
匹配布尔值类型,像这样is_admin has_errors allow_empty
匹配int/float类型,像这样age port user_id users_count length_of_username
数值基础
定义数值字面量时,如果数字特别长,可以通过插入_分隔符来让它变得更易读,像这样
ini
#以"千"为单位分隔数字
i = 1_000_000
浮点数精度问题
看这段代码:
bash
print(0.1 + 0.2) # 0.30000000000000004
可以看到结果并不是0.3,这就是由于浮点数精度导致的。
为了解决这个问题,Python提供了一个内置模块:decimal。它在做四则运算时不会损失任何精度:
sql
from decimal import Decimal
# 注意0.1和0.2必须是字符串
print(Decimal('0.1') + Decimal('0.2'))
在使用Decimal的过程中,大家需要注意:必须使用字符串来表示数字。如果你提供的是普通浮点数而非字符串,在转换为Decimal对象前就会损失精度,掉进所谓的"浮点数陷阱",像这样
python
from decimal import Decimal
print(Decimal(0.1)) # 0.1000000000000000055511151231257827021181583404541015625
布尔值其实也是数字
布尔类型其实是整型的子类型,在绝大多数情况下,True和False这两个布尔值可以直接当作1和0来使用。像这样
python
print(True + 1) # 2
这个特点,可以用来统计总数,比如:一个包含整数的列表,我需要计算列表里一共有多少个偶数
看到这个题目,正常思维,写一个循环判断完成统计,但利用这个特点可以简化代码,像这样
ini
numbers = [1, 2, 3, 4, 5, 6, 7]
count = sum(i % 2 == 0 for i in numbers)
字符串常用操作
当做序列操作
遍历字符串
ini
s = "hello, python!"
for c in s:
print(c)
切片
ini
s = "hello, python!"
# 反转字符串
s[::-1]
当然反转字符串也可以使用内置方法reversed
实现
bash
''.join(reversed(s))
reversed会返回一个可迭代对象,通过字符串的.join方法可以将它转换为字符串
格式化
三种格式化方式:
1、C语言风格的基于百分号%的格式化语句 'hello, %s' % 'python'
。这种方式不推荐
2、(str.format)方式(Python 2.6新增):"Hello,{}".format ('World')。
3、f-string(Python 3.6新增)
ini
name = 'python';
print(f'Hello, {name}')。
str.format的独特之处:支持用位置参数来格式化字符串,实现对参数的重复使用,像这样
python
print('{0}: name={0} score={1}'.format('jack', 100)) # jack: name=jack score=100
拼接多个字符串
使用join
,像这样
lua
output = ['hello', 'python']
print(' '.join(s for s in output))
当然还有另一种方式+=
切分字符串
split
和partition
lua
output = "name:jack"
print(output.split(':')) # ['name', 'jack']
print(output.partition(":")) # ('name', ':', 'jack')
可与看到,他们返回的结果会有所不同,split
返回一个列表,partition
返回一个包含三个成员的元组:(part_before, sep, part_after),它们分别代表分隔符前的内容、分隔符以及分隔符后的内容。
替换字符
replace
替换单个字符
bash
s = 'hello, python.'
print(s.replace(',', '!')) # hello! python.
当我们需要替换多个字符时,可以使用translate
,像这样
lua
s = 'hello, python.'
# 创建替换规则表:',' -> ',', '.' -> '。'
table = s.maketrans(',.', '!。')
print(s.translate(table)) # hello! python。
字符串与字节串
1、字符串(str)类型,使用Unicode标准,可通过.encode()方法编码为字节串
2、字节串(bytes)类型,bytes一定包含某种真正的字符串编码格式(默认为UTF-8),可通过.decode()解码为字符串
案例:
ini
# 字符串
s = 'hello, python.'
byte_s = s.encode('UTF-8') # b'hello, python.'
# 字节串
byte_object = b'hello'
print(type(byte_object)) # <class 'bytes'>
print(byte_object.decode()) # hello
当你要把字符串写入文件时,请谨记:普通字符串采用的是文本格式,没法直接存放于外部存储,一定要将其编码为字节串------也就是"二进制字符串"------才行。这个编码工作有时需要显式去做,有时则隐式发生在程序内部。比如在写入文件时,只要通过encoding参数指定字符串编码格式,Python就会自动将写入的字符串编码为字节串,像这样
python
#通过 encoding指定字符串编码格式为 UTF-8
with open('output.txt', 'w', encoding='UTF-8') as fp:
fp.write("hello python")
如果未指定encoding,Python会尝试自动获取当前环境下偏好的编码格式,笔者的电脑为Mac,这个编码方式为UTF-8,验证一下:
python
import locale
print(locale.getpreferredencoding()) # UTF-8
最后
实际编程中我们要刻意去练习这些技巧,才能逐渐写出优雅的代码,希望大家都早日成为python大神。