一、简单句式
1.1 数值
# 校验输入是否为有效数字
if not math.isnan(num):
xxxx
# 浮点数精度问题
print(0.1 + 0.2) # 0.30000000000000004
0.1 + 0.1 + 0.1 == 0.3 # false
math.isclose(0.1 + 0.1 + 0.1, 0.3) # true
round(0.1 + 0.1 + 0.1, ndigits=2) == round(0.3, ndigits=2) # true
# 字符串是否可转数字
st.isdecimal()
st.isnumeric()
# Generate a random number within the specified range
import random
random_number = random.uniform(min_range, max_range)
# Generate a random int in the range [min_val, max_val]
random_number = random.randint(min_val, max_val)
# 正负无穷大
a = float("inf")
b = float("-inf")
1.2字符串 string
# Reverse the string
reversed_string = input_string[::-1]
# Count occurrences of the target character
count = input_string.count(target_char)
# Check if main_string starts with search_string
starts_with = main_string.startswith(search_string)
# Trim the string
trimmed_string = string_with_spaces.strip()
# Check if main_string contains substring_to_check
contains_substring = substring_to_check in main_string
# Case-sensitive comparison
case_sensitive_comparison = string1 == string2
# Case-insensitive comparison
case_insensitive_comparison = string1.lower() == string2.lower()
# 移除所有白空格
import re
re.sub(r'\s', '', input_text)
# 判断字符串是否为空
len(string) == 0
# 字符串分割
st.split( ); # 以空格为分隔符,包含 \n
st.split(' ', 1 ); # 以空格为分隔符,分隔成两个
# Remove non-alphabetic characters and convert to lowercase
clean_str1 = ''.join(filter(str.isalpha, str1.lower()))
# 格式
str_percentage = 'The user %s was born %s years ago.' % (name, age)
str_f_string = f'The user {name} was born {age} years ago.'
str_fun_string = 'The user {} was born {} years ago.'.format(txt, num)
str_fun_string2 = 'The user {1} was born {0} years ago.'.format(num, txt)
str_fun_string3 = 'The user {name} was born {age} years ago.'.format(name = txt, age = num)
print(f'PI is '{pi:.3}'.') # number of digits (defaults n = number)
print(f'The user {name:>10} was born {age:>10} years ago.') # The user Foo Bar was born 42.12 years ago.
print( f'a{{df{num}') # 字符 { 要用 {{, 字符 }要用 }}
print(r'a\nb {name}') # a\nb {name}
print(rf'a\nb {name}') # a\nb foo
1.3 数组 list
# 快速构造数组
a1=[0]*4 # 错误,这是浅拷贝,见下几行解析
a1= [0 for _ in range(4)) # 可行,[0,0,0,0]
a1=list(itertools.repeat(0,4)) # 可行
a3=[[0]*3 for _ in range(0,5)] #5行3列0
a1=list(itertools.repeat([0]*3,5))
## 误区-浅拷贝
>>> mat=[[0]*3]*3
>>> mat
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> mat[0][0]=1
>>> mat
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
# 反转数组
reversed_array = original_array.copy().reverse()
reversed_array = original_array[::-1]
b = ['x', 2, 'y']
':'.join(b) # 直接join会报错
':'.join( map(str, b) ) # 要先做类型转换
'ab:cd:ef'.split(':') # ['ab', 'cd', 'ef']
list('abcd') # 字符串转数组,['a', 'b', 'c', 'd']
words = ['apple', 'banana', 'cat']
words.insert(2, 'zebra') # 指定位置插入,['apple', 'banana', 'zebra', 'cat']
words.remove('zebra') # 移除第一个匹配的元素
words.clear() # 清空
words.pop(0) # 移除指定index,移除第一个
words.pop() # 移除最后一个
words[2:4] = [] # 移除一段
# list当做queue来用
a_queue = []
a_queue.append('Moo')
first = a_queue.pop(0)
# 双向queue
from collections import deque
items = deque(['foo', 'bar'])
items.append('zorg')
nxt = items.popleft()
# 固定长度的deque
queue = deque([], maxlen = 3) # append 超过3个后,会移除最左边的一个元素
# 增加元素
l1.extend(l2) # 增加可迭代对象,l2也是一个list
l1=l1+l2#另一种写法
# 排序
planets.sort() # 类型不一致,会报错
planets.sort(reverse=True)
planets.sort(key=len, reverse=True) # 按key函数结果排序
# sort在原list上修改,返回None。 sorted 返回修改后的list,不改动原list
planets=sorted(planets, reverse=True, key=len)
students = [
('John', 'A', 2),
('Zoro', 'C', 1),
('Dave', 'B', 3),
]
sorted(students) # 按第1个元素排序
sorted(students, key=lambda s : s[1] # 按第2个元素排序
# 枚举
list = [10, 20, 30]
for i, value in enumerate(list):
print(i, ': ', value) # 0 : 10 1 : 20 2 : 30
# list slice是copy
x = [1, 1, 2, 3, 5, 8, 13, 21, 34]
y = x[2:5]
print(y) # [2, 3, 5]
x[2] = 20
print(x) # [1, 1, 20, 3, 5, 8, 13, 21, 34]
print(y) # [2, 3, 5]
1.4 字典
user={"a":1,"b":2,"c":3}
# 遍历
for k in user.keys():
for v in user.values():
for k, v in user.items():
for i in user: print(i) # 输出 a b c 等价于for k in user.keys()
# 取值
user.get('address') # 可防止没有key报错,无key返回None
# 判断key存在
if 'a' in user:
# 判断value存在
if 2 in user.values():
# 删除key
del user['a']
# 按value排序
sorted_names = sorted(user) # 按value排序, 注意,返回的是key,["a","b","c"]
sorted_names = sorted(user,key=lambda x: user[x]) # 等价
sorted_names = sorted(user.keys(), key=lambda x: user[x]) # 等价
for k in sorted_names:
print('{} : {}'.format(k, scores[k]))
# 有序字典,自python 3.7 开始,字典是有序的,按插入顺序
d={}
d['a'] = 1
d['b'] = 2
d['c'] = 3
print(d) # {'a': 1, 'b': 2, 'c': 3}
# 有序字典更多操作-OrderedDict
from collections import OrderedDict
d = OrderedDict()
d['a'] = 1
d['b'] = 2
d['c'] = 3
d.move_to_end('a') # 移到尾部
d.move_to_end('d', last=False) # 移到头部
# 指定排序顺序
planned_order = ('b', 'c', 'a')
e = OrderedDict(sorted(d.items(), key=lambda x: planned_order.index(x[0])))
plan = dict(zip(planned_order, range(len(planned_order)))) # 等价-part1
f = OrderedDict(sorted(d.items(),key=lambda x: plan[x[0]])) # 等价-part2
1.5 集合sets
元素类型必须一致
s1={1,2,3}
s2={2,3,4}
# 交集
s1.intersection(s2) # {2,3}
# 子集
s1.issubset(s2) # False
# 对称差:只属于其中一个集合,而不属于另一个集合的元素组成的集合
s1.symmetric_difference(s2) # {1,4}
# 并集
s1.union(s2) # {1,2,3,4}
# 差集:移除相同的
s1-s2 # {1}
s2-s1 # {4}
# 空集
s1 = set()
# 增加元素
s1.add(1)
# 移除
s1.remove(4) # 没有4,会报错
s1.discard(4) # 没有4,不会报错
# 合入
s1.update(s2) # 等价于 s1 = s1.union(s2)
1.6 函数
# 函数参数,可混合,要遵守顺序:必选参数(又叫位置参数)、默认参数、可变参数、命名关键字参数和关键字参数
# 必选参数a,b
def fun(a,b)
# 默认参数c
def fun(a,b,c='a')
# 可变参数d
def fun(a,b,c='a',*d) #剩余参数会作为元组,赋值给d,例如fun(1,2,3,4),结果为a:1,b:2,c:3,d:(4,)
def fun(*d) #也可单独一个d,则fun(1,2,3,4),d为(1,2,3,4)
# 关键字参数kw
def fun(a,b,**kw) # fun(1,2,c=3,d=4),则kw为{'c':3,'d':4},也可解包裹法赋值,见后
# 命名关键字参数c,d
def fun(a,b,*,c,d) # fun(1,2,c=3,d=4),*后的参数为命名关键字参数,函数调用时,必须赋值,否则会报错
def fun2(a,b,*arg,c,d) #这样,就不需要单独的*,c,d也是 命名关键字参数
fun(1,2,5,c=3,d=4) # 报错 可见 *,c,d是一体的,而不是*把其他参数作为可变参数
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() takes 2 positional arguments but 3 positional arguments (and 2 keyword-only arguments) were given
# 混合规则:必选参数(又叫位置参数)、默认参数、可变参数、命名关键字参数和关键字参数
def func(a, b, c=0, *arg, d, **kw)
# 解包裹
# 当我们创建一个元组时,我们通常会为其分配值。这称为“打包”
# 我们也可以将值提取回变量中。这称为“解包”
li = (1,2,3,4) #打包, li =[1,2,3,4]也是
x,y,z,w=li #解包
# 带*号的解包
x,*y,z=li # y为[2,3]
x,y,*z=li # zw为[3,4]
m1={'a':1,'b':2,'c':3,'d':4,'e':5}
x,*y,z=m1 #y为['b','c','d']
# 函数传参的解包
def fun(a,b,c,d) #调用时 fun(*li)
def fun(**kw) # 调用时解包fun(**m1),注意:kw为m1的一个拷贝,修改kw不会改变m1
# 函数参数传递的是对象的引用
l = [1, 2]
def func(a):
a[0] = 5
print(a)
print(l)
func(l)
print(l)
>>[1, 2]
>>[5, 2]
>>[5, 2]
# 参数类型指定
def add(a :int, b :int) -> int:
return a+b
# 类型的指定也可以用字符串表示
def add(a :"int", b :"int") -> "int":
return a+b
# python中运行时即使给错类型,如果使用中没有错误,也不会报错
1. 7 文件 File
1) 文件读写
# 读取
try:
with open(filename) as fh: # 默认模式为rb
lines=[]
for line in fh: # 通过迭代器读取
对line在做处理
lines.append(line.rstrip('\n')) # 多行处理成一行
lines_str = fh.read([size]) # 读取所有字符作为一个字符串。size 未指定则返回整个文件,如果文件大小 >2 倍内存则有问题,f.read()读到文件尾时返回""(空字串)。
fh.readline() # 返回一行
fh.readlines([size]) # 返回包含size行的列表, size 未指定则返回全部行。
except Exception as err: # 文件不存在会报错
print('There was some error in the file operations.')
print(err)
print(type(err).__name__)
# 写入
with open(filename, 'w') as out: # 从头写
out.write('text\n')
with open(filename, 'a') as out: # 追加写
out.write('append more text\n')
2)目录操作和系统相关
os.getcwd()、sys.path[0]、sys.argv[0]和__file__的区别
sys: 系统特定参数和功能
os: 多种操作系统接口
stat: 定义了一些用于解读 os.stat()
, os.fstat()
和 os.lstat()
(如果它们存在) 输出结果的常量和函数。
os.path: 常用的路径操作
一下说明是假设执行下面命令:
D:\softwares\Python\Python37\python.exe C:/Users/x00450248/PycharmProjects/Test/main.py
import os,sys,stat
# 常见函数
sys.argv # 返回列表,其中包含了被传递给 Python 脚本的命令行参数。 argv[0] 为脚本的名称(是否是完整的路径名取决于操作系统)。如果是通过 Python 解释器的命令行参数 -c 来执行的, argv[0] 会被设置成字符串 '-c' 。如果没有脚本名被传递给 Python 解释器, argv[0] 为空字符串。
>>> ['C:/Users/x00450248/PycharmProjects/Test/main.py']
sys.executable # 返回字符串,提供 Python 解释器的可执行二进制文件的绝对路径,仅在部分系统中此值有意义。如果 Python 无法获取其可执行文件的真实路径,则 sys.executable 将为空字符串或 None。
>>> 'D:\softwares\Python\Python37\python.exe'
os.getcwd() # 返回字符串,当前文件(即main.py文件)所在目录(绝对路径),
>>> 'C:\Users\x00450248\PycharmProjects\Test'
os.mkdir(path, mode=0o777, *, dir_fd=None) # 创建一个名为 path 的目录,应用以数字表示的权限模式 mode。如果目录已经存在, 引发 FileExistsError 。如果路径中的父目录不存在,则会引发 FileNotFoundError 。
os.makedirs(name, mode=0o777, exist_ok=False) # 递归目录创建,自动创建到达最后一级目录所需要的中间目录。
os.remove(path, *, dir_fd=None) # 移除(删除)文件 path。 如果 path 是目录,则会引发 OSError。 请使用 rmdir() 来移除目录。 如果文件不存在,则会引发 FileNotFoundError
os.rmdir(path, *, dir_fd=None) # 移除(删除)目录 path。 如果目录不存在或不为空,则会分别引发 FileNotFoundError 或 OSError。 要移除整个目录树,可以使用 shutil.rmtree()。
shutil.rmtree(path, ignore_errors=False, onerror=None, *, onexc=None, dir_fd=None) # 删除一个完整的目录树;path 必须指向一个目录(但不能是一个目录的符号链接)。 如果 ignore_errors 为真值,则删除失败导致的错误将被忽略;如果为假值或被省略,则此类错误将通过调用由 onexc 或 onerror 所指定的处理器来处理,或者如果此参数被省略,异常将被传播给调用方。
os.walk(root) # 生成目录树中的文件名,方式是按上->下或下->上顺序浏览目录树。对于以 top 为根的目录树中的每个目录(包括 top 本身),它都会生成一个三元组 (dirpath, dirnames, filenames)。
os.path.join(dirpath, name) # 要获取 dirpath 中文件或目录的完整路径 (以 top 打头,请执行 os.path.join(dirpath, name)
files = os.listdir(path) # 返回列表,包含该path下除'.' 和 '..' 的所有对象
os.chdir(path) # 将当前工作目录更改为 path
# os.path
os.path.basename(path_to_thing)
os.path.dirname(path_to_thing)
os.path.abspath(path_to_file)
os.path.exists(path_to_file)
os.path.isfile(path_to_thing)
os.path.isdir(path_to_thing)
os.path.join('home', 'foo', 'work') # home/foo/work
os.path.expanduser('~') # 返回字符串,home
os.path.expanduser('~/work') # 返回字符串,home/work
# 路径延展
os.path.join(os.path.dirname(dir0), 'lib')
# 运行shell命令
os.system('ls -l')
# 列举特殊文件
import glob
files = glob.glob('*.py')
1.8 迭代器
iterable – 可迭代对象
注意不是一种特定类型。一种能够逐个返回其成员项的对象。 可迭代对象的例子包括所有序列类型(如 list, str 和 tuple 等)以及某些非序列类型如 dict, 文件对象 以及任何定义了__iter__()
方法或实现了 sequence 语义的__getitem__()
方法的自定义类的对象。
当一个可迭代对象作为参数被传给内置函数 iter()
时,它会返回该对象的迭代器。
iterator – 迭代器
用来表示一连串数据流的对象。 重复调用迭代器的 __next__()
方法 (或将其传给内置函数 next()
) 将逐个返回流中的项。
1.8.1 range
内置类型有三种基本序列类型:list, tuple 和 range 对象。
range对象比list省内存空间。
range转list: list(range(20))
1.8.2 map
map
返回一个将 function 应用于 iterable 的每一项,并产生其结果的迭代器。
如果传入了额外的 iterables 参数,则 function 必须接受相同个数的参数并被用于到从所有可迭代对象中并行获取的项。
当有多个可迭代对象时,当最短的可迭代对象耗尽则整个迭代将会停止。
对于函数的输入已经是参数元组的情况,请参阅 itertools.starmap()。
itertools.starmap()
map() 和 starmap() 之间的区别类似于 function(a,b) 和 function(*c) 之间的差异。
1.8.3 生成器和yield
1.8.4 其他常用库
1.8 模块 Modules
模块搜索路径存储在 system 模块的 sys.path
变量中。变量里包含(搜索顺序也如下)
- 当前目录
- PYTHONPATH
- 由安装过程决定的默认目录
# 增加搜索路径
import sys
sys.path.insert(0, '/home/foobar/python/libs')
# 重复引入相同名字的对象会override
from mycalc import add
print(add(2, 3)) # 5
from mymath import add
print(add(2, 3)) # 6
1.9 正则表达式
Python3 正则表达式
【Python练习cookbook】字符串实用操作、正则表达式操作
# compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
re.compile(pattern_str[, flags])
"""
pattern_str: 一个字符串形式的正则表达式
flags 可选,表示匹配模式,比如忽略大小写,多行模式等
"""
pattern = re.compile(r'#.*$')
通常,pattern可用于等价替换re相关的函数:
re.match(pattern, string, flags=0)
pattern.match(string[, pos[, endpos]]) # 相似
re.search(pattern, string, flags=0)
pattern.search( string[, pos[, endpos]]) # 相似
re.sub(pattern, repl, string, count=0, flags=0)
pattern.sub(repl, string, count=0) # 等价
re.split(pattern, string[, maxsplit=0, flags=0])
pattern.split(string[, maxsplit=0) # 等价
1) re.match 与 re.search的区别
re.match
只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None
re.search
匹配整个字符串,直到找到一个匹配。
# 搜索
print(re.match('www', 'www.runoob.com').span()) # 元组:(0,3)
line = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
matchObj.group() # 'Cats are smarter than dogs'
matchObj.group(0) # 等价,'Cats are smarter than dogs'
matchObj.group(1) # 'Cats'
matchObj.group(2) # 'smarter'
matchObj.groups() # ('Cats', 'smarter')
else:
print ("No match!!")
# 查找所有
re.findall(pattern, string, flags=0) # 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式带括号的(),则返回元组列表,如果没有找到匹配的,则返回空列表。
pattern.findall(string[, pos[, endpos]])
re.finditer(pattern, string, flags=0) # 和findall类似,结果以迭代器返回
pattern.finditer(string[, pos[, endpos]])
"""
pattern 匹配模式。
string 待匹配的字符串。
pos 可选参数,指定字符串的起始位置,默认为 0。
endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
"""
re.findall(r'\d+','runoob 123 google 456') # ['123', '456']
re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10') # [('width', '20'), ('height', '10')]
2) 替换
re.sub(pattern, repl, string, count=0, flags=0)
"""
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 编译时用的匹配模式,数字形式。
"""
# 删除注释
phone = "2004-959-559 # 这是一个电话号码"
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)
# repl为函数
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s)) # (?P<groupname>PATTERN)给group命名
# subn
re.subn(pattern, repl, string, count=0, flags=0) # 行为与 sub() 相同,但是返回一个元组 (字符串, 替换次数).
re.subn(r'#.*$', "", phone) # ('2004-959-559 ', 1)
3) 分割
re.split(pattern, string[, maxsplit=0, flags=0]) # 返回列表
pattern.split(string[, maxsplit=0) # 等价
"""
pattern 匹配的正则表达式
string 要匹配的字符串。
maxsplit 分割次数,maxsplit=1 分割一次,默认为 0,不限制次数。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志
"""
re.split('\W+', 'runoob, runoob, runoob.') # ['runoob', 'runoob', 'runoob', '']
re.split('(\W+)', ' runoob, runoob, runoob.') # ['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']
4) 常用几个转义字符
\d 数字: [0-9]
\w 字母:[0-9a-zA-Z_]
\s 白空格: [\f\t\n\r ]
[^abc] : 非a、b、c
\D 非数字: [^\d]
\W 非字母: [^\w]
\S 非白空格: [^\s]
\b 单词边界:例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 非单词边界:'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
1.10 其他
# 检查变量是否未定义或为null
if variable is None:
xxx
# 检查变量是否是函数
if callable(my_function):
print('The variable is of function type')
# 一次性初始化多个变量
a,b,c,d=1,2,3,4 # 并行赋值的
a=b=c=d=1
li = [1,2,3] # li=(1,2,3)也可以,# 利用列表或元组
x,y,z=li # (x,y,z)=li也行,即使li是list,[x,y,z]=li也可以
# 原地交换
x,y=y,x # 实际上,等号右边先处理成常量,然后再从左到右赋值
# 嵌套表达式
l = [[1,2,3],[4,5,6]]
l2= [y for x in l for y in x]
>> [1,2,3,4,5,6]
# 按列取元素
>>> a=[[1,2,3], [4,5,6]]
>>> a[:, 0] # 尝试用数组的方法读取一列失败,这是numpy的用法
TypeError: list indices must be integers or slices, not tuple
# 一种可行方法
>>> b = [i[0] for i in a] # 从a中的每一行取第一个元素。
>>> print(b)
[1, 4]
# 经典用法zip(*a)方案
>>> a=[[1,2],[3,4],[5,6]]
>>> list(zip(*a))
[(1, 3, 5), (2, 4, 6)]
>>> list(zip(*a))[0]
(1, 3, 5)
# 解释:zip可同时zipN个可迭代对象,所以可以用*a来解包裹
>>> b=[[1,2,3],[4,5,6],[7,8,9]]
>>> list(zip(*b))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> a=[1,2,3]
>>> b=[4,5,6]
>>> c=[7,8,9]
>>> list(zip(a,b,c))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
# iter的停止1
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
try:
# 获得下一个值:
x = next(it)
print(x)
except StopIteration:
# 遇到StopIteration就退出循环
break
# iter的停止2
while True:
x = next(it, 'stop')
if x == 'stop':
break
else:
print(x)