1 入门基础

1.1 Pycharm快捷使用

  • ctr + / - 添加注释和取消注释
  • ctr + shift + z - 反撤销
  • alt + Enter - 快速导包

1.2 基础/变量与运算符

1.2.1 注释

  1. 单行注释: 在注释性文字的开头加#
  2. 多行注释: 用三个单引号或者三个双引号引起来

1.2.2 语句

  1. 一条语句占一行,语句结束的时候不用写分号;如果一行写多条语句,语句之间必须用分号隔开
  2. 如果一条语句的长度超过一定范围需要换行显示,就换行位置前加\ (注意: \的位置不能破坏数据)

     result = 789789798798798 + 378923498732 \
         - 37489172348 * 32471827349 /\
         1203472893 + 2873498237
    
  3. 行和缩进

    1. 一条语句的前面不能随意添加空格或缩进
    2. 有的时候语句的前面必须有一个缩进(四个空格表示一级缩进-PEP8规范)

1.2.3 标识符(命名规范)

要求: 由字母、数字和下划线组成,并且数字不能开头(注意: 其实标识符可以包含中文,但是不要这样做)

PEP8规范:

  • 变量 - 所有字母都小写,如果有多个单词单词之间用下划线隔开
  • 函数名 - 应该小写,如果想提高可读性可以用下划线分隔。
  • 类名 - 一般使用首字母大写的约定。
  • 常量 - 通常定义在模块级,通过下划线分隔的全大写字母命名。

1.2.4 关键字

截止 Python3.12 总共有35个关键字,且额外有 4 个软关键字(仅在特定上下文中被保留)

关键字

关键字查看方法:

import keyword
print(keyword.kwlist)

""" False await else import pass None break except in raise True class finally is return and continue for lambda try as def from nonlocal while assert del global not with async elif if or yield """

软关键字

  • match, case_ 是在 match 语句中使用 (Python3.10 添加)
  • type 是在 type 语句中使用 (Python3.12 添加)

1.3 内置函数

内置函数官方文档参考 内置函数

数据类型转换

  • bool() - 布尔类型
  • int() - 整数类型
  • float() - 浮点型
  • complex() - 复数
  • str() - 将数据转换为字符串
  • bytes() - 将字符串类型转换为bytes类型
  • list() - 将可迭代对象转换为列表
  • tuple() - 将可迭代对象转换为元组
  • dict() - 创建一个字典
  • set() - 创建一个集合
  • frozenset() - 创建一个冻结的集合,不能进行添加删除
  • isinstance() - 判断一个对象是否是一个已知的类型
  • issubclass() - 判断一个类是否是另一个类的子类

数学运算

  • abs() - 返回绝对值
  • divmod() - 返回商和余数
  • round() - 四舍五入
  • pow(a, b) - 求a的b次幂,如果有第三个参数,则求完后再取幂
  • sum() - 求和
  • min() - 最小值
  • max() - 最大值
abs(-2) # 2
divmod(20, 3) # (6, 2)
round(4.6) # 5
pow(10, 2) # 100
pow(10, 2, 3) # 1
sum(1, 2, 3, 4, 5) # 15
min(1, 2, 3, 4, 5) # 1
max(1, 2, 3, 4, 5) # 5

数据结构

  • reversed() - 将序列翻转,返回翻转序列的迭代器,不改变原序列
  • slice() - 列表的切片
  • format() - 格式化字符串
    • < - 左对齐
    • > - 右对齐
    • ^ - 居中对齐
    • = - 将填充放在符号之后数字之前
    • + - 表示正负数都应该使用一个符号
    • - - 表示只有负数应该用一个符号
    • 空格 - 表示正数前用空格,负数前用负号
  • ord() - 输入字符,返回字符编码
  • chr() - 输入字符编码,返回字符
  • ascii() - 是ascii码中的返回该值,不是就返回u
  • repr() - 返回一个对象的string形式
lst = [1, 2, 3]
reversed(lst) # [3, 2, 1]

s = slice(1, 2, 1)
lst[s] # [2]

s = 'hello'
format(s, '<10') # '     hello'
format(s, '>10') # 'hello     '
format(s, '^10') # '  hello   '
format(-5, '=5') # '-   5'
format(5, '+') # '+5'
format(+5, '-') # '5'
format(5, ' ') # ' 5'

迭代器操作函数

  • iter() - 生成迭代器
  • next() - 获取下一个值
  • aiter() - 异步迭代器
  • anext() - 异步获取下一个值
  • enumerate() - 返回一个枚举对象,同时列出数据和数据下标,一般用在 for 循环当中
  • all() - 判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False
  • any() - 判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True
  • filter() - 用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象
  • map() - 根据提供的函数对指定序列做映射

输入输出函数

  1. 输出函数: print(内容)

    1. end的用法 print(需要打印的内容, end='结束后的打印')
    2. sep的用法 print(需要打印的内容, sep='分隔的符号')

      print(100, 111, 222, sep='+', end=';\n')   #100+111+222;\n
      
  2. 输入函数:input(屏幕提示信息)

    注意: python2中应该使用raw_input,python2中input会用eval进行计算

进制转换

二进制:

  • 表示方法: 加前缀0b或0B, 例如 0b1010
  • 转换方式: bin(数字)

八进制:

  • 表示方法: 加前缀0o或0O, 例如 0o12
  • 转换方式: oct(数字)

十六进制:

  • 表示方法: 加前缀0x或0X, 例如 0xa
  • 转换方式: hex(数字)

二进制和字符串的转换:

  • 字符串转二进制: bytes(字符串, encoding='utf-8') / 字符串.encode()
  • 二进制转字符串: str(二进制, encoding='utf-8') / 二进制.decode(encoding='utf-8')

原码反码和补码

正数的原码反码和补码都是一样

90(10) -> 01011010(原码) -> 01011010(反码) -> 01011010(补码)

负数的原码是其绝对值的原码最高位(符号位)变为一

反码是符号位不变,其余位取反

补码是反码加一

-90(10) -> 1 1011010(原码) -> 10100101(反码) -> 10100110(补码)

变量声明

  1. 同时声明多个变量赋相同的值: 变量名1 = 变量名2 = ... = 值
  2. 同时声明多个变量赋不同的值: 变量名1, 变量名2,... = 值1, 值2,...

变量三要素: 值、地址、类型

  1. id(变量/数据) - 获取变量/数据的地址
  2. type(变量/数据) - 获取变量/数据的类型

运算符

数学运算符

+(加), -(减), *(乘), /(乘), %(取余), //(整除), **(幂运算)

比较运算符

  • > - 大于
  • < - 小于
  • >= - 大于等于
  • <= - 小于等于
  • == - 等于
  • != - 不等于

注意:

  • 所有的比较运算符的运算结果都是布尔值
  • is判断的是数据的地址是否相等
  • ==判断的是数据的值是否相等

逻辑运算符

  • and - 逻辑与运算
  • or - 逻辑或运算
  • not - 逻辑非运算

注意:

  • 所有的逻辑运算符的运算结果都是布尔值

逻辑运算符的短路:

  • and的短路操作: and前面的条件如果是False, 那么and后面的条件语句不会执行
  • or的短路操作: or前面的条件如果是True,那么or后面的条件语句不会执行

逻辑运算符的数字运算

"""
num1 and num2 - 如果num1是0结果就是0,如果num1不为0结果是num2
num1 or num2 - 如果num1为0结果就是num2, 如果num1不为0结果就是num1
"""
print(6 and 7, 10 and 1, 0 and 3, -1 and 4)          #7 1 0 4
print(4 or 3, 2 or 10, 0 or 2)                   #4 2 2

赋值运算符

=, +=, -=, *=, /=, %=, **=

  1. 变量 = 值 - 将后面的值赋给左边的变量

    注意: 如果值是已经赋值过的变量,它将是将地址赋给变量

  2. +=, -=, *=, /=, %=, **=

    变量 += 值 -> 变量 = 变量 + 值

位运算

  • & - 按位与
  • | - 按位或
  • ^ - 按位异或
  • ~ - 按位取反
  • >> - 右移运算符
  • << - 左移运算符

成员运算符

  • in - 如果在指定的序列中找到了值返回True,否则返回False
  • not in - 如果在指定的序列中找到了值返回False,否则返回True

身份运算符

  • is - 判断两个标识符是不是引用一个对象,判断地址是否一样
  • is not - 判断两个标识符是不是引用不同的对象

运算顺序

优先级从高到低: 数学运算符 > 比较运算符 > 逻辑运算符 > 赋值运算

运算符优先级
**
~ +(正负号)
* / % //
+ -
>> <<
&
^ |
<= < > >=
== !=
= %= += -= //= /=
is    is not
in   not in
not   or   and

python语法结构

for循环

for 变量名 in 序列:
    循环体

range函数:

range(M, N, step) - 从M开始,每次加step产生下一个数字,到N为止(不包括N),M默认为0,可省略,step默认为1,可省略。

while循环

while 条件语句:
    循环体

if分之

if 条件语句1:
    代码段1
elif 条件语句2:
    代码段2
elif 条件语句3:
    代码段3
else:
    代码段N

三目运算符

值1 if 条件语句 else 值2 -> 如果条件语句的结果是True,那么整个运算的结果就是值1,否则是值2

三个关键字

  1. continue
    • continue是循环体中的关键字,只能用在循环体中。用的时候直接用。
    • 执行循环体的时候如果遇到continue,直接结束当次循环,进入下次循环的判断
  2. break
    • break是循环体中的关键字,只能用在循环体中;用的时候直接用。
    • 如果在执行循环体的时候遇到了break,那么整个循环直接结束
  3. else

    • 和else关联的循环自然死亡,else后面的代码段会执行;如果循环是因为遇到break而结束,else后面的代码段不会执行

      for 变量 in 序列:
        循环体
      else:
        代码段
      
      while 条件语句:
        循环体
      else:
        代码段
      

变量类型

数字类型

int:整型

  • 整型中 -5~256为不可变,其余为可变

float:浮点型

  • 支持科学计数法(3e4)

bool:布尔类型

  • True本质为1,False本质为0

complex:复数类型

  • j为虚数单位,j*j=-1

数据类型相关方法

  1. type(数据) - 获取指定数据类型
  2. isinstance(数据, 类型) - 判断指定的数据是否是指定的类型
  3. 类型(数据) - 将数据转换成指定类型,int() float() bool() str()
  4. abs(数据) - 取该数据的绝对值

任何数据类型的数据都能转换成布尔; 所有为零,为空的值都会转换成False,其他的都是True

为False的时候:

print(bool(0), bool(0.00), bool(''), bool([]), bool({}), bool(()), bool(None))

Random随机数

需要先import random

  1. 随机挑选
    • random.choice(序列) - 在序列中随机挑选出一个元素
  2. 在指定范围内取一个随机数
    • random.randrange(开始, 结束, 步长)
    • random.randrange(结束) - 从0到结束之间选取一个随机数
  3. 产生[0, 1)的随机数
    • random.random()
  4. 随机排序
    • random.shuffle(列表) - 将列表中的元素随机排序(序列必须是可变的)
  5. 产生随机浮点数
    • random.uniform(m, n) - 产生[m, n]的随机浮点数
  6. 产生随机整数
    • random.randint(m, n) - 产生[m, n]的随机整数

数学方法

import math
#向上取整(得19)
print(math.ceil(18.1))
print(math.ceil(18.9))

#向下取整(得18)
print(math.floor(18.1))
print(math.floor(18.9))

#返回整数部分和小数部分(小数在前,整数在后)
print(math.modf(12.8)) # 0.8 12.0

#开平方
print(math.sqrt(16))

列表list

获取列表元素

  1. 获取单个元素

    列表[下标] - 获取列表中指定下标对应的元素

    • 0 ~ 长度-1(从前往后取)
    • -1 ~ -长度(从后往前取)
    • 0表示第一个元素, -1表示最后一个元素
  2. 获取部分元素(列表切片)

    • 列表[start:end:step] - 从开始下标开始取,每次下标值增加步长去取下一个元素,直到取到结束下标前一个元素为止。返回的数据一定是列表
    • 列表[start:end] - 步长为1
    • 列表[:结束下标:步长] / 列表[:结束下标]
      • 步长为正,从下标为0开始;步长为负,从最后一个元素开始
    • 省略结束下标: 列表[start::step] / 列表[start:]
      • 步长为正,取到最后一个元素为止;步长为负,取到第一个元素为止
    • 开始下标和结束下标都省略: 列表[::step] / 列表[:]

遍历列表

  1. 直接遍历元素

     for 元素 in 列表:
         pass
    
    • 变量取到的就是列表中的每个元素
  2. 通过遍历下标来遍历列表元素

     for 下标 in range(列表长度):
         元素 = 列表[下标]
    
    • 获取列表长度: len(列表)
  3. 同时获取值和下标

     for 下标, 元素值 in enumerate(列表):
         pass
    

增加元素

  • 列表.append(元素) - 在列表的最后中添加指定的元素。(直接影响原列表不会产生新的列表)
  • 列表.insert(下标, 元素) - 在列表指定下标前插入指定的元素
  • list.extend([元素1,元素2]) - 在list列表末端拆分增加多个元素;传入必须是数据容器

删除元素

  • del 列表[下标] - 删除列表中指定下标对应的元素 (del 列表 - 删除列表)
  • 列表.remove(元素) - 删除列表中指定的元素(如果这个元素有多个只删第一个)
  • 列表.pop() - 取出列表最后一个元素, 返回被取出的元素
  • 列表.pop(下标) - 取出列表中指定下标对应的元素,返回被取出的元素

更改元素

列表[下标] = 新值 - 将列表中指定下标对应的元素改成新值

列表的数学运算符

  1. 列表1 + 列表2 - 将两个列表中的元素合并在一个产生一个新的列表

     nums1 = [100, 10, 80]
     strs = ['abc', 'hello', 'how', 'are']
     print(nums1 + strs)  # [100, 10, 80, 'abc', 'hello', 'how', 'are']
    
  2. 列表 * N / N * 列表 - 列表中的元素重复N次产生一个新的列表

     nums1 = [100, 10, 80]
     print(nums1 * 3)  # [100, 10, 80, 100, 10, 80, 100, 10, 80]
    

列表的比较运算符

  1. ==, != -> 判断两个列表是相等/不相等(两个列表只有元素个数、元素的值和元素顺序都一样的时候才相等)

     list1 = [1, 2, 3]
     print(list1 == [1, 2, 3])  # True
     print(list1 is [1, 2, 3])  # False
     print([] is [])  # False
    
  2. 比较大小

    从第一个元素开始进行比较,ASCII值大的大,类型不同无法比较

列表的in和not in

  • 元素 in 列表 - 判断列表中是否存在指定的元素,结果是布尔
  • 元素 not in 列表 - 判断列表中是否不存在指定的元素,结果是布尔

相关函数

  • len(序列) - 统计序列中元素的个数(迭代器和生成器不行)
  • max(序列)/min(序列) - 求序列中元素的最大值/最小值(迭代器和生成器不行) 注意: 序列中的元素的类型必须一致,并且支持比较运算符
  • list(数据) - 将指定的数据转换成列表
  • sum(序列) - 求序列中所有元素的和(序列中的元素只能是数字)

相关方法

  • 列表.count(元素) - 统计列表中指定元素的个数;返回值是该元素的个数
  • 列表.index(元素) - 获取元素在列表中的下标(正值); 如果元素不存在则报错;如果元素有多个只获取第一个的下标
  • 列表.reverse() - 反向列表(不会产生新的列表)(改变本身的顺序)
  • 列表.clear()/列表名 = [] - 清空列表
  • 列表.copy() - 复制/拷贝列表中的元素产生一个新的列表, 和'列表[:]'的功能一样。这个拷贝是浅拷贝
  • 对列表中元素排序
    • 列表.sort() - 改变本身的顺序,默认升序,括号中填入reverse=True改为降序
    • 注意: 列表中的元素类型必须一致,而且元素本身支持比较大小的运算
    • sorted(序列, reverse=True) - 对序列中的元素排序(会产生一个新的列表),默认升序,reverse改为降序

元组tuple

元组简介

  • 元组就是不可变的列表(列表中除了增删改,以及 列表. 相关的方法,元组不能用,其他元组和列表一样)
  • 元组是容器型数据类型(序列); 将()作为容器的标志,多个元素用逗号隔开: (元素1,元素2,元素3...)
  • 元祖不可变,有序, 若元组的元素为列表,列表可以变
  • 只有一个元素的元组: (元素1,)
  • 没有元素的元组: ()
Tuple1 = (10,)
Tuple2 = ()

直接用逗号将多个数据隔开,表示一个元祖

Tuple2 = 10, 20, 30, 'abc'

获取元组元素

  1. 让变量的个数和元组中元素的个数保持一致

     point = (10, 100, 100)
     x, y, z = point
    
  2. 用多个变量分别取获取元素的时候,在一个变量前加*(这个变量就变成列表);

     tuple5 = ('小明', 18, 90, 78, 36, 85, '男', 180)
     name, *scores, sex, height = tuple5
     print(name, scores, sex, height) # 小明 [18, 90, 78, 36, 85] 男 180
    
  3. *的特殊用法2: 拆包

     nums = [1, 2, 3]
     print(nums)
     print(*nums)  # print(1, 2, 3)
    

元组方法

  • del 元组 - 删除元组
  • + - 元组连接
  • * - 元组重复
  • in/not in - 判断元素是否在元组中
  • 元组名[开始下标:结束下标] - 元组的截取
  • len(元组名) - 返回元组中元素的个数
  • min(元组名) - 返回元组中的最小值
  • max(元组名) - 返回元组中的最大值
  • tuple(列表) - 将列表转换为元组(元素去重)

字典dict

字典简介

  • python中字典使用的是hash方式保存的
  • 用hash码来决定对象的存放的地址
  • 告诉计算机自定义对象如何判断是否重复,需要重写对象的 __hash____eq__ 方法
  • 字典是容器型数据类型(序列); 将{}作为容器的标志,多个元素之间用逗号隔开(元素是键值对): {键1:值1, 键2:值2, ...}
  • 字典是键集合和值集合的一个映射,字典的keys()方法返回的就是一个键视图对象,该对象直接支持集合运算
  • 字典是可变的,无序的
  • 键 - 不可变(一般使用字符串),唯一
  • 值 - 任何类型的数据都可以,值可以相同

字典查找

  1. 获取单个元素

    • 字典[key] - 获取指定key对应的值,如果key不存在会报错
    • 字典.get(key)/字典.get(key, 默认值) - 获取指定key对应的值;如果key不存在不会报错,并且返回默认值(没有默认值返回None)
  2. 遍历字典

遍历字典取到的是字典中所有的key

#遍历key
for key in dict1:
    print(key)

#遍历value
for value in dict1.values():
    print(value)

#同时遍历key和value
for k, v in dict1.items():
    print(k, v)

#枚举key,并编号
for i, k2 in enumerate(dict1):
    print(i, k2)

字典增、改

  • 字典[key] = 值 - 当key存在,修改key对应的值;当key不存在,添加'key:值'的键值对

字典删除元素

  • del 字典[key] - 删除字典中指定key对应的键值对
  • 字典.pop(key) - 取出字典中指定key对应的值, 返回值就是被取出的值
  • 字典.clear() - 删除字典中所有的键值对
  • 字典.popitem() - 随机删除字典中的一对键值对

字典比较运算符

字典不支持: +、*、>, <, >=, <=; 只支持: ==, !=

==!= 判断时,只判断键值是否相等,与顺序无关

字典的in和not in

  • 键 in 字典 - 判断字典中是否存在指定的键

字典相关函数

  • len() - 计算字典键值对个数,即键的总数
  • dict(数据) - 将其他数据转换成字典;数据本身必须是序列,序列中的元素是小序列,

字典转换注意事项

  • 小序列有且只有两个元素,第一个元素不可变
  • 字典不能转换成数字,可以转换成布尔;
  • 字典转列表,将字典中所有的key作为列表元素

字典相关方法

  • 字典.clear() - 清空字典
  • 字典.copy() - 拷贝字典产生一个新的字典(浅拷贝)
  • dict.fromkeys(序列, 值) - 创建一个字典,将序列中的元素作为key,key对应的value都是指定的值
  • 字典.items() - 将字典中所有的键值对都转换成元组作为一个序列的元素
  • 字典.values() - 获取字典中所有的值,返回一个序列
  • 字典.keys() - 获取字典中所有的键,返回一个序列
  • 字典.setdefault(key, value) - 当key不存在的时候添加键值对(不会修改)
  • 字典1.update(字典2) - 将字典2中的键值对添加到字典1中
  • zip(key, value) - 将key和value序列中的值一一对应生成元组对元素

集合set

集合简介

  • python中集合的保存使用的是hash方式保存,
  • 用hash码来决定对象的存放的地址,
  • 告诉计算机自定义对象如何判断是否重复,需要重写对象的 __hash____eq__ 方法
  • 集合是容器型数据类型;将{}作为容器标志,多个元素用逗号隔开: {元素1, 元素2,...}
  • 集合是可变的、无序的
  • 集合中的元素必须是不可变的数据,而且是唯一(自带去重功能)
  • {} 表示空字典
  • set5 = set() 表示空集合
class Employee:
    def __init__(self, name, age, sex, partner):
        self.name = name
        self.age = age
        self.sex = sex
        self.partner = partner

    def __hash__(self):
        return hash('%s%s' % (self.name, self.sex))

    def __eq__(self, other):
        if self.name == other.name and self.sex == other.sex:
            return True

集合的元素查找

获取集合元素,只有遍历一种方法

for 变量 in 集合:
    pass

补充: 遍历字典和集合的时候,其实是遍历将字典或者集合转换成的列表

集合的元素增加

  • 集合.add(元素) - 在集合中添加一个元素
  • 集合.update(序列) - 将序列中的元素添加到集合中, 打碎插入

集合的删除

  • 集合.remove(元素) - 删除集合中指定元素

集合的更改

集合不支持该操作

集合的比较运算符

运算符: 支持判断相等的==, !=

集合的in和not in

判断集合中是否有该元素

集合的相关方法

len、max、min、sum、sorted、set

集合的数学运算

python中的集合直接支持数学的集合运算: |(并集), &(交集), -(差集), ^(对称差集), >/<(判断包含)

  • 集合1 | 集合2 - 将两个集合合并在一起
  • 集合1 & 集合2 - 获取两个集合的公共部分
  • 集合1 - 集合2 - 获取集合1中除了集合2剩下的部分
  • 集合1 ^ 集合2 - 获取集合1和集合2除了公共部分以外的部分
  • 集合1 > 集合2 - 判断集合1中是否包含集合2(判断集合2是否是集合1的子集)

字符串

字符串简介

  • 字符串是容器型数据类型(序列); 将''或""作为容器的标志,多个字符(元素)直接包含在引号中
  • 字符串是不可变的、有序的

  • 转义字符

    • 在指定的符号或者字母前加\来表示特殊功能或者特殊意义的字符
    • 注意: 一个转义字符的长度是1
    • \' - 表示一个单引号
    • \" - 表示一个双引号
    • \\ - 表示一个\
    • \n - 换行符
    • \t - 制表符
    • %% - 百分号
  • 编码字符

    • u4位的十六进制数表示一个字符; 数字对应值是字符对应的编码值

字符与编码值的转换

  • chr(编码值) - 获取编码值对应的字符
  • ord(字符) - 获取字符对应的编码值

字符串查找

  • 字符串[下标] - 获取单个字符
  • 字符串[开始下标:结束下标:步长] - 字符串切片
  • 直接遍历字符串/通过遍历下标遍历字符串 - 遍历字符串

字符串数学运算符

数学运算符: +, *

  • 字符串1+字符串2 - 将字符串1和字符串2拼接在一起产生一个新的字符串
  • 字符串 * N / N * 字符串 - 字符串重复N次产生一个新的字符串

比较运算符: >, <, >=, <= , ==, !=

  • 字符串比较大小: 从前往后比较两个字符串中相同位置上的字符的大小,谁的字符的编码值大,对应的字符串就大
  • 'A' <= char <= 'Z' - 判断字符是否是大写字母
  • 'a' <= char <= 'z' - 判断字符是否是小写字母
  • ('A' <= char <= 'Z') or ('a' <= char <= 'z') - 判断字符是否是字母
  • '\u4e00' <= char <= '\u9fa5' - 判断字符是否是中文字符
  • '0' <= char <= '9' - 判断字符是否是数字字符

字符串的in 和 not in

  • 字符串1 in 字符串2 - 判断字符串2中是否包含字符串1(判断字符串1是否是字符串2的子串)

相关函数: len、max、min、sorted、str

  • str(数据) - 将指定数据转换成字符串;(所有数据类型的数据都可以转换成字符串, 转换的时候是直接在数据本身外加引号)
  • 字符串转整型: 字符串去掉引号后本身就是一个整数,才能转换成整型
  • 字符串转浮点型: 字符串去掉引号后本身就是一个数字,就能转换成浮点数

格式化字符串

  1. 带有格式占位符的字符串 % (值1, 值2, 值3,...)

    • %s - 字符串
    • %d - 整型
    • %.Nf - 浮点型, N表示小数点后小数的位数,采用四舍五入的方式
    • %c - 字符(可以将字符编码转换成字符拼接到字符串中)

      name = '小明'
      message = name + ',你好,吃饭了吗?'
      age = 18
      gender = '男'
      weight = 50
      pay = 7500
      message = '%s今年%d岁,性别%s, 体重:%.1fkg, 薪资: %.2f元' % (name, age, gender, weight, pay)
      
  2. 带有{}的格式字符串.format(值1,值2,值3,...)

     message = '{2}, {0}, {1}, {0}, {1}, {1}, {2}'.format('小明', 10, 'abc')
     message = '{name}, {age} = {age}, {name}, {gender}'.format(name='张三', age=18, gender='男')
     message = '{name}, {age} = {age}, {name}, {gender}'.format(**{'name': 'Tom', 'age': 18, 'gender': '男'})
    
  3. 将f放在前面进行的f-string格式化

    • 格式字符串中约束小数位数的时候采用的时候四舍五入
    • {:.Nf} - 让数字保留N位小数

      name = '小明'
      age = 18
      gender = '男'
      weight = 50
      pay = 7500
      message = f'{name}今年{age}岁,性别{gender}, 体重:{weight:.1f}kg, 薪资: {pay:.2f}元'
      

字符串相关方法

  1. 字母大小写转换:
    • 字符串.upper() - 小写字母转大写: 编码值减去32
    • 字符串.lower() - 大写字母转小写: 编码值加上32
    • 字符串.swapcase() - 大小写转换(大变小,小变大)
    • 字符串.capitalize() - 字符串首字母大写
    • 字符串.title() - 字符串每个单词首字母大写
  2. 字符串对齐
    • 字符串.center(长度, 字符) - 产生一个指定长度的字符串,原字符串居中,剩下的部分用指定的字符填充
    • 字符串.ljust(长度, 字符) - 产生一个指定长度的字符串,原字符串放在左边,剩下的部分用指定的字符填充
    • 字符串.rjust(长度, 字符) - 产生一个指定长度的字符串,原字符串放在右边,剩下的部分用指定的字符填充
    • 字符串.zfill(长度) - 产生一个指定长度的字符串,原字符串放在右边,剩下的部分用字符0填充
  3. 查找
    • 字符串1.find(字符串2, 开始下标, 结束下标) - 在开始下标到结束下标前对应的范围内查找字符串2,默认从头到尾,没有返回-1
    • rfind - 为从右向左找
    • 字符串1.index(字符串2, 开始下标, 结束下标) - 在开始下标到结束下标前对应的范围内查找字符串2,默认从头到尾,没有的话报错
    • rindex - 为从右向左找
    • 字符串1.count(字符串2,开始下标,结束下标) - 返回字符串1中字符串2出现的次数,可以指定一个范围,默认从头到尾
  4. join()
    • 字符串1.join(序列) - 将序列中的元素用字符串1连接在一起产生一个新的字符串 (序列中的元素必须都是字符串)
  5. 字符串替换
    • 字符串1.replace(old, new) - 将字符串1中所有的old都替换成new,然后产生一个新的字符串
    • str.maketrans(字符串1,字符串2) - 创建字符串1和字符串2字符一一对应的映射表,
    • 字符串.translate(映射表) - 按照映射表将字符串中的字符串1进行替换为字符串2,产生一个新的字符串
  6. 字符串切割
    • 字符串1.split(字符串2) - 将字符串1中的字符串2作为切点,切割字符串1
    • 字符串1.lstrip(字符串2) - 截掉字符串1左侧的字符,默认为空格(去头)
    • 字符串1.rstrip(字符串2) - 截掉字符串1右侧的字符,默认为空格(去尾)
  7. 将字符串当作有效的表达式求值并返回结果

  8. eval() - 将字符串当作有效的表达式求值并返回结果,例如 eval('1+2+3') -> 6

其他类型

  • Boolean(布尔)
  • None(空)

函数

声明

函数名规范: 函数名应该小写,多个单词之间用下划线隔开。

语法:

def 函数名(参数列表):
​    函数说明文档
​    函数体

调用

语法: 函数名(实参列表)

调用过程:

  1. 回到函数声明的位置
  2. 用实参给形参赋值(传参);传参的时候要保证每个参数都有值
  3. 执行函数体
  4. 确定函数返回值
  5. 回到函数调用的位置,接着往后执行。

参数

参数类型

  • 位置参数: 让实参和形参一一对应,来给不同的形参赋不同的值 ​- 命名关键字参数: 以'参数名1=值1,参数名2=值2,...'的形式来传参
  • def(a, b, /, c, d, *, e, f): /前面为仅位置参数,*后面为命名关键字参数

参数默认值 - 形参

声明函数的时候,可以给形参赋默认值; 已经有默认值的参数在调用的时候可以不用传参

注意: 没有默认值的参数必须放在有默认值参数的前面

参数类型说明

  • 给参数设置默认值,默认值的类型就是参数的类型
  • 形参:类型名

不定长参数 - 参数个数不确定

  1. 在参数名前加*, 那么这个参数就会变成一个元祖去接收多个参数, 调用的时候不能使用关键字参数传参 ​2. 在参数名前加**, 那么这个参数就会变成一个字典去接收多个参数,调用的时候只能使用关键字参数传参

值的改变

  • 传入为string/tuple/number时,不会改变实参的值(非全局变量)
  • 传入为list/dict/set时,函数内改变元素的值会改变实参的元素的值(引用传递)

返回值

return 返回值

return 返回值1,返回值2,返回值3...

没有返回值,返回值就是none

变量的作用域

  • 全局变量: 没有声明在函数里或类里面的变量就是全局变量;作用域:从声明开始到文件(程序)结束任何地方都可以使用
  • 局部变量: 声明在函数中的变量就是局部变量;作用域:从声明开始到函数结束的任何地方都可以使用

global和nonlocal

  • globalnonlocal 只能在函数体中使用
  • global - 在函数中声明/修改全局变量,就在变量赋值前加 global 变量名
  • nonlocal - 想要在局部的局部中修改局部变量的值,就使用nonlocal

匿名函数

定义: 函数名 = lambda 形参列表:返回值

调用: 函数名(实参列表)

作用: 匿名函数能做到的普通函数都能做,普通函数能做到的匿名函数不一定能做到。

匿名函数在函数功能简单的情况下,代码更简洁

func1 = lambda x, y: x+y
sum1 = func1(10, 20)

递归函数

声明函数的时候,调用自己的函数就是递归函数; 循环能做的事情递归都可以做(死循环不行)

怎么写递归函数:

  1. 找临界值(让循环结束的条件), 在这儿必须让函数结束(return)
  2. 找关系: 找f(n)与f(n-1)的关系(当次循环和上次循环的关系)
  3. 假设函数的功能已经实现,通过f(n-1)去实现f(n)的功能

注意:

  • windows下默认最大递归深度为998 (实际测试打印到996)
  • python支持的最大递归深度不超过3925-3929 (实际测试打印到29934)

更改最大递归层数限制方法为:

import sys
sys.setrecursionlimit(100000)

测试最大递归层数方法:

def recursion(n):
    print(n)
    recursion(n+1)

if __name__ == '__main__':
    recursion(1)

偏函数

把一个参数固定住,形成一个新的函数

def int2(str, base=2):
    return int(str, base)

也可以使用from functools import partial后,用partial打造偏函数

from functools import partial
import pymysql

get_conn = partial(
    pymysql.connect,
    host='120.77.222.217', port=3306,
    user='root', password='123456', charset='utf8'
)

函数作为变量

  1. 函数就是变量: python中声明函数其实就是声明一个类型是function的变量,函数名就是变量名。变量能做的函数都能做
  2. 变量可以给别的变量赋值
  3. 重新给变量赋值
  4. 变量作为容器类型数据的元素
  5. 变量作为函数的参数

系统实参高阶函数: 列表.sort、sorted、max、min...中有个参数key,类型就是function。

装饰器

  • 装饰器的本质就是函数,是用来给函数添加功能用的
  • 不带参数的装饰器使用时不打圆括号

装饰器 = 实参高阶函数+返回值高阶函数+糖语法

  1. 语法:

     def 函数名1(fn):
         def 函数名2(*args, **kwargs):
             实现添加功能的代码
             fn(*args, **kwargs)
         return 函数名2
    
  2. 说明:

    • 函数名1 - 装饰器的名字(根据添加的功能来命名)
    • fn - 随便命名,类型是函数,指向的需要添加功能的函数
    • 函数名2 - 实现添加功能的函数,名字随便命名,一般为func
    • 在装饰函数前加@wraps(fn)的作用: 不改变使用装饰器原有函数的结构(如__name__, __doc__)
    • 使用了@wraps(fn)的装饰器使用原函数.__wrapped__可以取消装饰器

      from functools import wraps
      def 函数名1(fn):
         @wraps(fn)
         def 函数名2(*args, **kwargs):
             实现添加功能的代码
             fn(*args, **kwargs)
         return 函数名2
      
  3. 带参数的装饰器(多嵌套一层)

     def record_time(times=5):
         def decorator(func):
             @warps(func)
             def wrapper(*args, **kwargs):
                 total = 0
                 for _ in range(times):
                     start = time.time()
                     result = func(*args, **kwargs)
                     end = time.time()
                     total += end-start
                 print(f'执行的平均时间{total/times}')
                 return result
             return wrapper
         return decorator
    
  4. 定义类的装饰器

     class record_time:
         def __init__(self, times=5):
             self.times = times
         def __call__(self, func):
             @warps(func)
             def wrapper(*args, **kwargs):
                 total = 0
                 for _ in range(times):
                     start = time.time()
                     result = func(*args, **kwargs)
                     end = time.time()
                     total += end-start
                 print(f'执行的平均时间{total/times}')
                 return result
             return wrapper
    
  5. 装饰类的装饰器:

     # 创建单例类的装饰器
     def singleton(cls):
         instances = {}
         lock = RLock()
         @wraps(cls)
         def wrapper(*args, **kwargs):
             # 保证多线程安全
             if cls not in instances:
                 with lock:
                     if cls not in instances:
                         instances[cls] = cls(*args, **kwargs)
             return instances[cls]
         return wrapper
    
  6. 取消装饰器功能

     import re
     import time
     from functools import wraps
    
     def cal_time(f):
         @wraps(f)
         def func(*args, **kwargs):
             start = time.time()
             res = f(*args, **kwargs)
             print(f'{f.__name__} cost time: {time.time() - start}')
             return res
         return func
    
     @cal_time
     def search_str():
         for item in range(1000000):
             status = re.search(r'abc', "12345abc12345")
    
     if __name__ == '__main__':
         search_str()  # 带装饰器
         search_str.__wrapped__()  # 去掉装饰器
    

迭代器

  • 迭代器是实现了迭代器协议的对象,迭代协议指的都是包含 __next____iter__ 方法的对象
  • 迭代器是容器型数据类型(序列), 迭代器中的元素只能通过将其他序列转换成迭代器或者创建生成器
  • 迭代器中的元素: 如果需要查看元素,需要将元素从迭代器取出,而且一旦取出就不能再放回去
  • iter(序列) - 创建迭代器,将序列转换成迭代器并返回
  • isinstance(变量, Iterable) - 判断是否为迭代器

获取元素:

  • next(迭代器) / 迭代器.__next__() - 获取单个元素
  • for item in 迭代器 - 遍历迭代器
  • list(迭代器) – 将迭代器元素转换为列表

生成器

生成器就是迭代器,容器有产生数据的能力。

  • 怎么创建生成器: 调用一个带有yield关键字的函数,就可以得到一个生成器对象
  • 生成器产生数据的原理:
    1. 调用一个带有yield关键字的函数的时候,不会执行函数体,也不会获取返回值,而是创建一个生成器;
    2. 生成器能产生多少个数据,以及每个数据的值,看执行完函数体会遇到几次yield生成器就可以产生几个数据,
    3. yield后面的数据就是会产生的数据。
    4. 每次获取生成器的元素的时候,都会去执行相应的函数的函数体,执行到yield为止;
    5. 取下一个元素,从上次结束的位置接着往后执行。
  • yield 和 yield from的区别
    • yield from 后面跟的如果是个迭代器,则会解析迭代器,将其中的元素依次产生出来。
    • yield是一个生成器,如果要变为协程,需要send(None)
yield range(5) # range(0, 5)
yield from range(5) # [0, 1, 2, 3, 4]
def func1():
    print('=======')
    print('+++++++')
    yield 89
    # return
    print('!!!!!!!!')
    yield 100
gen1 = func1()
print('re:', gen1) 
print('next:', next(gen1)) 
print('第一次结束,第二次执行:')
print('next:', next(gen1))

生成式

常规生成式

生成式就是生成器的一种简写

  1. (表达式 for 变量 in 序列) - 序列有多少个元素,生成器就能产生多少个数据。

    相当于:

     def func1():
         for 变量 in 序列:
             yield 表达式
    
  2. (表达式 for 变量 in 序列 if 条件语句)

    相当于:

     def func1():
         for 变量 in 序列:
             if 条件语句:
                 yield 表达式
    

生成式变形

  1. 列表生成式
    • [表达式 for 变量 in 序列] 相当于 list((表达式 for 变量 in 序列))
    • [表达式 for 变量 in 序列 if 条件语句]
  2. 集合生成式
    • {表达式 for 变量 in 序列} 相当于: set((表达式 for 变量 in 序列))
    • {表达式 for 变量 in 序列 if 条件语句}
  3. 生成式转字典
    • dict(表达式 for 变量 in 序列)
  4. 生成器
    • (x*3 for x in [2, 4, 6, 8])

高阶函数

map

原型: map(fn,lsd)

参数: fn是函数,lsd是序列

功能: 将传入的函数依次作用在序列中的每一个元素,并把结果作为新的Iterator返回

reduce

使用reduce需要先导入from functools import reduce

原型: reduce(fn, lsd)

参数: fn是函数,lsd是序列

功能: 一个函数作用在序列上,这个函数必须接受两个参数,reduce把结果继续和序列的下一个元素累计运算

filter

原型: filter(fn, lsd)

参数: fn为函数,lsd为序列

功能: 用于过滤序列,把传入的函数依次作用于序列的每个元素,根据返回的是True还是False决定是否保留该元素

sorted

原型: sorted(lsd, key ,reverse=false)

参数: lsd为序列,key接收一个函数,reverse决定升序还是降序,默认升序

文件、json与pickle

文件

打开文件

文件对象 = open(file, mode='r',...,encoding=None,errors=None) - 以指定的方式打开指定文件并且返回文件对象

  • file - 字符串,本地文件路径,可以是绝对路径也可以是相对路径
    • 绝对路径: 文件在计算机上的全路径
    • 相对路径: 相对当前目录(代码文件所在的目录)
      • ./ - 代表当前目录
      • ../ - 代表当前目录的上层目录
      • .../ - 代表当前目录的上层目录的上层目录
  • mode - 字符串, 读写方式; 决定打开文件后能做什么,以及读写的数据的类型

    • r - 只读
    • w - 只写(清空原文件)
    • a - 只写
    • b - 二进制
    • t - 文本(字符串)
    • r(rt/tr) - 只读; 读到的数据的类型是字符串
    • rb/br - 只读; 读到的数据的类型是二进制
    • w(wt/tw) - 只写; 写入文件中的数据的类型是字符串; 打开后会清空原文件中的内容
    • wb/bw - 只写; 写入文件中的数据的类型是二进制; 打开后会清空原文件中的内容
    • a(at/ta) - 只写; 写入文件中的数据的类型是字符串
    • ab/ba - 只写; 写入文件中的数据的类型是二进制
  • errors - 错误处理

    • ignore - 忽略错误

注意

  • bt 中必须有一个,如果不写就是 t
  • encoding - 字符串, 文本文件的编码方式; 一般使用'utf-8';
  • 二进制数据不能设置encoding(mode带b都不能设置)
  • 同一个文件读写时的编码方式必须一致

关闭文件

  • 文件对象.close() - 关闭指定文件; 文件关闭后不能再进行读写操作

打开不存在的文件

  • 如果以读的形式打开一个不存在的文件,程序会报错: FileNotFoundError;
  • 如果以写的形式打开一个不存在的文件,程序不会报错,而且会自动创建这个文件再打开。

文件作用域

只有在文件作用域范围内才能操作文件; 离开文件作用域,文件会被自动关闭

with open(file, mode='r',...,encoding=None,...) as 文件对象:
​    文件作用域

操作文件

  1. 读操作 - 获取文件中的内容

    • 文件对象.read() - 获取指定文件对象中内容(从文件读写位置开始到文件结束),并且返回,可以读所有文件,括号中写一个数字表示一次读入多少字节的内容
    • 文件对象.readline() - 读一行内容(从文件读写位置到一行结束),并且返回,只能读文本文件
    • 文件对象.readlines() - 读取所有行并返回一个列表
  2. 写操作 - 修改文件中的内容

    • 文件对象.write(数据) - 将指定数据写入指定文件; 数据只能是结果是字符串的数据或者是二进制数据
    • 文件对象.flush() - 刷新缓冲区,write实际是将文件写入缓冲区,等待缓冲区自动刷新写入,flush主动刷新立即写入
  3. eval函数

    • eval(字符串) - 将字符串转换成列表或者字典; 字符串必须是去掉引号后本身就是一个列表或者字典

json数据

什么是json

  • json是一种数据格式;
  • 一个json有且只能有一个数据;这一个数据必须是json支持的数据类型的数据。

json支持的格式

  • 数字类型 - 包含所有的数字,小数中支持科学计数法。例如: 89, 12.89, -890, 3e4
  • 字符串 - 使用双引号引号来的数据。"hello", "1234", "abc\n232"
  • 布尔 - 只有true和false两个值
  • 空值 - null
  • 数组 - 相当于python中的列表, [元素1,元素2,元素3,...]
  • 字典 - 相当于python中的字典, {key1:value1, key2: value2,...} key只能是字符串

json转python

json.loads(数据) - 将json数据转换成python数据。

数据必须是字符串;字符串中的内容必须是json格式的数据

json python
数字 int/float
字符串 str; 可能会将双引号变成单引号
布尔 bool; true -> True, false -> False
空值 null -> None
数组 list
字典 dict

python转json

json.dumps(数据) - 将python数据转换成json格式的字符串

python json
int/float 数字
bool 布尔; True -> true; False -> false
str 字符串; 单引号都会变成双引号
None None -> null
list,tuple 数组
dict 字典

读写本地json

  • json.load(f) - 读本地json
  • json.dump(data, f) - 写本地json

Pickle

使用前需要先导入import pickle

pickle转python

pickle.loads(bytes_object) - bytes_object为二进制对象,返回二进制对象所封装的内容

python转pickle

pickle.dumps(obj) - obj为要转为pickle二进制的对象,返回已封装后的二进制数据

读写本地pickle

注意: file必须以二进制可写入模式打开

  • pickle.load(file,*,fix_imports=True, encoding="ASCII", errors="strict") - file为要读取的文件,*后面的都为关键字参数
  • pickle.dump(obj, file, protocol=None,) - obj为要写入文件的对象,file为写入到哪个文件,protocol为协议,python3默认支持协议3

异常与测试

捕获所有异常

try:
    正常执行的代码
except:
    遇到错误的代码
else:
    没有出现错误执行
finally:
    无论有没有错误都执行
其他语句

捕获指定异常

try:
    正常执行的代码
except 异常类型:
    遇到指定错误的代码
finally:
    无论有没有错误都执行
其他语句

同时捕获指定的多种异常

try:
    正常执行的代码
except(异常类型1,异常类型2,...):
    遇到指定错误的代码
finally:
    无论有没有错误都执行
try:
    正常执行的代码
except 异常类型1:
    遇到异常1执行的代码
except 异常类型2:
    遇到异常2执行的代码
...
finally:
    无论有没有错误都执行

finally

  • 以上所有的语法结构的最后都可以加一个finally, 加完后不会影响原结构的功能。
  • try后面的代码块不管发生什么情况,finally后面的代码块都会执行

断言

出错后会将后面的内容提示出来

def func(num, div):
    assert(div != 0), 'div不能为零'
    return num/div
print(func(10, 0))
# 结果:AssertionError: div 不能为零

异常抛出

raise 异常类型

自定义异常

class AgeError(Exception):
    def __str__(self):
        return '年龄的值应该在0~200之间'

raise AgeError

对函数进行测试

使用前需要先导入import unittest

import unittest
from 对函数进行单元测试 import mySum
from 对函数进行单元测试 import mySub

class Test(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        print('所有测试开始前自动调用')

    @classmethod
    def tearDownClass(cls):
        print('所有测试结束后自动调用')

    def setUp(self):
        print('每个测试开始时自动调用')

    def tearDown(self):
        print('每个测试结束时自动调用')

    # 为了测试mySum
    # 在函数名前加test_
    def test_mySum(self):
        self.assertEqual(mySum(1, 2), 3, '加法有误')

    def test_mySub(self):
        self.assertEqual(mySub(2, 1), 1, '减法有误')


if __name__ == '__main__':
    # 开始测试
    unittest.main()

# 或者使用命令行
# python -m unittest 测试文件名

对类进行测试

import unittest
from person import Person

class Test(unittest.TestCase):
    def test_init(self):
        p = Person('stolen', 20)
        self.assertEqual(p.name, 'stolen', '属性赋值有误')

    def test_getAge(self):
        p = Person('stolen', 22)
        self.assertEqual(p.getAge(), p.age, 'getAge函数有误')
if __name__ == '__main__':
    # 开始测试
    unittest.main()

对文档进行测试

使用前先导入import doctest

对文档进行测试必须严格按照命令行格式书写

import doctest
# doctest模块可以提取注释中的代码执行
def mySum(x, y):
    '''
    get The Sum from x and y
    :param x: first num
    :param y: second num
    :return: sum

    example
    >>> mySum(1,2)
    3
    '''
    return x + y

print(mySum(1, 3))

# 进行文档测试
doctest.testmod()

pytest

使用前安装pip install pytest

可以使用命令行执行 pytest 后自动查找测试文件 -v 显示详情

模块和包

什么是模块

python中一个py文件就是一个模块, 模块名就是py文件的文件名

模块的引用方式

  • import 模块名 - 导入指定的模块,导入后可以在当前模块中使用指定模块中所有的全局变量。以 '模块名.变量名'的方式去使用
  • from 模块名 import 变量名1,变量名2,变量名3,... - 导入指定的模块,导入后可以在当前模块中使用指定的全局变量。变量直接使用,不用加前缀
  • from 模块名 import * - 导入指定的模块,导入后可以在当前模块中使用指定模块中所有的全局变量。变量直接使用,不用加前缀
  • import 模块名 as 新模块名 - 导入指定模块,导入到给模块重新命名;在当前模块中应使用新的模块名
  • from 模块名 import 变量名1 as 新变量名1,变量名2, 变量名3 as 新变量名3,...

模块的引用原理

  1. 当我们通过import或者from-import去导入一个模块的时候,会将这个模块中的代码全部执行一遍
  2. 怎么导入模块的时候选择性的执行部分代码

     #代码段1 - 在被导入的时候会被执行的代码
     if __name__ == '__main__':
         #代码段2 - 在被导入的时候不会执行的代码,但是在当前模块直接执行又会被执行
    

原理: 当创建模块的时候每个模块中都有一个__name__属性,用来保存当前模块的模块名。它的值默认就是py文件的文件名。当直接运行这个模块的时候,模块中的__name__属性会临时变成__main__

包的介绍

python中包就是拥有__init__.py文件的文件夹

包的使用

  • import 包名 - 需要在__init__.py中通过'包名.模块名'的方式导入包中相应的模块
  • import 包.模块 [as 新名字]
  • from 包 import 模块1, 模块2,...
  • from 包.模块 import 变量1,变量2,....

hashlib/base64/百分号编码

什么是hashlib

  • 使用hashlib首先要导入import hashlib
  • hashlib是python提供用来产生摘要算法的模块。摘要算法又叫哈希算法、离散算法。例如: md5、sha相关算法。
  • 该算法不可逆(根据摘要(密文)不能获取/推导出原文)
  • 使用相同算法对相同的数据加密后的结果是一样的
  • 不同长度的数据通过相同的算法加密后的密文的长度是一样的

生成摘要(加密)

  • 哈希对象 = hashlib.算法名() - 根据算法创建hash对象
  • 哈希对象.update(数据) - 指定加密数据,数据必须是二进制数据
  • 哈希对象.hexdigest() - 获取以16进制形式表示的密文(摘要), 数据类型是字符串
import hashlib
hash1 = hashlib.md5()
hash1.update(password.encode())
pw = hash1.hexdigest()
print(pw)

base64原理

将原来数据用二进制表示出来,然后六位六位的取,用1-9a-zA-Z+/来表示,

base64方法

  • base64.b64encode() - 将二进制数据转换为base64编码
  • base64.b64decode() - 将base64编码数据转换为二进制

百分号编码

url中不允许出现非ascii码的字符,故需要进行百分号转换处理

使用前需要先导入from urllib.parse import unquote, quote

  • quote() - 将字符转换为百分号编码
  • unquote() - 将百分号编码转换为字符

OS模块

使用os模块首先要导入import os

  • os.system() - 执行操作系统命令
  • os.name - 获取操作系统类型,nt->Windows posix-> Linux、Unix或Mac OS
  • os.uname - 在非Windows系统中打印详细内容
  • os.environ - 获取操作系统中所有的环境变量
  • os.environ.get('PATH') - 获取指定环境变量
  • os.curdir - 获取当前目录
  • os.getcwd() - 获取当前工作目录,即当前python脚本所在目录
  • os.listdir() - 以列表形式返回指定目录下的所有文件
  • os.mkdir('目录名') - 在当前目录下创建新目录
  • os.rmdir('目录名') - 在当前目录下删除目录
  • os.stat('文件名') - 获取文件属性
  • os.rename('旧名字', '新名字') - 重命名
  • os.remove('文件名') - 删除普通文件
  • os.system('命令') - 运行shell命令
  • os.path.abspath('.') - 查当前的绝对路径
  • os.path.join(path1, path2) - 拼接路径
  • os.path.split(path) - 拆分路径(返回元组,第一个元素为路径,第二个元素为文件名)
  • os.path.splitext(path) - 拆分扩展名
  • os.path.isdir(path) - 判断是否是目录
  • os.path.isfile(path) - 判断文件是否存在
  • os.path.exists(path) - 判断目录是否存在
  • os.path.getsize() - 获得文件大小(字节)
  • os.path.dirname() - 获得文件目录
  • os.path.basename() - 获得文件名

时间与日期

time

使用time需要先导入import time

时间戳

1970年1月1日零时开始算起,以秒为单位

元组表示法

一种python的数据格式表示,这个元组有9个整型内容 year month day hours minutes seconds weekday Julia_day flag(1 或 -1 或0)

格式化时间字符串

  • %a - 本地(local)简化星期名称
  • %A - 本地完整星期名称
  • %b - 本地简化月份
  • %B - 本地完整月份名称
  • %c - 本地相应的日期和时间表示
  • %d - 一个月中的第几天(01-31)
  • %f - 当前时间的微秒
  • %H - 一天中的第几小时(24小时制,00-23)
  • %I - 第几个小时(12小时制,01-12)
  • %j - 一年中的第几天(001-366)
  • %m - 月份(01-12)
  • %M - 分钟数(00-59)
  • %p - 本地am或者pm的相应符
  • %S - 秒(01-61)
  • %U - 一年中的星期数。(00-53,星期天是一个星期的开始)第一个星期天之前的所有天数都放在第0周
  • %w - 一个星期中的第几天(0-6,0是星期天)
  • %W - 和U基本相同,W是以星期一为开始
  • %x - 本地相应日期
  • %X - 本地相应时间
  • %y - 去掉实际的年份(00-99)
  • %Y - 完整的年份
  • %Z - 时区的名字(如果不存在为空字符)
  • %% - ‘%’字符

时间方法

  • time.time() - 返回当前时间戳,浮点数形式,不需要参数,
  • time.gmtime(c) - 将时间c转为UTC时间元组
  • time.localtime(c) - 将时间戳c转为本地时间元组
  • time.mktime(b) - 将本地时间b转换为时间戳
  • time.asctime(b) - 将时间元组b转换为字符串
  • time.ctime(c) - 将时间戳c转换为本地时间字符串,相当于time.asctime(time.localtime(time.time()))
  • time.strftime('%Y-%m-%d %H:%M:%S', b) - 将时间元组转换成给格式的字符串,参数2为时间元组,如果没有参数2,默认转当前时间
  • time.strptime(q, '%Y-%m-%d %H:%M:%S') - 将时间字符串转换为时间元组
  • time.sleep(时间) - 延迟一个时间,整型或者浮点型
  • time.clock() - 返回当前程序的cpu执行时间,Unix系统始终返回全部的运行时间, Windows从第二次开始,都是以第一次调用此函数的开始时间戳作为基数
y1 = time.clock()
print(y1)
time.sleep(1)
y2 = time.clock()
print(y2)

datatime

  • 使用前需要先导入import datetime
  • 基于time封装

有五个类:

  • datetime - 同时有时间和日期
  • timedelta - 主要用于计算时间跨度
  • tzinfo - 时区相关
  • time - 只关注时间
  • date - 只关注日期

常用方法

  • datetime.datetime.now() - 获取当前时间
  • datetime.datetime(1996, 5, 18, 17, 0, 0, 123456) - 获取指定时间
  • 时间.strftime('%Y-%m-%d %X') - 将时间转换为字符串
  • datetime.datetime.strptime(时间字符串, '%Y-%m-%d %X') - 格式化字符串转化为datetime对象(格式要与转换为字符串时一致)

时间计算

d5 = datetime.datetime(1996, 5, 18, 17, 0, 0, 123456)
d6 = datetime.datetime.now()
d7 = d6 - d5
print(d7)
# 获取间隔的天数
print(d7.days)
# 间隔天数之外的秒数
print(d7.seconds)

calendar

使用前需要先导入import calendar

  • calendar.month(2019, 4) - 返回指定某年某月的日历
  • calendar.calendar(2019) - 返回指定年的日历
  • calendar.isleap(2000) - 闰年返回Ture,否则返回False
  • calendar.monthrange(2019, 12) - 返回某个月的weekday的第一天和这个月所有的天数
  • calendar.monthcalendar(2019, 4) - 返回某个月以每一周为元素的列表

Tkinter

使用前需要先导入import tkinter

使用结构

# 创建主窗口
win = tkinter.Tk()
# 设置标题
win.title('标题内容')
# 设置大小和位置
win.grometry('400x400+200+200')
# 设置不可改变窗口大小
win.resizable(0,0)
# 退出
win.quit()
# 刷新页面
win.update_idletasks()
win.update()

Label控件

显示文本控件 Label属性

  • text - 显示的文本内容,可以使用'\n'表示换行
  • bg - 背景色
  • fg - 字体颜色
  • font - 设置字体颜色和大小
  • width - 设置控件的宽
  • height - 设置控件的高
  • wraplength - 指定text文本中多宽进行换行
  • justify - 设置换行对齐方式
  • anchor - 文本在Label中的位置 n北 e东 s南 w西
  • center - 居中
  • background(bg) - 背景色
  • foreground(fg) - 前景色
  • borderwidth(bd) - 边框宽度
  • bitmap - 标签中的位图
  • image - 标签中的图片
  • textvariable - 显示文本自动更新,与StringVar等配合着用

Button控件

按钮控件

  • anchor - 指定按钮上文本的位置
  • background(bg) - 指定按钮的背景色
  • bitmap - 指定按钮上显示的位图
  • borderwidth(bd) - 指定按钮边框的宽度
  • command - 指定按钮消息的回调函数
  • cursor - 指定鼠标移动到按钮上的指针样式
  • font - 指定按钮上文本的字体
  • foreground(fg) - 指定按钮的前景色
  • height - 指定按钮的高度
  • image - 指定按钮上显示的图片
  • state - 指定按钮的状态(disabled)
  • text - 指定按钮上显示的文本
  • width - 指定按钮的宽度
  • padx - 设置文本与按钮边框x的距离,还有pady
  • activeforeground - 按下时前景色
  • textvariable - 可变文本,与StringVar等配合着用

Entry控件

输入控件

  • show='*' - 密文显示
e = tkinter.Variable()
entry = tkinter.Entry(win, textvariable=e)
# e就代表输入框这个对象
# 设置值
e.set('陈倔强好帅')
# 取值
print(e.get())
# 用控件的对象只能用get,不能用set
# entry.set('123')  # 报错
print(entry.get())

Text控件

文本控件: 显示多行文本

  • background(bg) - 文本框背景色
  • foreground(fg) - 前景色
  • selectbackground - 选定文本背景色
  • selectforeground - 选定文本前景色
  • borderwidth(bd) - 文本框边框宽度
  • font - 字体
  • show - 文本框显示的字符,若为*,表示文本框为密码框
  • state - 状态
  • width - 文本框宽度
  • textvariable - 可变文本,与StringVar等配合着用
  • height - 表示显示的行数

拥有insert方法,进行文本插入

text = tkinter.Text(win, width=30, height=3)
text.pack()
str = '羊皮卷之七我要笑遍世界。只有人类才会笑。树木受伤时也会流“血”,禽兽也会 因痛苦和饥饿而哭嚎哀鸣,然而,只有我才具备笑的天赋,可以随时开怀大笑。从今往后,我要培养笑的习惯。笑有助于消化,笑能减轻压力,笑,是长寿的秘方。'
text.insert(tkinter.INSERT, str)

Scrollbar控件

滚动条: 需要进行双向关联才有效

scroll = tkinter.Scrollbar()
text = tkinter.Text(win, width=50, height=7)
# side 放到窗体的哪一册, fill填充Y轴
scroll.pack(side=tkinter.RIGHT, fill=tkinter.Y)
text.pack(side=tkinter.LEFT, fill=tkinter.Y)
# 关联
scroll.config(command=text.yview)
text.config(yscrollcommand=scroll.set)

Checkbutton

多选框: 需要绑定tkinter变量,判断是否选中用变量.get()方式,返回True为选中,返回False为未选中

  • anchor - 文本位置
  • background(bg) - 背景色
  • foreground(fg) - 前景色
  • borderwidth - 边框宽度
  • width - 组件的宽度
  • height - 组件高度
  • bitmap - 组件中的位图
  • image - 组件中的图片
  • font - 字体
  • justify - 组件中多行文本的对齐方式
  • text - 指定组件的文本
  • value - 指定组件被选中中关联变量的值
  • variable - 指定组件所关联的变量
  • indicatoron - 特殊控制参数,当为0时,组件会被绘制成按钮形式
  • textvariable - 可变文本显示,与StringVar等配合着用
def updata():
    message = ''
    if hobby1.get() == True:
        message += 'money\n'
    # 清空text中的所有内容
    text.delete(0.0, tkinter.END)
    text.insert(tkinter.INSERT, message)

# 要绑定的变量
hobby1 = tkinter.BooleanVar()
# 多选框
check1 = tkinter.Checkbutton(win, text='money', variable=hobby1, command=updata)
check1.pack()

Radiobutton

单选框: 一组单选框需要绑定同一个变量

获取值可以使用值的方式进行

def updata():
    print(r.get())

# 一组单选框要绑定同一个变量
r = tkinter.IntVar()
radio1 = tkinter.Radiobutton(win, text='one', value=1, variable=r, command=updata)
radio2 = tkinter.Radiobutton(win, text='two', value=2, variable=r, command=updata)

Listbox

列表框

selectmode:

  • tkinter.BORWER - 支持鼠标按下选中元素
  • tkinter.SINGLE - 不支持鼠标按下选中元素
  • tkinter.EXTENDED - 支持shift和control选中
  • tkinter.MULTIPLE - 支持多选
  • listvariable - 绑定变量
  • 控件对象.insert(标志,元素) - 向列表中插入元素
    • 标志:
      • tkinter.END - 在最后插入
      • tkinter.ACTIVE - 在开始添加
  • 控件对象.delete(参数1,参数2) - 删除参数1为开始,参数2为结束的索引,如果不指定参数2,只删除第一个索引内容。
  • 控件对象.select_set(参数1,参数2) - 选中参数1为开始,参数2为结束的索引,如果不指定参数2,只选中第一个索引内容。
  • 控件对象.select_clear(参数1,参数2) - 取消选中
  • 控件对象.size() - 获取列表中元素的个数
  • 控件对象.get(参数1, 参数2) - 获取索引的元素
  • 控件对象,curselection() - 返回当前的索引项下标
  • 控件对象.selection_includes(选项) - 判断此索引项是否被选中
namelist = tkinter.Variable
lb = tkinter.Listbox(win, selectmode=tkinter.BROWSE, listvariable=namelist,)
lb.pack()
for item in ['good', 'nice', 'handsonme']:
    lb.insert(tkinter.END, item)

Scale

滑动条

  • tkinter.HORIZONTAL - 水平
  • tkinter.VERTICAL - 竖直
  • length - 水平时表示宽度,竖直时表示高度
  • tickinterval - 选择值将为该值的倍数
scale = tkinter.Scale(win, from_=0, to=100, orient=tkinter.HORIZONTAL, tickinterval=100, length=200)
scale.pack()
# 获取值
print(scale.get())
# 设置初始值
scale.set(20)

Spinbox

数值范围控件

  • increment - 步长, 默认为1
  • value - 最好不要与from_=0,to=100,increment=1同时使用。使用元组value=(0, 2, 4, 6, 8)
  • command - 只要值改变就会执行对应的方法
v = tkinter.StringVar()

def func():
    print(v.get())

sp = tkinter.Spinbox(win, from_=0, to=100, textvariable=v, command=func)

v.set(20)

顶层菜单

参数:

  • tearoff - 分窗,0为在原窗,1为点击分为两个窗口
  • bg, fg - 背景,前景
  • borderwidth - 边框宽度
  • font - 字体
  • activebackgound - 点击时背景,同样有activeforeground,activeborderwidth,disabledforeground
  • cursor
  • postcommand
  • selectcolor - 选中时背景
  • takefocus
  • title
  • type
  • relief

方法:

  • menu.add_cascade - 添加子选项
  • menu.add_command - 添加命令(label参数为显示内容)
  • menu.add_separator - 添加分隔线
  • menu.add_checkbutton - 添加确认按钮
  • delete - 删除
# 菜单条
menubar = tkinter.Menu(win)
# 显示顶层菜单
win.config(menu=menubar)
# 创建一个菜单选项
menu1 = tkinter.Menu(menubar, tearoff=False)
# 给菜单选项添加内容
for item in ['Python', 'C', 'Java', 'C++', 'Shell', 'Matlab', 'Html', 'exit']:
    if item == 'exit':
        # 添加分割线
        menu1.add_separator()
        menu1.add_command(label=item, command=win.quit)
    else:
        menu1.add_command(label=item)

# 向菜单条上添加菜单选项
menubar.add_cascade(label='编程语言', menu=menu1)

右键菜单

menubar = tkinter.Menu(win)
# win.config(menu=menubar)

# 菜单
menu = tkinter.Menu(menubar, tearoff=False)
for item in ['Python', 'C', 'Java', 'C++', 'Shell', 'Matlab', 'Html', 'exit']:
    menu.add_command(label=item)

menubar.add_cascade(label='编程语言', menu=menu)

def shouMenu(event):
    menubar.post(event.x_root, event.y_root)

# 绑定右键事件(1、左键,2、滚轮,3、右键)
win.bind('<Button-3>', shouMenu)

Combobox

下拉控件

# 绑定变量
cv = tkinter.StringVar()
com = ttk.Combobox(win, textvariable=cv)
com.pack()

# 设置下拉数据
com['value'] = ('黑龙江', '吉林', '辽宁')

# 设置默认值
com.current(2)

def func(event):
    print('stolen is a good man')
    # 获取变量值
    print(com.get())
    print(cv.get())

# 绑定事件
com.bind('<<ComboboxSelected>>', func)

Frame

框架控件

类似html的div,主要进行布局

ttk.Treeview

使用需要先导入from tkinter import ttk

表格数据

tree = ttk.Treeview(win)
tree.pack()
# 定义列
tree['columns'] = ('姓名', '年龄', '身高', '体重')
# 设置列,列还不显示
tree.column('姓名', width=100)
tree.column('年龄', width=100)
tree.column('身高', width=100)
tree.column('体重', width=100)

# 设置表头 前面名称要和定义一样
tree.heading('姓名', text='姓名-name')
tree.heading('年龄', text='年龄-age')
tree.heading('身高', text='身高-height')
tree.heading('体重', text='体重-weight')

# 添加数据
tree.insert('', 0, text='line1', value=('哒哒', '20', '173', '120'))
tree.insert('', 1, text='line2', value=('哒哒2', '202', '1732', '1202'))
tree.insert('', 2, text='line3', value=('哒哒3', '203', '1733', '1203'))
tree.insert('', 3, text='line4', value=('哒哒4', '204', '1734', '1204'))
tree.insert('', 4, text='line5', value=('哒哒5', '205', '1735', '1205'))

树状数据

tree = ttk.Treeview(win)
tree.pack()

# 添加一级树枝
treeF1 = tree.insert('', 0, '中国', text='China', values=('F1'))
treeF2 = tree.insert('', 1, '美国', text='American', values=('F2'))
treeF3 = tree.insert('', 2, '英国', text='English', values=('F3'))

# 添加二级树枝
treeF1_1 = tree.insert(treeF1, 0, '黑龙江', text='中国黑龙江', values=('F1_1'))
treeF1_2 = tree.insert(treeF1, 1, '吉林', text='中国吉林', values=('F1_2'))
treeF1_3 = tree.insert(treeF1, 2, '辽林', text='中国辽林', values=('F1_3'))

treeF2_1 = tree.insert(treeF2, 0, '纽约', text='美国纽约', values=('F2_1'))
treeF2_2 = tree.insert(treeF2, 1, '旧金山', text='美国旧金山', values=('F2_2'))
treeF2_3 = tree.insert(treeF2, 2, '拉斯维加斯', text='美国拉斯维加斯', values=('F2_3'))

布局

place 绝对布局

label1 = tkinter.Label(win, text='good', bg='red')
# x为距离左边框的距离, y为距离上边框的距离
label1.place(x=10, y=10)
  • anchor - 组件对其方式
  • x - 组件左上角的x坐标
  • y - 组件左上角的y坐标
  • relx - 组件相对于窗口的x坐标,为0-1之间的小数
  • rely - 组件相对于窗口的y坐标,为0-1之间的小数
  • width - 组件的宽度
  • height - 组件的高度
  • relwidth - 组件相对于窗口的宽度,为0-1之间的小数
  • relheight - 组件相对于窗口的高度,为0-1之间的小数

pack 相对布局

  • after -将组件置于其他组件之后
  • before -将组件置于其他组件之前
  • fill - 填充方式
    • tkinter.X - 水平填充
    • tkinter.Y - 垂直填充
    • tkinter.BOTH - 水平和竖直方向填充
    • tkinter.NONE - 不填充
  • side - 停靠在窗口的哪个位置
    • tkinter.LEFT - 左
    • tkinter.RIGHT - 右
    • tkinter.TOP - 上
    • tkinter.BOTTON - 下
  • expand - 是否扩展
    • tkinter.YES - 扩展整个空白区域
    • no - 不扩展
  • anchor - 位置
    • N - 北 上
    • E - 东 右
    • S - 南 下
    • W - 西 左
label1 = tkinter.Label(win, text='good', bg='red')
label1.pack(fill=tkinter.Y, side=tkinter.LEFT)

grid - 表格布局

  • row - 第几行
  • column - 第几列
  • rowspan - 跨几行
  • columnspan - 跨几列
label1 = tkinter.Label(win, text='good', bg='red')
label1.grid(row=0, column=0)

事件绑定

控件名.bind(事件名,事件函数)

控件焦点设置: 控件名.focus_set()

鼠标点击事件

  • <Button-1> - 鼠标左键
  • <Button-2> - 鼠标中键
  • <Button-3> - 鼠标右键
  • <ButtonPress-1> - 鼠标左键
  • <ButtonPress-1> - 鼠标中键
  • <ButtonPress-1> - 鼠标右键
  • <Double-Button-1> - 双击鼠标左键
  • <Double-Button-2> - 双击鼠标中键
  • <Double-Button-3> - 双击鼠标右键
  • <Triple-Button-1> - 三击鼠标左键
  • <Triple-Button-2> - 三击鼠标中键
  • <Triple-Button-3> - 三击鼠标右键

鼠标移动事件

  • <B1-Motion> - 左键移动
  • <B2-Motion> - 中键移动
  • <B3-Motion> - 右键移动

鼠标释放事件

  • <ButtonRelease-1> - 鼠标左键释放
  • <ButtonRelease-2> - 鼠标中键释放
  • <ButtonRelease-3> - 鼠标右键释放

鼠标进入与离开事件

  • <Enter> - 鼠标光标进入控件时触发
  • <Leave> - 鼠标光标离开空间时触发

按键事件

  • <Key> - 响应所有键盘按键事件
  • <KeyPress-A> - 按下A键,A可用其他键替代
  • <Alt-KeyPress-A> - 同时按下alt和A,alt可用ctrl和shift替代
  • <Double-KeyPress-A> - 快速按两下A
  • Lock-KeyPress-A - 大写状态下按A

特殊按键事件

  • <Shift_L> - 左Shift
  • <Shift_R> - 右Shift
  • <F5> - F5按键
  • <Return> - 回车
  • <BackSpace> - 退格
  • <MouseWheel> - 滚动滚轮

窗口事件

  • Activate - 当组件由不可用转为可用时触发
  • Configure - 当组件大小改变时触发
  • Deactivate - 当组件由可用转变为不可用时触发
  • Destroy - 当组件被销毁时触发
  • Expose - 当组件从被遮挡状态中暴露出来时触发
  • Unmap - 当组件由显示状态变为隐藏状态时触发
  • Map - 当组件由隐藏状态变为显示状态时触发
  • FocusIn - 当组件获得焦点时触发
  • FocusOut - 当组件失去焦点时触发
  • Property - 当窗体的属性被删除或改变时触发
  • Visibility - 当组件变为可视状态时触发

响应事件

event对象(def function(event)):

  • char - 按键字符,仅对键盘事件有效
  • keycode - 按键名,仅对键盘事件有效
  • keysym - 按键编码,仅对键盘事件有效
  • num - 鼠标按键,仅对鼠标事件有效
  • type - 所触发的事件类型
  • widget - 引起事件的组件
  • width,heigh - 组件改变后的大小,仅Configure有效
  • x,y - 鼠标当前位置,相对于窗口
  • x_root,y_root - 鼠标当前位置,相对于整个屏幕

弹窗

messagebox._show函数的控制参数:

  • default - 指定消息框按钮
  • icon - 指定消息框图标
  • message - 指定消息框所显示的消息
  • parent - 指定消息框的父组件
  • title - 标题
  • type - 类型

simpledialog模块参数:

  • title - 指定对话框的标题
  • prompt - 显示的文字
  • initialvalue - 指定输入框的初始值

  • filedialog - 模块参数

  • filetype - 指定文件类型
  • initialdir - 指定默认目录
  • initialfile - 指定默认文件
  • title - 指定对话框标题

colorchooser模块参数:

  • initialcolor - 指定初始化颜色
  • title - 指定对话框标题

类和对象

什么是类和对象

  • 类是拥有相同功能和相同属性的对象的集合 - 类是抽象
  • 对象是类的实例 - 对象是具体的

类的声明和使用

类的声明

class 类名(object,metaclass=type):
    类的说明文档
    类的内容
  • class - 关键字,固定写法
  • 类名 - 程序员自己命名,必须是标识符,不能是关键字,见名知义,驼峰式命名并且首字母大写,不同使用系统提供的函数名、模块名或类名
  • metaclass - 指定元类
  • 类的说明文档 - 注释,主要说明类中提供的功能有哪些
  • 类的内容 - 包含类中的函数(方法)和属性
    • 方法: 对象方法、类方法和静态方法
    • 属性: 类的字段和对象属性

创建对象

  • 对象 = 类名(初始化参数) - 创建指定类对应的对象

类的方法

对象方法

  • 怎么声明: 直接声明在类中
  • 怎么调用: 用对象来调用
  • 特点: 自带参数self。self在调用的时候不用传参,系统会自动将当前对象传给它
  • 什么时候用: (实现函数功能需要对象) 实现函数的功能需要用到对象属性就使用对象方法

类方法

  • 怎么声明: 在装饰器@classmethod后面声明函数(声明前加@classmethod)
  • 怎么调用: 用类来调用
  • 特点: 有默认参数cls。cls在调用的时候不用传参,系统会自动将当前类传给它。(类能做的cls都可以做)
  • 什么时候用: (实现函数功能不需要对象的前提下,需要类)

静态方法

  • 怎么声明: 声明前加@staticmethod
  • 怎么调用: 用类来调用
  • 特点: 没有默认参数
  • 什么时候用: (实现函数的功能既不需要类也不需要对象)

类的属性

类的字段

  • 直接声明在类的里面函数的外面的变量就是类的字段
  • 怎么声明: 直接声明在类中
  • 怎么使用: 通过类来使用: 以'类.字段'的形式使用
  • 什么时候用: 保存的属性值不会因为对象不同而不一样的时候使用

对象属性

  • 怎么声明: 声明在init方法中, 以'self.属性 = 值'的形式声明
  • 怎么使用: 通过对象来使用: 以'对象.属性'的形式使用
  • 什么时候用: 属性值会因为对象不同而不一样的属性就声明成对象属性

构造方法和__init__方法

构造方法

  • 构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成
  • 构造方法就是用来创建对象函数;构造方法的名字和类名一样的。

python中的构造方法:

  1. 当声明类的时候,系统会自动创建一个函数名和类名同名的构造方法。
  2. 当通过对象方法创建对象的时候,会自动调用__init__方法来对对象进行初始化操作

__init__方法

__init__是类中一个特殊的对象方法;这个方法不需要主动调用, 用来对对象进行初始化

构造方法调用__init__方法

  1. 通过构造方法创建对象的时候,类中__init__会被自动调用
  2. 类中的__init__方法可以写也可以不用写,如果写函数名和参数self不能动,但是可以随意添加其他参数
  3. 如果__init__方法中有除了self以外的参数,那么创建对象的时候需要在构造方法中给这些参数传参

对象属性的增删改查

获取对象属性的值

  • 对象.属性 - 获取指定对象指定属性的值, 属性不存在会报错
  • getattr(对象, 属性名) - 获取指定对象指定属性的值,属性不存在会报错
  • getattr(对象, 属性名, 默认值) - 获取指定对象指定属性的值,属性不存在的时候不会报错而是返回指定的默认值

对象属性的增改

  • 对象.属性 = 值 - 当属性存在的时候,修改指定属性的值;当属性不存在的时候,给对象添加属性
  • setattr(对象, 属性名, 值) - 当属性存在的时候,修改指定属性的值;当属性不存在的时候,给对象添加属性

删除对象属性

  • del 对象.属性 - 删除对象中指定的属性
  • delattr(对象, 属性名) - 删除对象中指定的属性

类的魔术方法

  • 类.__name__ - 获取当前类的类名
  • 类.__doc__ - 获取类的说明文档
  • 对象.__class__ - 获取指定对象对应的类(和type的功能一样)
  • 类.__dict__ - 获取指定类中所有的字段和对应的值,以字典的形式返回
  • 对象.__dict__ - 获取对象所有的属性和对应的值,以字典的形式返回
  • 类.__module__ - 获取指定类所在的模块的模块名
  • 类.__bases__ - 获取当前类的父类
    • object - 是基类
  • __slots__ - 约束当前类的对象能够拥有哪些属性
    • 如果在类中给__slots__赋值:
    • 赋值后,__slots__对应的元组中的元素就是当前类的对象能够拥有的所有属性
    • 如果类中设置了__slots__的值,那么这个类的对象就不能使用__dict__属性
  • __call__ - 将一个类实例变成一个可调用对象,相当于把这个对象当作函数来使用。也就是实现了 () 运算符,即可调用对象协议
  • __enter____exit__ - 实现上下文语法,就可以使用with语法。如果enter有返回值,可以使用with...as...来接收这个值

私有化

  • 私有化的方式
  • 在需要私有化的属性名或者方法名前加__(双下划线)
  • 私有化的原理: 设置带有__开头的属性名和变量名,系统在保存的时候会自动在前面加_类名,导致直接访问访问不了

getter和setter

getter和setter的作用

  • 如果需要在获取属性值之前做别的事情,就给这个属性添加getter
  • 如果需要在给属性赋值之前做别的事情,就给这个属性添加setter

添加getter

  • 在需要添加getter的属性名前加_
  • 声明一个函数,声明前加@property。
  • 函数名就是不带_的属性名;除了self以外不能有别的参数;需要一个返回值 (需要返回属性的值)
  • 在类的外部使用这个属性的时候去掉_

添加setter

  • 属性如果要添加setter必须先添加getter
  • 保证属性名前有_
  • 声明一个函数, 声明前加@getter名.setter
  • 函数名是不带_的属性名; 除了self以外需要一个参数,不需要返回值(需要完成给属性属性的功能)
  • 在类的外部给这个属性赋值的时候去掉_

继承

继承简介

  • 让一个类直接拥有另一个类的属性和方法,这个过程就叫继承。
  • 父类: 被继承的类,又叫超类
  • 子类: 去继承别的类的类(继承者)

语法:

class 类名(父类1,父类2,父类3,...):
    类的说明
    类的内容
  • () - 可以省略,相当于(object); object是python中所有类直接或者间接父类,也叫基类
  • 父类 - 有()的时候,括号中可以写一个或者多个父类
  • __slots__只能约束当前类的对象,对子类没有约束效果

super

类中的函数的调用过程:

  1. 当通过类或对象去调用函数的时候,是先看当前类中有没有声明这个函数,如果有就直接调用自己的;
  2. 没有就去看父类中有没有,如果父类有就调用父类的;
  3. 如果父类中也没有就看父类的父类中有没有,...以此类推
  4. 如果找到object都没有声明这个函数,才报错
  5. 当调用了子类的__init__,父类的__init__将不再调用,若要继承父类的对象属性需要用:
    • super().__init__()
    • super(object,self).__init__()super().__init__()效果一样

注意: 静态方法中不能使用super()去调用父类方法

多重继承(多继承,左下原则)

  • 当存在多重继承的时候,按照继承图从左到右,从下到上进行
  • python中新式类用的广度优先搜索
  • python中旧式类用的深度优先

重载

函数重载

  • 重载指的是函数名相同,但是参数不一样的多个函数。
  • python不支持函数的重载
// c语言的函数重载
void func1(){
}
void func1(int a){
}
void func1(int a, int b){
}
void func1(char a, float b){
}
func1()
func1(10, 20)
func1(100)

运算符重载

  • python中使用不同的运算符对数据进行运算的时候,本质是在调用相应的方法
  • 当不同类型的数据使用相同的运算符的时候,调用的方法的方法名一样,但是方法不同
  • 看某种类型的数据是否支持某种运算符,就看这个类型对应的类中是否实现了相应的方法
  • self - 运算符前面的那个数据
  • other - 运算符后面的那个数据
  • 返回值 - 运算结果
  • 比较大小的运算符中,只要重载一个就可以
def __add__(self, other):       //重载+
    print(self, other)
    return self.age + other.age

枚举

继承Enum的类就是枚举, 枚举的特点: 不能创建对象

class PokerColor(Enum):
    """牌的花色类"""
    Hearts = '♥'
    Spade = '♠'
    Club = '♣'
    Diamonds = '♦'

析构函数

释放对象时自动调用(删除对象的时候调用)

class Person:
    def __del__(self):
        print('这里是析构函数')
per = Person()
del per

重写打印函数

  • __str__(): 在调用print打印对象时自动调用,是给用户的,是一个描述对象的方法
  • __repr__(): 是给机器的,在Python解释器里面直接敲对象名再回车后调用的方法(黑终端中使用) 注意: 在没有str时,且有repr,str = repr
class Person:
    def __str__(self):
        return '你好'
per = Person()
print(per)# 你好

__str__在有多层的时候,无法使用,只能使用__repr__

动态添加对象方法

动态添加对象方法需要先导入import types

import types
class Person(object):
    __slots__ = ('name', 'age')

per = Person()

def say(self):
    print('my name is '+ self.name)

per.speak = types.MethodType(say, per)
per.speak()

上下文实现

要能够使用with,需要在类中定义__entry____exit__方法

抽象类

定义:

from abc import ABCMeta, abstractmethod

# 此类只支持继承,不支持定义类
class Employee(metaclass=ABCMeta):

    def __init__(self, name):
        self.name = name

    @abstractmethod
    def get_salary(self):
        # pass可以不写
        pass

元类

元类实现单例:

from threading import RLock
class SingletonMeta(type):
    def __init__(cls, *args, **kwargs):
        cls.__instance = None
        cls.__lock = RLock()

    def __call__(cls, *args, **kwargs):
        if not cls.__instance:
            with cls.__lock:
                if not cls.__instance:
                    cls.__instance = super().__call__(*args, **kwargs)
        return cls.__instance

内存管理

内存开辟

内存分为栈区间和堆区间, python中所有的数据都是保存在堆区间的,栈区间中保存存储数据地址的变量。

每次需要一个数据的时候,python自动去开辟相应的空间;原则上只要需要数据就会开辟一个新的空间,哪怕数据和之前的数据是相等的也会重新开辟;但是数字和字符串特殊,每次给数字或者字符串开辟空间前会先检查这个数据在内存是否已经存在,如果存在就直接使用之前存储的数据,不存在才会重新开辟空间

内存释放

  • python中内存释放采用的是垃圾回收机制,当数据(堆中)的引用计数为0的时候,数据就会被自动销毁(被回收)
  • python中针对数据的循环引用已经做了特殊处理,程序员不用再写额外的代码去处理循环应用处理循环引用的方法为标记清除分代回收

引用计数

  • 当一个对象的引用被创建或者复制时,对象的引用计数加1
  • 当一个对象的引用被销毁时,对象的引用计数减1
  • 当一个对象的引用计数为0时,对象就会被销毁,释放内存

优点

  • 简单直观
  • 实时性,只要没有了引用就释放资源

缺点

  • 维护引用计数需要消耗一定的资源
  • 循环引用时,无法回收,解决办法是使用标记清除和分代回收

查看引用计数方法getrefcount()

标记清除

  • 标记清除不改动真实的引用计数,而是将集合中对象的引用计数复制一份副本,改动该对象引用的副本,对于副本做任何的改动,都不会影响对象生命周期的维护

分代回收

  • 将系统中所有的内存块根据其存活的时间划分为不同的集合,每一个集合就称为一个代,垃圾收集频率随着代的存活时间的增大而减小,也就是说,活得越长的对象,越不可能是垃圾,就应该减少对它进行垃圾回收的频率。通常使用几次垃圾回收的动作来衡量存活时间,经过垃圾回收的次数越多,意味着存活的时间越长

栈与队列

先进后出,如列表

stack = []
# 压栈(存数据)
stack.append('a')
stack.append('b')
stack.append('c')
# 出栈(取数据)
res = stack.pop()#c
res2 = stack.pop()#b
res3 = stack.pop()#a

队列

使用队列需要先导入import collections

通常用作目录遍历

import collections
# 创建队列
queue = collections.deque()
# 进队
queue.append('a')
queue.append('b')
queue.append('c')
# 出队
res1 = queue.popleft()#a
res2 = queue.popleft()#b
res3 = queue.popleft()#c

深拷贝和浅拷贝

使用深拷贝和浅拷贝需要先:import copy

浅拷贝

列表切片、列表.copy、字典.copy等都属于前拷贝,copy模块中的copy也是浅拷贝,可以拷贝任何数据

深拷贝

copy模块中的deepcopy是深拷贝

深拷贝和浅拷贝的区别

不管是浅拷贝还是深拷贝,赋值的时候都是先复制原数据产生一个新的数据,然后将新的地址赋给变量。如果拷贝对象中又有子对象(除了数字和字符串以外的数据), 浅拷贝地址原样赋值,不会拷贝子对象; 深拷贝,子对象也会被拷贝

a = [100, 200]
list1 = [1, 2, a]
list2 = copy.copy(list1)
list3 = copy.deepcopy(list1)
list1.append('abc')
print(list2, list3)
# [1, 2, [100, 200]] [1, 2, [100, 200]] 表示均产生了一个新的列表
a.append('1000')
print(list2, list3)   # [1, 2, [100, 200, '1000']] [1, 2, [100, 200]]

多线程和多进程

多线程

简介

使用多线程需要import threading

默认情况下一个程序中都有一个线程,这个线程叫主线程。主线程以外的线程叫子线程

多线程使用步骤

创建线程对象(需要一个子线程就需要创建一个线程对象)

Thread(target,args, name)

  • target - function(函数),需要在子线程中调用的函数
  • args - 元组, 接收在子线程中调用函数时,函数的实参
  • name - 给线程取名字
  • threading.current_thread().name - 获取当前线程的名字
  • 线程对象.start() - 让子线程执行任务(调用target对应的函数)
  • 线程对象.join() - 当线程对象中的任务全部完成后,再执行这条语句后面的其他语句,等待线程对象执行结束
def download(name):
    print('%s开始下载: %s' % (name, datetime.now()))
    time.sleep(3)
    print('%s下载结束: %s' % (name, datetime.now()))

# 守护线程,主线程结束,子线程也 就结束
t1 = threading.Thread(target=download, args=('葫芦娃',), deamon=True)
t2 = threading.Thread(target=download, args=('猫和老鼠',))
t1.start()
t2.start()

线程对象

通过创建Thread的子类对象来创建线程,启动线程就在子线程中自动调用子类中的run方法

import threading
import data
class DownloadThread(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self) -> None:
        print(threading.current_thread())
        print('%s开始下载: %s' % (self.name, datetime.now()))
        time.sleep(3)
        print('%s下载结束: %s' % (self.name, datetime.now()))

t1 = DownloadThread('葫芦娃')
t1.start()

多线程数据安全

# 创建锁
b_lock = threading.Lock()
# 加锁
b_lock.acquire()
# 释放锁
b_lock.release()

from threading import RLock
# 重入锁,当加锁内容需要调用另一个要枷锁的内容需要使用
lock = RLock()
lock.acquire()

案例

from time import sleep
from threading import Thread,Lock
class Account:
    """银行账号类"""
    def __init__(self, name, tel, password, balance=10):
        self.num = '728238278238823'
        self.user_name = name
        self.tel = tel
        self.password = password
        self.balance = balance
        self.lock = Lock()
    def save_money(self, num):
        print('存%s元钱' % num)
        self.lock.acquire()
        b = self.balance
        sleep(5)
        self.balance = b + num
        self.lock.release()
    def draw_money(self, num):
        print('取%s元钱' % num)
        self.lock.acquire()
        b = self.balance
        if b < num:
            print('余额不足')
            return
        sleep(5)
        self.balance = b - num
        self.lock.release()
    def show_balance(self):
        print('当前余额为:%s' % self.balance)
account = Account('余婷', '17273627323', '123123', 1000)
t1 = Thread(target=account.save_money, args=(1000,))
t2 = Thread(target=account.draw_money, args=(500,))
t1.start()
t2.start()
t1.join()
t2.join()
account.show_balance()

Semaphore控制最大进程数量

sem = threading.Semaphore(2)
def run():
    with sem:
        for i in range(10):
            print('%d' %i))
            time.sleep(1)

if __name__ == '__main__':
    for i in range(5):
        t = threading.Thread(target=run)
        t.start()
    t.join()
    print('主线程结束')

Barrier 凑够一定数量执行

bar = threading.Barrier(4)

def run():
    print('start')
    time.sleep(1)
    bar.wait()
    print('end')

if __name__ == '__main__':
    for i in range(5):
        t = threading.Thread(target=run)
        t.start()
    t.join()
    print('主线程结束')

Timer 延时执行

def run():
    print("I'm a good man")

# 延时执行线程
t = threading.Timer(5, run)
print('父线程开始')
t.start()
t.join()
print('父线程结束')

Event线程事件

def func():
    # 事件对象
    event = threading.Event()

    def run():
        for i in range(5):
            # 阻塞,等待事件触发
            event.wait()
            # 重置(必须进行)
            event.clear()
            print("I'm a good man")
    t = threading.Thread(target=run).start()
    return event

e = func()

# 触发事件
for i in range(5):
    e.set()
    time.sleep(2)
  • event.wait(timeout=None): 调用该方法的线程会被阻塞,如果设置了timeout参数,超时后,线程会停止阻塞继续执行;
  • event.set(): 将event的标志设置为True,调用wait方法的所有线程将被唤醒;
  • event.clear(): 将event的标志设置为False,调用wait方法的所有线程将被阻塞;
  • event.isSet(): 判断event的标志是否为True。

Condition线程调度

cond = threading.Condition()

def run1():
    with cond:
        for i in range(0, 10, 2):
            print(threading.current_thread().name, i)
            time.sleep(1)
            cond.wait()
            cond.notify()

def run2():
    with cond:
        for i in range(1, 10, 2):
            print(threading.current_thread().name, i)
            time.sleep(1)
            cond.notify()
            cond.wait()

threading.Thread(target=run1).start()
threading.Thread(target=run2).start()
  • wait([timeout]): 线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。
  • notify(n=1): 通知其他线程,那些挂起的线程接到这个通知之后会开始运行,默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。
  • notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程

多进程

多进程简介

  • 进程是系统中程序执行和资源分配的基本单位,每个进程都有自己的数据段、代码段和堆栈段
  • 使用前先导入from multiprocessing import Process
  • linux中可以使用fork创建进程
  • 在子进程中修改全局变量对父进程中的全局变量没有影响,在创建子进程时对全局变量做了一个备份,父进程与子进程中的num时完全不同的两个变量

多进程使用步骤

# 创建进程对象
p = Process(target=run, args=('nice',))
# 启动进程
p.start()
# 父进程的结束不能影响子进程,让父进程等待子进程结束再执行父进程
p.join()
  • target - function(函数),需要在子线程中调用的函数
  • args - 元组, 接收在子线程中调用函数时,函数的实参
  • start - 启动进程
  • join - 等待子进程结束

进程池

from multiprocessing import Pool
pp = Pool(2)
for i in range(5):
    # 创建进程,放入进程池统一管理
    pp.apply_async(run, args=(i, ))

# 在调用join之前必须先调用close,调用close之后就不能再继续添加新的进程了
pp.close()
# 进程池对象调用join,会等待进程池中所有的子进程结束完毕再去执行父进程
pp.join()

进程间通信

from multiprocessing import Process, Queue

def write(q):
    for chr in ['A', 'B', 'C', 'D']:
        q.put(chr)

def read(q):
    while True:
        value = q.get(True)
        print('value = ' + value)

if __name__ == '__main__':
    # 父进程创建队列,并传递给子进程
    q = Queue()

    pw = Process(target=write, args=(q, ))
    pr = Process(target=read, args=(q,))
    pw.start()
    pr.start()

    # 等待写子进程
    pw.join()
    # pr进程里是个死循环,无法等待其结束,只能强行结束
    pr.terminate()
    print('父进程结束')
  • os.getpid() - 获取当前进程号

排列组合

使用前需要导入import itertools

排列

全排列:和位置有关,列表数字只能取一次

myList = list(itertools.permutations([1, 2, 3, 4], 3)) # 24

组合

和位置无关,列表数字只能取一次

myList = list(itertools.combinations([1, 2, 3, 4], 3))

排列组合同时使用

和位置有关,数字可以取多次

myList = list(itertools.product([1, 2, 3, 4, 5], repeat=4))

正则表达式

什么是正则

正则表达式是用来描述字符串规律的一种语法,可以更加方便的解决字符串匹配、字符

串查找、字符串切割等相关操作

字符

  • 普通字符 - 表示这个字符本身
  • . - 匹配任意字符
  • \w - 匹配字母、数字、下划线
  • \W - 匹配除开字母、数字、下划线的其他字符
  • \s - 匹配空白字符:空格、回车(\n)、制表符(\t)
  • \S - 匹配除开空白字符的其他字符
  • \d - 匹配一个数子字符
  • \D - 匹配非一个数子字符
  • [字符集] - 匹配字符集中任意一个字符
  • [^字符集] - 匹配不在字符集中的任意一个字符
  • [字符1-字符2] - 匹配编码值在字符1编码到字符2编码中的所有字符中的任意一个,字符1的编码值必须小于字符2
  • [0-9] - 数字字符,效果同与 \d
  • [\u4e00-\u9fa5] - 中文
  • [ \n\t] - 空白字符,效果同与 \s

检测字符

  • \b - 检测是否是单词边界(空白字符、标点符号、字符串开头和结束等)
  • \B - 检测是否不是单词边界
  • ^ - 检测是否是字符串开头(必须是在[]外面)
  • $ - 检测是否是字符串结尾(必须是在[]外面)
  • \A - 匹配整个的字符串开始,在re.M的模式下也是整个字符串开始
  • \Z - 匹配整个的字符串结尾,在re.M的模式下也是整个字符串结尾

次数控制

  • * - 匹配0次或多次
  • + - 匹配1次或多次
  • ? - 匹配0次或1次
  • {M} - 匹配M次
  • {M,} - 匹配至少M次
  • {M,N} - 匹配M到N次
  • {,N} - 匹配最多N次

贪婪匹配:所有不确定次数匹配均为贪婪匹配,如果要解决这个问题,在次数控制符号后面加?

*?,+?,??,{M,N}?,{M,}?,{,N}?

结构

分支

  • 正则1|正则2 - 分之,匹配满足正则1或正则2的内容

分组

() - 分组

  1. 做整体操作(\d{3}|[A-Z]{2})abc HKabc

  2. 重复内容 - 正则中在数字前加\, 用来重复它前面第几个分组匹配到的内容(一个括号就是一个分组)(\d{3})abc\1 123abc123123

还原特殊符号意义

转义字符

为了让正则中有特殊意义的符号的意义消失,而在这个符号前加\

放在特殊位置

除了^方法在[]的最开头,-放在[]中两个字符之间,其他单独存在有特殊意义的符号在[]中都是普通字符

python中的re

在python中使用正则表达式,需要先导入re模块import re

编译正则

compile(pattern, flags=0) pattern: 要编译的正则表达式

re_obj = re.compile(r'\d{3}')
re_obj.fullmatch('789')

匹配

  1. fullmatch(正则表达式,字符串) - 完全匹配,让整个字符串和正则表达式进行匹配。如果匹配成功返回匹配对象,否则返回None

  2. re.match(pattern, string, flags=0)

    • patter:匹配的正则表达式
    • string:要匹配的字符串
    • flag:标志位,用于控制正则表达式的匹配方式,值如下
      • re.I - 忽略大小写
      • re.L - 做本地户识别
      • re.M - 多行匹配,影响^和$
      • re.S - 是.匹配包括换行符在内的所有字符
      • re.U - 根据Unicode字符集解析字符,影响\w,\W,\b,\B
      • re.X - 使我们以更灵活的格式理解正则表达式

功能: 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,返回None

  1. 获取匹配结果(匹配到的子串)

    • 匹配对象.group() - 获取整个正则表达式匹配到的结果
    • 匹配对象.group(N) - 获取正则表达式中第N个分组匹配到的结果
  2. 获取匹配结果在原字符串中的范围 -返回:(开始下标,结束下标), 结束下标取不到

    • 匹配对象.span() - 获取整个正则表达式匹配结果在原字符串中的范围
    • 匹配对象.span(N) - 获取指定分组匹配结果在原字符串中的范围

3)获取原字符串 匹配对象.string

查找

  1. re.search(pattern, string, flags=0) - 扫描整个字符串,并返回第一个成功的匹配

    • patter - 匹配的正则表达式
    • string - 要匹配的字符串
    • flag - 标志位,用于控制正则表达式的匹配方式,值如下
      • re.I - 忽略大小写
      • re.L - 做本地户识别
      • re.M - 多行匹配,影响^和$
      • re.S - 是.匹配包括换行符在内的所有字符
      • re.U - 根据Unicode字符集解析字符,影响\w,\W,\b,\B
      • re.X - 使我们以更灵活的格式理解正则表达式
  2. re.findall(pattern, string, flags=0) - 扫描整个字符串,并返回结果列表

    • patter - 匹配的正则表达式
    • string - 要匹配的字符串
    • flag - 标志位,用于控制正则表达式的匹配方式,值如下

      • re.I - 忽略大小写
      • re.L - 做本地户识别
      • re.M - 多行匹配,影响^和$
      • re.S - 是.匹配包括换行符在内的所有字符
      • re.U - 根据Unicode字符集解析字符,影响\w,\W,\b,\B
      • re.X - 使我们以更灵活的格式理解正则表达式

      注意:

    • 如果findall中的正则表达式中有一个分组;返回列表中的元素只取匹配结果中分组对应的部分
    • 如果正则表达式中有多个分组,返回的列表中的元素是元祖,元祖中的元素是每个分组对应的结果
  3. re.finditer(pattern, string, flags=0) - 与findall类似,扫描整个字符串,返回的是一个迭代器

    • patter - 匹配的正则表达式
    • string - 要匹配的字符串
    • flag - 标志位,用于控制正则表达式的匹配方式,值如下
      • re.I - 忽略大小写
      • re.L - 做本地户识别
      • re.M - 多行匹配,影响^和$
      • re.S - 是.匹配包括换行符在内的所有字符
      • re.U - 根据Unicode字符集解析字符,影响\w,\W,\b,\B
      • re.X - 使我们以更灵活的格式理解正则表达式

切割

re.split(正则表达式,字符串) - 将字符串中所有和正则表达式匹配的子串作为切割点,对字符串进行切割;返回值是列表

替换

  • sub(pattern, repl, string, count=0, flags=0)
  • subn(pattern, repl, string, count=0, flags=0)

    • pattern - 正则表达式(规则)
    • repl - 指定的用来替换的字符串
    • string - 目标字符串
    • count - 最多替换次数
  • 功能: 在目标字符串中以正则表达式的规则匹配字符串,再把他们替换成指定的字符串,可以指定替换的次数,如果不指定,替换所有的匹配字符串

  • 区别: 前者返回一个被替换的字符串,后者返回一个元组,第一个元素是被替换的字符串,第二个元素表示被替换的次数

网络编程

使用前需要先导入import socket

TCP服务端

  1. 创建一个socket,参数1:指定协议 AF_INET 或AF_INET6,参数2:SOCK_STREAM执行使用面向流的tcp协议
  2. 绑定ip和端口
  3. 监听
  4. 等待连接
  5. 连接成功,收发数据
import socket

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1', 9999))
server.listen(5)
clientSocket, clientAddress = server.accept()
data = clientSocket.recv(1024).decode('utf-8')
clientSocket.send(data.encode())

TCP客户端

  1. 创建一个socket
  2. 绑定服务端
  3. 收发数据
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 9999))
client.send(data.encode())
info = client.recv(1024).decode('utf-8')

UDP服务端

  1. 创建一个socket, 参数1:指定协议 AF_INET 或AF_INET6,参数2:SOCK_DGRAM执行使用面向流的udp协议
  2. 绑定ip和端口
  3. 等待接收数据
  4. 发送数据
import socket

udpServer = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udpServer.bind(('127.0.0.1', 9998))
data, addr = udpServer.recvfrom(1024)
udpServer.sendto(info.encode('utf-8'), addr)

UDP客户端

  1. 创建一个socket
  2. 发送数据
  3. 接收数据
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(data.encode('utf-8'),('127.0.0.1', 9998))
info = client.recv(1024).decode('utf-8')

网络请求

使用前需要先导入import urllib.request

网页请求

import urllib.request
# 设置网页请求和超时时间,超时会报错
response = urllib.request.urlopen('htts://www.baidu.com', timeout=0.5)

# 请求的数据直接保存
urllib.request.urlretrieve('http://www.baidu.com', filename=r'E:\BaiduNetdiskDownload\python_study\18day\html file\file2.html')
# urlretrieve在执行的过程中,会产生一些缓存
# 清除缓存
urllib.request.urlcleanup()
  • req = urllib.request.Request(url, headers=headers) - 设置请求体
  • response = urllib.request.urlopen(req) - 发起请求
  • 返回对象.read() - 获取请求到的全部内容,
  • 返回对象.readline() - 读取一行
  • 返回对象.readlines() - 读取全部内容,返回一个列表
  • 返回对象.info() - 返回当前环境的有关信息
  • 返回对象.getcode() - 返回状态码
  • 返回对象.geturl() - 返回正在爬取的URL地址
  • urllib.request.unquote(url) - 对url进行解码,(中文进行识别)
  • urllib.request.quote(url) - 对url进行编码

Post请求

使用前需要先导入import urllib.request import urllib.parse

url = 'http://www.sunck.wang:8085/form'
data = {
    'username': 'sunck',
    'passwd': '666'
}
postData = urllib.parse.urlencode(data)
# 请求体
req = urllib.request.Request(url, data=postData)
response = urllib.request.urlopen(req)

抓取动态网页的数据

import urllib.request
import json
import ssl

def ajaxCrawler(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
    }
    req = urllib.request.Request(url, headers=headers)
    context = ssl._create_unverified_context()
    response = urllib.request.urlopen(req, context=context)
    jsonStr = response.read().decode('utf-8')
    jsonData = json.loads(jsonStr)
    return jsonData

# url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=unwatched&start=20&limit=20'
# info = ajaxCrawler(url)
# print(info)

for i in range(1, 11):
    url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=unwatched&start=' + str(i*20) + '&limit=20'
    info = ajaxCrawler(url)
    print(info)

requests

安装pip install requests

使用前导入import requests

请求:

  • r = requests.get(url, params=d) 参数d表示值为字符串的字典,d不是必须的
  • r = requests.post(url,data=data)post请求需设置请求参数data

响应:

  • r.status_code - 响应状态码
  • r.raw - 原始响应体,使用r.raw.read()读取
  • r.content - 字节方式的响应体,需要进行解码
  • r.text - 字符串形式的响应体,会自动根据响应头部的字符编码进行解码
  • r.headers - 以字典对象存储服务器响应头,字典见键不区分大小写,若键不存在返回none。
  • r.json() - Requests中内置的json解码器
  • r.raise_for_status() - 请求失败,抛出异常
  • r.url - 获取请求链接
  • r.cookies - 获取请求后的cookie
  • r.encoding - 获取编码格式

PyMySQL

使用前需要先导入import pymysql

连接数据库

连接对象 = pymysql.connect(参数名=参数值) - 创建一个数据库链接,返回一个数据库对象

说明:

  • host - mysql服务所在主机的ip
  • port - 端口(不是字符串)
  • user - 连接用户名
  • password - 连接密码
  • database - 数据库名
  • charset - 字符集,常用utf8
  • autocommit - 自动提交,默认关闭
  • cursorclass - 设置游标类型,默认为元组,设置为字典为pymysql.cursors.DictCursor

示例:db = pymysql.connect('localhost', 'root', 'stolen', 'stolen')

创建一个cursor()对象

  • cursor = 连接对象.cursor()
  • cursor = 连接对象.cursor(pymysql.cursors.DictCursor) - 指定为字典形游标,查询返回的结果就是字典结构。

执行查询相关语句

执行查询sql语句

cursor对象名.execute('sql语句')

示例: cursor.execute("SELECT version()")

获取查询返回的信息

接收变量 = cursor对象名.fetchone()

示例:data = cursor.fetchone()

说明:

  • fetchone() - 抓取一条查询结果记录,结果是一条数据的元组
  • fetchall() - 抓取剩下结果所有的查询结果,结果集是一个元组,元组元素是元组
  • fetchmany(M) - 抓取查询结果中指定个数条数据
  • rowcount() - 只读属性,返回execute()方法影响的行数

执行修改相关语句

执行修改sql语句

cursor对象名.execute('sql语句')

示例:cursor.execute('insert into bandcard values(0,100)')

提交修改

格式:连接对象.commit()

说明:如果不报错,说明提交成功,如果报错,说明提交失败

格式:连接对象.rollback()

说明:回滚到上次数据,通常提交失败使用

示例

import pymysql
sql = 'insert into bandcard values(0,100)'
try:
    cursor.execute(sql)
    db.commit()
    print('提交成功')
except:
    db.rollback()

断开连接

cursor对象名.close(), 数据库对象名.close

示例:cursor.close(), db.close()

常见错误

使用PyMySQL连接MySQL数据库

  • Connection reset by peer - 连接被对端重置 - 阿里云封IP - 安全管控中添加IP白名单
  • Can't connect to MySQL server on '1.2.3.4' (timed out) - 无法连接指定的服务器 - IP地址或者端口写错
  • Access denied for user 'root'@'1.2.3.4' (using password: YES) - 访问被拒绝 - 用户名或密码错误
  • Unknown database '...' - 未知的数据库 - 数据库名字写错了
  • AttributeError: 'NoneType' object has no attribute 'encoding' - AttributeError - 字符集写错了

mongoDB

使用前需要先导入from pymongo import MongoClient

连接步骤

  1. 连接服务器 conn = MongoClient('localhost',27017)
  2. 连接数据库 db = conn.mydb
  3. 获取集合 collection = db.student
  4. 操作集合
  5. 关闭连接 conn.close()

添加文档

  • collection.insert_ont(文档字典) - 添加一个文档
  • collection.insert_many(文档列表) - 添加多个文档

查询文档

  • res = collection.find({查询条件}) - 查询部分文档
  • res = collection.find() - 查询所有文档
  • res = collection.find({查询条件}).count()/res = collection.count_documents({查询条件}) - 查询统计
  • res = collection.find({'_id':ObjectId(id值)}) - 根据id查询
  • res = collection.find().sort('age',pymongo.DESCENDING) - 排序,按照age降序排列
  • res = collection.find().skip(2).limit(5) - 分页查询,跳过两条文档显示五条文档

更新文档

  • collection.update_one(查找条件字典,更新内容字典) - 更新文档

删除文档

  • collection.delete_one(查找条件字典) - 删除文档

redis

使用前需要先导入import redis

redis连接

redis模块提供了两个类,Redis和StricRedis, StrictRedis用于实现大部分官方的命令,Redis是 StrictRedis的子类,用于向后兼用旧版本。

语法:

  • cli = redis.Redis(host='地址', port=端口号, password='登录redis密码', db=数据库
  • cli = redis.StrictRedis(host='地址', port=端口号, password='登录redis密码', db=数据库

说明: 端口号为整型,不能用引号,数据库为数据库名,redis默认有16个,名为0到15

redis使用

redis中所有的命令在python中均变为方法:

示例:

  • cli.set('name', 'wangdachui')
  • cli.get('name')

缓冲数据执行

示例:

pipe = cli.pipeline()
pipe.set('p2', 'well')
pipe.set('p3', 'nice')
pipe.set('p4', 'cool')
pipe.set('p5', 'handsome')
pipe.execute()

说明: 减少服务器-客户端的tcp连接

内置模块

python内置函数

slice(start, stop [, step]) - 创建一个切片对象,该对象可以用在任何切片的地方

a = [1, 2, 3, 4, 5, 6, 7, 8 ,9, 10]
item = slice(2, 7)
a[item]  # [3, 4, 5, 6, 7]
item.start  # 2
item.stop  # 7
item.step  # 如果slice中没有step,则没有返回值
item.indices(length)  # 返回一个在length长度内的切片范围元组。

timeit

  • 计算程序运行时间模块
  • 使用前导入import timeit

timeit.timeit()

# stmt 需要测试的函数或语句,字符串形式
# setup 运行的环境,本例子中表示 if __name__ == '__main__':
# number 被测试的函数或语句,执行的次数,本例表示执行100000次add()。省缺则默认是10000次
# 综上: 此函数表示在if __name__ == '__main__'的条件下,执行100000次add()消耗的时间
t = timeit.timeit(stmt="add()", setup="from  __main__ import add", number=100000)

timeit.repeat()

# stmt 需要测试的函数或语句,字符串形式
# setup 运行的环境,本例子中表示 if __name__ == '__main__':
# number 被测试的函数或语句,执行的次数,本例表示执行100000次add()。省缺则默认是10000次
# repeat 测试做100次,python3.7默认为5
# 综上: 此函数表示 测试 在if __name__ == '__main__'的条件下,执行100000次add()消耗的时间,并把这个测试做100次,并求出平均值
t = timeit.repeat(stmt="add()", setup="from __main__ import add", number=100000, repeat=100)

heapq堆模块

使用前导入import heapq

  • heapq.nlargest(n, iterable, key=None) - 获取iterable中最大的前n个数
  • heapq.nsmallest(n, iterable, key=None) - 获取iterable最小的前n个数
  • heapq.heapify(x) - 将列表x在线性时间内就地转换为堆,其中第一个元素是最小的
  • heapq.heappop(heap) - 从堆中弹出最小的值
  • heappush(heap, x) - 将x压入heap堆中

collections模块

使用前导入 import collections

collections.defaultdict

作用: 让字典中的key具有默认值

from collections import defaultdict

d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
# d = {'a':[1, 2]}

d = defaultdict(set)
d['a'].add('1')
d['a'].add('2')
# d = {'a':{1, 2}}

collections.OrderedDict字典排序

作用: 保证字典有序

from collections import OrderedDict
# d是一个有序字典
d = OrderedDict()

collections.Counter

most_common([n]) - 返回出现次数最多的前n个元素

from collections import Counter
a = [1, 2, 3, 4, 5, 6, 7, 5, 2, 6, 3, 1, 6, 2, 6]
count = Counter(a)  # count本质上就是一个字典
count.most_common(3)  # [(6, 4), (2, 3), (1, 2)]
count.update(容器)  # 在之前计数的基础上将传入的容器统计进来

operator模块

使用前导入import operator

operator.itemgetter

根据某个或某几个字典字段来排序这个列表

rows=[{'fname':'Brian','lname':'Jones','uid':1003},{'fname':'David','lname':'Beazley','uid':1002},{'fname':'John','lname':'Cleese','uid':1001},{'fname':'Big','lname':'Jones','uid':1004}]

from operator import itemgetter
rows_by_fname = sorted(rows, key=itemgetter('fname'))
rows_by_lfname=sorted(rows, key=itemgetter('lname','fname'))

operator.attrgetter

自定义sorted排序字段

class User:
    def __init__(self, user_id):
        self.user_id = user_id
    def __repr__(self):
        return'User({})'.format(self.user_id)
def sort_notcompare():
    users=[User(23), User(3), User(99)]
    print(users)
    # 以下两个结果一样
    print(sorted(users, key=lambdau: u.user_id))
    sorted(users, key=attrgetter('user_id'))

uuid模块

使用前导入import uuid

  • uuid.uuid1().hex - 返回一个随机16进制的字符串

asyncio异步编程

  • async - 将函数异步化
  • await - 程序阻塞后释放处理器

使用前导入import asyncio

import asyncio
async def print_number(num):
    await asyncio.sleep(1)
    print(num)

loop = asyncio.get_event_loop()
# 多路函数异步协作
loop.run_until_complete(asyncio.wait([print_number(num) for num in range(10)]))

itertools

使用前导入import itertools

itertools.groupby

将字典或序列根据特定字段

# 表示返回一个rows通过data分组后的序列
groupby(rows, key=itemgetter('date')

signal

使用前导入import signal

  • signal.signal(signal.CTRL_C_EVENT, 回调函数) - windows监听退出事件
Copyright © book.stolenzc.com 2021-2024 all right reserved,powered by GitbookFile Modify: 2024-09-24 02:47:04

results matching ""

    No results matching ""