7、Python

1、Python

1.1 Python介绍

1.1.1 Python语言的介绍
  • Python就是—门解释型的编程语言,而且是现在世界上最流行的编程语言之一。
1.1.2 pip
  • pip管理Python包

    1. 安装指定的包:pip install<包名>
    2. 删除指定的包:pip uninstall<包名>
    3. 显示已经安装的包:pip list
    4. 显示已经安装的包,并且以指定的格式显示:pip freeze
    5. 安装required.txt文件里列出的安装包:pip install -r required.txt
  • 修改pip下载源

    pip install 包名 -i 国内源地址

    国内源地址:

    ​ 阿里云 https://mirrors.aliyun.com/pypi/simple/
    ​ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
    ​ 豆瓣(douban) https://pypi.douban.com/simple/
    ​ 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
    ​ 中国科学技术大学 https://pypi.mirrors.ustc.edu.cn/simplel

1.1.3 pycharm快捷键
  • 快捷键

    格式化代码:ctrl + l

    注释代码:ctrl + /

  • 修改快捷键

    File——Setting——Keymap

1.2 变量和数据类型

1.2.1 注释
  • 单行注释

    #单行注释
    
  • 多行注释

    """
    多行注释
    """
    '''
    多行注释
    '''
    
1.2.2 变量和数据类型
  • 变量的定义

    变量名 = 变量值

  • 数据类型

    类型实例
    intn = 1
    floatn = 1.1
    strn = “yang”
    complexn = complex(1,2)
    booln = True
    listn = [1,2,3]
    tuplen = (1,2,3)
    setn = {1,2,3}
    dictn = {1:2,2:True,“name”:“yang”}
  • type()

    使用type()查看数据类型

    n = 2
    m = 20.0
    t = "yang"
    k = True
    a = []
    b = ()
    c = {1,2}
    d = {1:2,2:"yang"}
    print(type(n),type(m),type(t),type(k),type(a),type(b),type(c),type(d))
    
1.2.3 标识符和关键字
  • 标识符

    变量名、函数名、类名、模块名等都可称为标识符

    #变量名
    n = 1
    #函数名
    def ok():
     	pass
    #类名
    class text():
     	pass
    #模块名
    import random
    
  • 标识符的命名标准

    1. 由字母、数字、下划线组成,且不能以数字开头。
    2. 严格区分大小写
    3. 不能使用关键字
    4. 命名尽量不要使用中文
    5. 顾名思义
    6. 命名规范:大、小驼峰命名法、 使用下划线连接
  • 常见关键字

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PqEaJXsb-1664335392573)(.\Img\0225.png)]

1.2.4 输出语句
  • print()

    print("1","2",sep = "_",end = "\n",file = None)
    
    1. sep:为分割符,默认为空格
    2. end:为换行符,默认为\n
    3. file:指定打印的位置,默认为None
  • 格式化输出

    id = 1
    name = "yang"
    age = 18
    score = 92.5
    print("id:%d,name:%s,age:%d,score:%.2f",%(id,name,age,score))
    print(f"id:{id},name:{name},age:{age},score:{score}")
    
  • 常用格式符号

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XNwLphAq-1664335392574)(.\Img\0226.png)]

1.2.5 输入语句
  • input()

    n = input("请输入信息:")
    
    1. input()返回一个字符串
    2. 括号里可以写提示信息
1.2.6 类型转换
  • 常见类型转换

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mVbsEtLp-1664335392575)(.\Img\0230.png)]

  • 其他类型转换

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FLXNaPMy-1664335392576)(.\Img\0227.png)]

  • 转换为int类型

    n = "10"
    print(int(n))
    
    m = "1a"
    #base = 16 表示以16进制输出
    print(m,base = 16)
    
  • 转换为float类型

    n = "10.2"
    print(float(n))
    
  • 转换为str类型

    n = 123
    print(str(n))
    
  • 转换为bool类型

    #转换值为False的bool类型
    a = ""			#空字串
    b = 0			#数值0
    c = None		#None
    d = ()			#空元组
    e = []			#空列表
    f = set()		#空集合
    g = {}			#空字典
    print(bool(a),bool(b),bool(c),bool(d),bool(e),bool(f),bool(g))
    
    #转换值为True的bool类型
    #除以上7种空类型外,其他都可以转换值为True的bool类型
    

1.3 运算符

1.3.1 算数运算符
  • 算数运算符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vWq4k5Cl-1664335392577)(.\Img\0228.png)]

    注意:优先级顺序:** 高于 *、/、// 、% 高于 +、-

  • 数字和字符串乘法的运用

    #多字符串进行重复复制
    n = 3
    m = "yang"
    print(m*n)
    
  • 字符串与字符串加法运算

    #将字符串进行连接
    n = "I "
    m = "LOVE "
    t = "YOU"
    print(n + m + t)
    
1.3.2 赋值运算符
  • 赋值运算符

    运算符描述实例
    =赋值运算符把=号右边的结果赋给左边的变量
    如num = 1 + 2 * 3,结果num的值为7
    +=加法赋值运算符c += a等效于c = c + a
    -=减法赋值运算符c -= a等效于c = c - a
    *=乘法赋值运算符*c = a等效于c = c * a
    /=除法赋值运算符c /= a等效于c = c / a
    //=整除赋值运算符c //= a等效于c = c // a
    %=取模赋值运算符c %= a等效于c = c % a
    **=幂赋值运算符c **= a等效于c = c** a
  • =

    #连着赋值
    x = y = z = 20
    #元组(可省略括号)
    n = 2,3,4 
    #拆包(变量和值的个数要对应)
    a,b,c = 1,2,3
    #长度可变变量赋值
    a,*b,c =1,2,3,4,1,9
    
1.3.3 比较运算符
  • 比较运算符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xZe4zLdJ-1664335392578)(.\Img\0236.png)]

  • 数字与字符串进行比较

    1. 数字 == 字符串,返回False。
    2. 数字 != 字符串,返回True,使用其他比较运算符将会报错。
  • 字符串和字符串做比较运算

    1. 按照字符的编码值逐一进行比较
  • 获取一个字符对应的编码

    ord("a")
    
  • 获取编码对应的字符

    chr(97)
    
1.3.4 逻辑运算符
  • 逻辑运算符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QJBkEC8D-1664335392579)(.\Img\0237.png)]

  • 取值问题

    1. 逻辑and运算在取值时,取第一个为False的值,若全部值为True,则取最后一个值。
    2. 逻辑or运算在取值时,取第一个为True的值,若全部值为False,则取最后一个值。
1.3.5 位运算符
  • 位运算符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oBKO5yk4-1664335392580)(.\Img\0238.png)]

  • 运算规则

    1. 按位与运算:将数字转为二进制再计算,同为1结果为1,否则为0
    2. 按位或运算:将数字转为二进制再计算,只要有1则为1,否则为0
    3. 按位异运算:将数字转为二进制再计算,同为1则为1,同为0则为1,否则为0
    4. 按位取反运算:将数字转为二进制再计算,1变0,0变1
    5. 左移运算:x << n <==> x * 2 ** n
    6. 右移运算:x >> n <==> x / 2 ** n
  • 二进制、八进制、十进制、十六进制

    # 二进制
    n = 0b0001			# 二进制以0b开头
    bin(12)				# 将其他进制数字转为二进制
    
    #八进制
    n = 0o34			# 八进制以0o开头
    oct(12)				# 将其他进制数字转为八进制
    
    #十进制
    n = 20
    
    #十六进制
    n = 0xf0384e		# 十六进制以0x开头	
    hex(12)				# 将其他进制数字转为十六进制
    
  • 例题分析1

    使用位运算,获取到十六进制颜色 0xF0384E 的RGB值,以十进制形式打印输出。

    color = 0xF0384E			# 1111 0000 0011 1000 0100 1110
    red = color >> 16			# 1111 0000
    green = color >> 8 & 0xFF	# 1111 0000 0011 1000 &
    							# 0000 0000 1111 1111 =
     						# 0000 0000 0011 1000
    bule = color & 0xFF			# 1111 0000 0011 1000 0100 1110 &
    							# 0000 0000 0000 0000 1111 1111 =
     						# 0000 0000 0000 0000 0100 1110
    print(color,green,bule)
    
1.3.6 运算符的优先级
  • 优先级(高——>低)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-el4I7Zl1-1664335392580)(.\Img\0239.png)]

1.4 流程控制语句

1.4.1 条件判断语句
  • 语法

    if 判断条件:
    	pass
    elif 判断条件:
    	pass
    .
    .
    .
    else:
    	pass
    
  • 三元表达式

    n = n1 if n1 > n2 else n2
    

    注:三元表达式可以嵌套,但不可使用elif

  • 例题分析1

    猜拳游戏

    import random
    
    while 1:
     	n = int(input("请输入剪刀(0)、石头(1)、布(2):"))
     	if n != 0 and n != 1 and n != 2:
         		print("你特喵出了个啥,请重新输入!!!")
         		continue
     	t = random.randint(0, 2)							
     	if n == t:
         		print("平局")
     	elif (n == 0 and t == 2) or (n == 1 and t == 0) or (n == 2 and t == 1):
         		print("你牛皮")
     	else:
         		print("小垃圾")
    
  • 指定生成范围随机整数

    import random 
    
    # 随机生成10~20之间的整数
    random.randint(10,20) 
    
1.4.2 循环语句
  • while语句

    1. 语法

      while 判断条件:
      	pass
      else:
      	pass
      
  • break、continue

    1. break是中断此循环语句。
    2. continue是跳过本次循环,进入下一次循环。
    3. break和continue只能出现在循环语句中(while、for)
  • 例题分析1(嵌套循环)

    求100以内的质数

    i = 100
    while i > 1:
     	j = 2
     	while j <= i ** 0.5:
         		if i % j == 0:
             		break
         	j = j + 1
     	else:
         		print(f"{i}是质数")
     	i = i - 1
    
  • 例题分析2(嵌套循环)

    打印九九乘法表

    i = 1
    
    while i <= 9:
     	j = 1
     	while j <= i:
         		print(f"{j}x{i}={i * j} ", end="")
         		j = j + 1
     	i = i + 1
     	print("\n")
    
  • 例题分析2(嵌套循环)

    冒泡排序

    list = [22, 50, 90, 1, 50, 70]
    print(f"排序前的序列:{list}")
    for i in range(len(list)):
     	for j in range(len(list) - i - 1):
         		if list[j] > list[j + 1]:
             		list[j], list[j + 1] = list[j + 1], list[j]
    print(f"排序后的序列:{list}")
    
  • for语句

    1. 语法

      for 循环变量 in 可迭代对象:
      	语句
      else:
          语句
        
      # 可迭代对象:字符串、列表、元组、字典、集合
      
  • range()

    range(n,m,k)是生成以步长k从n~m的数字

    1. n代表开始的的数字
    2. m代表结束的数字(生成的数字不包含m)
    3. k代表步长
  • 例题分析3

    求100以内的质数

    for i in range(2, 101):
     	for j in range(2, i):
         		if i % j == 0:
             		break
     	else:
         		print(f'{i}是质数')
    

1.5 字符串、列表、元组、字典、集合

1.5.1 字符串
  • 常用转义字符

    \'		# 单引号 
    \"		# 双引号
    \\		# 反斜杠
    \n		# 换行
    \r		# 回车
    \t		# 制表符
    
  • r"字符串"

    字符串前加入r,则表示字符串原样输出

  • 字符串输入、输出

    # 字符串输入
    n = input()
    
    # 字符串输出
    print("%s" % n)
    
  • 字符串下标

    n = "abcdef"
    n[i]			# 表示字符串的第i个字符
    
  • 字符串切片

    n = "abcdefghijklmn"
    n[i:j]			# 表示获取字符串的[i,j)子字符串
    n[i:j:k]		# 表示以步长为k获取字符串的[i,j)子字符串
    n[i:]			# 表示获取字符串从第i个字符开始到最后一个字符的子字符串
    n[:j]			# 表示获取字符串的[0,j)子字符串
    n[-i:-j]		# 表示获取字符串的从倒数第i个到倒数第j个的字符
    n[i:j:-k]		# 表示从后向前以步长k获取字符串
    
  • 字符串常用方法

    n = "abcdefghigk"
    
    # 获取字符串长度
    len(n)
    
    # 查找指定字符串是否存在字符串中,若找到返回下标,找不到则返回-1
    n.find("bc")			
    n.find("bc",3)			# 从下标3开始查找字符串是否存在指定字符串中
    n.find("bc",3,5)		# 从下标3开始到下标5结束查找字符串是否存在指定字符串中
    n.rfind("bc")			# 从右向前开始查找指定字符串是否存在字符串中
    
    # 查找指定字符串是否存在字符串中,若找到返回下标,找不到报异常错误
    n.index("bc")
    n.rindex("bc")			# 从右向前开始查找指定字符串是否存在字符串中
    
    # 判断字符串是否以指定字符串开头,返回值为bool类型
    n.startswith("bc")
    
    # 判断字符串是否以指定字符串结尾,返回值为bool类型
    n.endswith("bc")
    
    # 判断字符串是否是纯字母组成,返回值为bool类型
    n.isalpha()
    
    # 判断字符串是否是纯数字组成,返回值为bool类型
    n.isdigit()
    
    # 判断字符串是否是数字或字母组成,返回值为bool类型
    n.isalnum()
    
    # 判断字符串是否是纯空格组成,返回值为bool类型
    n.isspace()
    
    # 统计指定字符串在字符串中出现的次数
    n.count("bc")
    
    # 以指定字符串替换字符串中的子字符串
    n.replace("bc","cd")
    n.replace("bc","cd",2)		# 指定替换次数最多为2次
    
    # 以指定字符串分割字符串,返回值为list类型
    n.split("bc")
    n.split("bc",2)				# 最多以指定字符串分割2次
    n.rsplit("bc",2)			# 从右向左进行分割,最多分割2次
    n.splitlines()				# 以行(\n)对字符串进行分割
    
    # 以指定字符串分割字符串为三部分(指定字符串前,指定字符串,指定字符串后),返回值为元组
    n.partition("bc")
    n.rpartition("bc")			# 从右向左以指定字符串分割字符串为三部分
    
    # 对字符串首字母转换为大写
    n.capitalize()
    
    # 对字符串中的每个单词首字母转换为大写
    n.title()
    
    # 对字符串中的所有小写字母转换为大写
    n.upper()
    
    # 对字符串中的所有大写字母转换为小写
    n.lower()
    
    # 返回指定长度的字符串
    n.ljust(30)			# 若指定长度小于原字符串长度,返回原字符串
    					# 若指定长度大于原字符串长度,返回对原字符串左边进行空格补全
    n.rjust(30)			# 若指定长度小于原字符串长度,返回原字符串
    					# 若指定长度大于原字符串长度,返回对原字符串右边进行空格补全
    n.center(30)		# 若指定长度小于原字符串长度,返回原字符串
    					# 若指定长度大于原字符串长度,返回对原字符串两边进行空格补全
    
    # 删除空白字符串
    n.lstrip()			# 删除字符串左边的空格
    n.rstrip()			# 删除字符串右边的空格
    n.strip()			# 删除字符串两边的空格
    
    # 字符串的拼接
    n.join("123")		# 返回原字符串的每个字符与指定字符串的拼接
    n.join(["1","2"])	# 返回列表的每个元素和指定字符串的拼接
    n.join(("1","2"))	# 返回元组的每个元素和指定字符串的拼接
    
  • 字符串的format方法

    name = "yang"
    sex = "男"
    age = 18
    
    # 使用{}占位
    print("姓名:{},性别:{},年龄:{}".format(name,sex,age))
    
    # 使用{下标}占位
    print("姓名:{1},性别:{0},年龄:{2}".format(sex,name,age))
    
    # 使用{变量}占位
    print("姓名:{b},性别:{a},年龄:{c}".format(a=sex,b=name,c=age))
    
    # 使用{}和{变量}混合占位
    print("姓名:{},性别:{a},年龄:{}".format(name,a=sex,age))
    
    # 使用{下标}和{变量}混合占位
    print("姓名:{1},性别:{0,年龄:{a}".format(sex,name,a=age))
    
    # 对列表中元素使用{}占位
    names = ["a","b","c","d"]
    print("同学们:{},{},{},{}".format(*names))
    
    # 对字典中元素使用{key}占位
    student_info = ["name":"yang","sex":"男","age":18]
    print("姓名:{name},性别:{sex},年龄:{age}".format(**student_info))
    
    # 转换字段
    print("{name!a}".format(name="yang"))			#返回指定字符串的ASCII码
    
    # format对其他形式的操作
    print('编号:{:_>3}'.format("a"))			# 输出 编号:__a
    print('编号:{:_<3}'.format(2))			# 输出 编号:2__
    print(f'编号:{9:#>3}')					# 输出 编号:##9
    
  • 字符串编码

    # 将字符串转为ASCII码
    ord("a")
    
    # 将ASCII码转为对应的字符串
    chr(97)
    
    # 将字符串编码位二进制
    "yang".encode(encoding="utf8")
    
    # 将二进制解码位字符串
    b"\xe4".decode(encodeing="utf8")
    
1.5.2 列表
  • 列表

    列表是可变数据类型,支持增删改查

  • 空列表

    li = []
    
  • 可迭代对象转为列表

    list(可迭代对象)
    
  • 下标

    li = [1,2,3,4,5]
    
    # 使用下标获取列表中的元素
    li[0]			# 返回1
    li[4]			# 返回5
    
  • 切片

    li = ["yang",1,"123",True]
    
    # 使用切片获取子列表
    li[0:2]			# 返回["yang",1,"123"]
    
  • 列表的增删改查

    li = ["yang",1,"123",True]
    
    # 列表的增
    li.append("321")			# 在列表的最后插入指定元素
    li.insert(1,"456")			# 在列表的指定下标位置插入指定元素
    li.extend(["741","852"])	# 将列表和指定列表进行合并
    
    # 列表的删
    li.pop(1)					# 根据下标删除元素,返回值为删除的元素
    li.remove("123")			# 删除列表中的指定元素,若列表中无指定元素则报错
    del li[1]					# 根据下标删除元素
    
    # 列表的改
    li[1] = 2					# 使用下标来修改列表中的元素
    
    # 列表的查
    li.index("123")				# 返回查找元素的下标,若列表中无查找元素则报错
    li.index("123",1,3)			# 在指定范围内查找元素,返回查找元素的下标
    							# 若列表中无查找元素则报错
    
  • 列表元素的统计

    li = ["yang",1,"123",True]
    
    # 统计指定元素在列表中出现的次数
    li.count("123")
    
  • 列表的排序

    li = ["a","b","c","d"]
    
    # 对列表升序排序
    li.sort()
    
    # 对列表降序排序
    li.sort(reverse=True)
    
    # 对列表逆置(不排序)
    li.reverse()
    
  • 列表的遍历

    li = ["a","b","c","d"]
    
    # 操作下标
    for i in range(len(li)):
     	print(li[i])
     
    # 直接遍历列表
    for x in li:
     	print(x)
     
    # 使用enumerate内置类实现带下标的遍历
    for x in enumerate(li):
     	print(x[0],x[1])
    
    for x,v in enumerate(li):
     	print(x,v)
    
1.5.3 元组
  • 元组

    元组是不可变数据类型,只支持查,不支持增删改

  • 空元组

    di = ()
    
  • 元组的查

    tu = ("1","2","3","a","b","c")
    
    # 元组的查
    tu[0]				# 返回下标对应的值
    tu.index("3")		# 查找元组中指定元素的下标,若元组中无指定元素则报错
    
    # 统计元组中指定元素的个数
    tu.count("a")
    
    # 若元组中只有一个元素,需要在元素后加逗号
    tu = ("abc",)
    
1.5.4 字典
  • 字典

    1. 字典是可变的数据类型,支持增删改查
    2. 数据以键值对的形式存在,key唯一,且key必须是不可变的数据类型
  • 空字典

    di = {}
    
  • 字典的增删改查

    di = {"name":"yang",1:"123",2:"yang"}
    
    # 字典的增
    di["age"] = 18					# 若key值存在,则会修改key对用的values
    								# 若key值不存在,则增加新元素
    di.setdefault("height":170)		# 若key值存在,则不修改字典
    								# 若key值不存在,则增加新元素
    di.update({"weight":50})		# 若key值存在,则会修改key对用的values
    								# 若key值不存在,则增加新元素 
    # 字典的删
    di.pop("name")					# 根据key值删除元素
    di.popitem()					# 删除字段的最后一个元素
    del di							# 删除整个字典
    clear di						# 清空字典的所有元素
    
    # 字典的改
    di["name"] = "ssun"				# 若key值存在,则会修改key对用的values
    								# 若key值不存在,则增加新元素
     
    # 字典的查
    di["name"]						# 通过key值获取对应的values
    								# 若key值不存在,则报错
    di.get("name")					# 通过key值获取对应的values
    								# 若key值不存在,则返回None
    di.get("name","ssun")			# 通过key值获取对应的values
    								# 若key值不存在,则返回默认值 ssun
    
  • 字典的遍历

    di = {"name":"yang",1:"123",2:"yang"}
    
    # 通过key值获取values
    for k in di:
     	print(di[k])
     
    for k in di.key():
     	print(di[k])
     
    # 直接遍历values
    for v in di.values():
     	print(v)
     
    # key值和values一起使用
    for k,v in di.items():
     	print(k,v)
    
1.5.5 集合
  • 集合

    集合是无序且元素不可重复的数据类型

  • 空集合

    st = set()
    
  • 集合的增删

    st = {'zhangsan', 'lisi', 'jack', 'tom'}
    
    # 集合的增
    st.add("yang")
    st.update(["ssun","lang"])				# 将集合与列表合并,并去重
    st.update(("ssun",))					# 将集合与元组合并,并去重
    st.update(("name":"ssun","age":18))		# 将集合与字典的key值合并,并去重
    
    # 集合的删
    st.pop()					# 随机删除一个元素
    st.remove("yang")			# 删除元组中的指定元素,若删除的元素不存在,则报错
    
  • 集合的遍历

    st = {'zhangsan', 'lisi', 'jack', 'tom'}
    
    # 随机遍历
    for x in st:
     	print(x)
     
    for i,x in enumerate(st):
     	print(i,x)
    
1.5.6 公共方法
  • 公共方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aByQia1E-1664335392583)(.\Img\0247.png)]

    注:在对字典使用not或not in时,是判断的key值

1.5.7 列表推导式
  • 列表推导式

    列表推导式就是使用轻量级循环创建列表

  • 列表推导式的使用

    # 列表推导式中嵌套if
    # 获取1~100的偶数
    nums = [i for i in range(1, 101) if i % 2 == 0]	
    
    # 列表推导式中嵌套for
    # 返回(x,y)的数据
    points = [(x, y) for x in range(0, 5) for y in range(5, 10)]
    
    # 字典中的使用
    # 将字典的key和value互换
    di_1 = {"a": 100, "b": 200, "c": 300}
    di_2 = {v: k for k, v in dict1.items()}
    

1.6 函数

1.6.1 函数基础
  • 函数的定义

    # 语法
    def 函数名([参数...]):
    	pass
    
  • 函数的调用

    # 调用
    函数名([参数...])
    
    # 可指定形参的数据类型
    def test(a:int):
     	pass
    
  • 函数的返回值

    执行return语句,将结束函数执行

    # 使用return可返回指定数据类型的数据
    def test():
     	x = 10
     	y = 20
     	return x,y				# 返回一个元组
    #	return [x,y]			# 返回一个列表
    #	return {"x":x,"y":y}	# 返回一个字典
    #	return {x,y}			# 返回一个集合
    
  • 函数的参数

    定义形参的顺序:位置参数、可变的位置参数、缺省参数、可变关键字参数

    # 位置参数:是对照位置进行传参
    def test(name,age):
     	pass
    test("yang",18)					
    
    # 可变的位置参数:以元组的形式接受多个参数
    def test(*args):
     	pass
    test("yang",18,170)
    
    # 缺省参数:传参时需要指定形参变量,若不对其进行传参,则使用默认值
    def test(name="yang"):
     	pass
    test()				# 不对其传参,则使用默认值
    test(name="ssun")	# 对其传参,使用传入的值
    
    # 可变关键字参数:传参时需要需要指定形参变量,多个关键字参数
    def test(**kwargs):
     	pass
    test(name="yang",age=18,sex="男")
    
    # 位置参数、可变的位置参数、缺省参数、可变关键字参数
    def test(name,*args,age=18,**kwargs):
     	pass
    
1.6.2 函数高级
  • 变量的作用域

    1. 全局变量

      作用域时当前文件

    2. 局部变量

      作用域只在当前所定义的函数内部

    3. 若想在函数内部使用并改变全局变量

      n = 10				# 全局变量
      def test()global n		# 使用global关键字,表示在函数内部可以使用并改变此全局变量
      
    4. 查看所有的全局变量和局部变量

      # 查看全局变量
      globals()
      
      # 查看局部变量
      locals()
      
  • 可变/不可变数据类型

    1. 可变数据类型:列表、字典、集合

      若对其进行修改,则内存地址不会发生改变

    2. 不可变数据类型:数字、字符串、元组

      若对其进行修改,则内存地址会发生改变

    3. 获取变量的内存地址

      id()
      
    4. 使用可变/不可变数据类型传参

      使用可变数据类型:修改形参,不影响实参

      使用不可变数据类型:修改形参,影响实参

  • copy的使用

    # 列表中的copy
    li = [1,2,3,4]
    x = li.copy()					# li与x共享列表
    
    # 模块copy
    import copy
    
    di = {"name":"yang","age":18}
    x = copy.copy(di)				# 浅拷贝,复制字典的数据,并另开辟空间将其存储
    								# 即x与li所指向的字典不是同一个
    li = [1,2,3,4[5,6]]
    x = copy.copy(li)				# 浅拷贝,复制列表的数据,并另开辟空间将其存储
    								# 但是对于列表中的元素是列表的情况,不能将其复制
    								# 即x与li所指向的列表不是同一个
      								# 但是列表中是列表的元素仍旧被x与li共享
    li = [1,2,3,4[5,6]]
    x = copy.deepcopy(li)			# 深拷贝,复制列表的数据,并另开辟空间将其存储
    								# 即x与li所指向的列表不是同一个
    
1.6.3 递归函数
  • 例题分析1

    求斐波那契数列的第n个值

    # 不使用递归函数实现
    def fibonacci_sequence(n):
     	num_1 = num_2 = 1
     	for i in range(n - 1):
         		num_2,num_1 = num_1 + num_2,num_2
     	return num_1
    print(fibonacci_sequence(10))
    
    # 使用递归函数实现
    def fibonacci_sequence(n):
     	if n == 1 or n == 2:
        		return 1
     	return fibonacci_sequence(n - 2 ) + fibonacci_sequence(n - 1)
    print(fibonacci_sequence(10))
    
1.6.4 匿名函数
  • 匿名函数的介绍

    1. 语法

      lambda 参数列表:运算表达式
      
    2. 函数别名

      # 定义一个函数
      def test():
          pass
      
      # 将函数的返回值赋予变量
      x = test()
      
      # 将函数赋值给变量(相当于给函数起了个别名)
      y = test
      print(y())			# 使用此变量可对函数进行操作
      
    3. 匿名函数作为参数

      当把一个函数A当做另一个函数B的参数使用时,可以将函数A定义成为匿名函数

      def B(x,y,fn):
         	n = fn(x,y)
      	return n
      print(B(10,20,lambda x,y:x*y))
      
    4. 匿名函数使用场景

      persons = [
          {'name': 'jack', 'age': 18, 'height': 178},
          {'name': 'tony', 'age': 20, 'height': 180},
          {'name': 'zhangsan', 'age': 19, 'height': 177},
          {'name': 'lisi', 'age': 17, 'height': 179}
      ]
      
      # 把 persons 列表按照年龄降序排序
      persons.sort(key=lambda ele: ele['age'],reverse=True)
      print(persons)
      
1.6.5 常见内置函数
  • 输入输出函数

    # 输出
    print()
    
    # 输出
    input()
    
  • 数序相关函数

    # 绝对值
    abs()
    
    # 取得整除商和余数
    divmod(除数,被除数)			# 得到一个元组(商,余数)
    
    # 幂运算
    pow(x,n)
    
    # 对浮点数四舍五入
    round(浮点数值,小数点保留的位数)
    
  • 可迭代对象相关函数

    # 查看可迭代对象里所有的元素转换成为布尔值是否全是True
    all(可迭代对象)
    
    # 查看可迭代对象里的元素转换成为布尔值,是否有一个是True
    any(可迭代对象)
    
    # 获取到可迭代对象的迭代器
    iter()
    
    # 获取到迭代器的下一个数据
    next()
    
    # 用来获取可迭代对象的长度
    len(可迭代对象)
    
    # 获取可迭代对象的最大/最小值
    max(可迭代对象)
    min(可迭代对象)
    
    # 用来排序,不改变原有的数据,生成一个新的结果
    sorted()
    # 例如
    tu = (9, 4, 2, 1, 6, 7, 8, 2, 3, 4, 6)
    x = sorted(tu)
    print(x)
    
    # 求和
    sum()
    
  • 判断相关函数

    1. callable()

      # 判断一个变量是否可以被调用(判断这个变量是否是函数的别名)
      def test():
          pass
      a = test
      print(callable(a))				# True
      
    2. isinstance()

      # 用来判断一个对象是否是由指定的类(或指定类的父类)创建的
      class A:
          pass
      class B:
          pass
      class C(A,B):
          pass
      p = C()
      print(isinstance(p,C))			# True
      print(isinstance(p,B))			# True
      print(isinstance(p,A))			# True
      print(isinstance(p,(A,B)))		# True
      
    3. issubclass()

      # 用来判断一个类是否是另一个类的子类
      class A:
          pass
      class B:
          pass
      class C(A,B):
          pass
      print(issubclass(C,A))			# True
      print(issubclass(C,B))			# True
      print(issubclass(C,(A,B)))		# True
      
  • 对象属性相关函数

    1. delattr()

      # 用来删除一个对象属性
      class Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
      p = Person("yang",18)				# 创建实例对象		
      delattr(p,"name")					# 删除实例对象p的name属性
      print(p.name)						# 报错,因为已经删除了其name属性
      
    2. getattr()

      # 用来获取一个对象的属性
      class Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
      p = Person("yang",18)				# 创建实例对象
      print(getattr(p, "name"))			# 获得实例对象p的name属性的值,<==> p.name
      
    3. setattr()

      # 用来设置一个对象的属性
      class Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
      p = Person("yang",18)				# 创建实例对象
      setattr(p,"name","ssun")			# 修改实例对象p的name属性的值
      									# <==> p.name = "ssun"
      print(p.name)						# 输出 ssun
      
    4. dir()

      # 用来列出一个对象所有的属性和方法
      class Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
      p = Person("yang",18)				# 创建实例对象
      print(dir(p))						# 输出实例对象的属性和方法列表
      
    5. vars()

      # 如果不传递参数,等价于locals;如果传递参数,用来将对象转换成为字典
      class Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
      p = Person("yang",18)				# 创建实例对象
      print(vars())						# 输出所在作用域的方法,<==> locals()	
      print(vars(p))						# 将实例对象p中的属性和值转为对应的字典
      									# <==> p.__dict__
      
  • 作用域相关函数

    # 查看全局变量
    globals()
    
    # 查看当前作用域局部变量
    locals()
    
  • 获取对象的内存地址的函数

    id()
    
  • 查看帮助文档函数

    help()
    
  • 打开一个文件,获取到文件流

    open()
    
  • 用来结束整个程序函数

    exit()
    quit()
    
  • 转换相关函数

    # 查看Unicode编码
    ascii()
    
    # 将数字转换成为二进制/八进制/十六进制
    bin()
    oct()
    hex()
    
    # 将字符转换成为对应的编码
    ord()
    
    # 获取编码对应的字符
    chr()
    
    # 将一个字符串转换成为python代码并执行
    eval()
    
    # 将一个对象转换成为字符串
    repr()
    
1.6.6 列表的常用操作
  • 列表的常用操作(reduce()、filter()、map())

    persons = [
     	{'name': 'jack', 'age': 18, 'height': 178},
     	{'name': 'tony', 'age': 20, 'height': 180},
     	{'name': 'zhangsan', 'age': 19, 'height': 177},
     	{'name': 'lisi', 'age': 17, 'height': 179}
    ]
    	
    from functools import reduce
    
    # 计算列表中用户的年龄和
    age = reduce(lambda x, y: x + y['age'], persons, 0)
    
    # 获取身高大于178的用户信息
    f = filter(lambda ele: ele['height'] > 178, persons)
    print(list(f))
    
    # 对列表中所有用户的年龄减一
    m = map(lambda ele: ele['age'] - 1, persons)
    print(list(m))
    
1.6.7 闭包
  • 什么是闭包

    一个内部函数对外部作用域的局部变量的引用,则认为此内部函数是闭包

  • 例题分析1

    def demo():
     	n = 10			# 对demo()函数中定义的变量
     	# 定一个内部函数
     	def inner():
       		nonlocal n	# 表示inner()对此外部变量拥有改变的权限
        		n = 20
     	inner()			# 调用内部函数
    
1.6.8 装饰器
  • 计算一段代码运行的时间

    import time
    
    # 定义一个计算1~1000的和的函数
    def factorial():
     	sum = 0
     	for i in range(1,10001):
         		sum = sum + i
     	return sum
    
    # 定义一个计算一段代码运行时间的函数
    def run_time(fn):
     	start_time = time.time()
     	sum = fn()
     	end_time = time.time()
     	return sum,end_time - start_time
    
    # 调用run_time()函数
    print(run_time(factorial))
    
  • 使用装饰器计算一段代码运行时间

    def run_time(fn):
     	def inner():
         		start_time = time.time()
         		sum = fn()
     		end_time = time.time()
     		return sum,end_time - start_time
     	return inner
    
    # 定义一个计算1~1000的和的函数
    @run_time
    def factorial():
     	sum = 0
     	for i in range(1,10001):
         		sum = sum + i
     	return sum
    
    # 调用factorial()函数其实调用的是inner()函数
    print(factorial())
    
  • 被装饰的函数带参数

    编写一个玩游戏超过时长将不能玩了,未达时长可继续玩耍

    def can_play(fn):
     	def action(name,game,*args,**kwargs):
         		if not args:
             		clock = kwargs.get("clock",5)
        		else:
             		clock = args[0]
         		if clock >= 5:
             		print("不能玩了!")
         		else:
             		fn(name,game)
     	return action
    
    @can_play
    def play_game(name,game):
     	print(f"{name}正在玩儿{game}")
     
    play_game("yang","王者荣耀",4)
    play_game("ssun","王者荣耀",clock=5)
    play_game("yang","绝地求生",3,clock=3,a="hhh",b="jjjj")
    
  • 使用装饰器验证权限

    验收用户有几个权限

    # 定义权限因子
    READ_PERMISSION = 1 
    WRITE_PERMISSION = 2  
    EXECUTE_PERMISSION = 4  
    DELETE_PERMISSION = 8  
    UPDATE_PERMISSION = 16  
    
    # 用户权限
    user_permission = 5
    
    # 定义函数来判断用户所拥有的的权限
    def check_permission(base_permission):
     	def handle_action(fn):
         		def do_action():
             		if user_permission & base_permission:
                 		fn()
         		return do_action
     	return handle_action
    
    # 读取权限
    @check_permission(READ_PERMISSION)
    def read():
     	print('读取权限')
        
    # 写入权限
    @check_permission(WRITE_PERMISSION)
    def write():
     	print('写入权限')
     
    # 执行权限
    @check_permission(EXECUTE_PERMISSION)
    def execute():
     	print('执行权限')
    
    # 删除权限
    @check_permission(DELETE_PERMISSION)
    def delete():
     	print('删除权限')
     
    # 更新权限
    @check_permission(UPDATE_PERMISSION)
    def update():
     	print('更新权限')
     
    # 查看用户的权限
    def user_all_permission():
     	read()
     	write()
     	execute()
     	delete()
     	update()
     
    # 调用user_all_permission()函数
    user_all_permission()
    
1.6.9 函数的综合练习
  • 名片管理系统

    # 名片管理系统
    # 添加名片
    # 用于存储用户名片
    persons = []
    # 用户编号
    user_id = -1
    
    # 添加名片
    def insert_user():
    	while 1:
    		name = input("请输入您的姓名:")
      		for x in persons:
          		if x["name"] == name:
              		print("您输入的用户名已存在,请重新输入!")
              		break
      	else:
          	break
    	tel = input("请输入您的手机号:")
    	qq = input("请输入您的QQ:")
    	global user_id
    	user_id = user_id + 1
    	di = {"id": user_id, "name": name, "tel": tel, "qq": qq}
    	persons.append(di)
    	return
    
    
    # 删除名片
    def delete_user():
    	while 1:
      		name = input("请输入您要删除的名片的名字:")
      		for x in persons:
          		if x["name"] == name:
              		while 1:
                  		n = input("您确定要删除吗?(yes/no):")
                  		if n.lower() == "yes":
                      		persons.remove(x)
                      		print("-" * 26 + "您已经成功删除了名片!" + "-" * 26)
                      		return
                  		elif n.lower() == "no":
                      		print("-" * 26 + "您已经退出删除名片页面!" + "-" * 26)
                      		return
                  		else:
                      		print("您输入的有误,请重新输入!")
      		else:
          		print("您输入的用户名字不存在,请重新输入!")
    
    
    # 修改名片
    def update_user():
    	while 1:
      		name = input("请输入您要修改的名片的名字:")
      		for x in persons:
          		if x["name"] == name:
              		print(f"您要修改的信息是:\
                          姓名:{x['name']},电话:{x['tel']},QQ:{x['qq']}")
              		new_name = name
              		while 1:
                 		new_name = input("请输入您的新名字:")
                  		for y in persons:
                      		if y["name"] == new_name and name != new_name:
                          		print("您输入的名字已经存在,请重新输入!")
                          		break
                  		else:
                      		break
              		tel = input("请输入您的手机号:")
              		qq = input("请输入您的QQ:")
              		# 可再一次确认操作
              		x["name"] = new_name
              		x["tel"] = tel
              		x["qq"] = qq
              		print("-" * 26 + "您已经成功修改了名片!" + "-" * 26)
              		return
      		else:
          		print("您输入的用户名字不存在,请重新输入!")
    
    
    # 查询名片
    def select_user():
    	name = input("请输入您要查询的名片的姓名:")
    	for x in persons:
      		if x["name"] == name:
          	print(f"查询的名片信息:姓名:{x['name']},电话:{x['tel']},QQ:{x['qq']}")
          	return
    	else:
      		print("您要查询的名片不存在...")
    
    
    # 显示所有名片
    def show_all_user():
    	print("序号".ljust(5), "姓名".ljust(15), "电话".ljust(15), "QQ".ljust(15))
    	for x in persons:
      		print(str(x["id"]).ljust(6), x["name"].ljust(17), x["tel"].ljust(16), 		  x["qq"].ljust(17))
    
    
    # 退出系统
    def exit_system():
    	while 1:
      	n = input("您确定要退出?(yes/no):")
      	if n.lower() == "yes":
          	print("-" * 26 + "您已经退出系统,欢迎下次光临!" + "-" * 26)
          	exit()
      	elif n.lower() == "no":
          	print("-" * 26 + "您已经退出了退出系统页面!" + "-" * 26)
          	return
      	else:
         	print("您输入的指令有误,请重新输入!")
    
    
    # 提示信息
    print(
    "-" * 26 + "名片管理系统 v1.0" + "-" * 26 + "\n 1:添加名片 \n 2:删除名片 \n 3:修改名片 \n 4:查询名片 \n 5:显示所有名片 \n 6:退出系统 \n" + "-" * 67)
    # 判断进入的接口
    while 1:
    	# 输入操作指令(1~6)
    	operating = int(input("请输入你的操作指令(0~6):"))
    	if operating == 1:
      		# 添加名片
      		print("-" * 26 + "您进入的是添加名片页面!" + "-" * 26)
      		insert_user()
      		print("-" * 26 + "您已经成功添加了名片!" + "-" * 26)
    	elif operating == 2:
      		# 删除名片
      		print("-" * 26 + "您进入的是删除名片页面!" + "-" * 26)
      		delete_user()
    
    	elif operating == 3:
      		print("-" * 26 + "您进入的是修改名片页面!" + "-" * 26)
      		# 修改名片
      		update_user()
    	elif operating == 4:
     		# 查询名片
      		print("-" * 26 + "您进入的是查询名片页面!" + "-" * 26)
      		select_user()
      		print("-" * 26 + "您已经退出了查询名片页面!" + "-" * 26)
    	elif operating == 5:
      		# 显示所有名片
      		print("-" * 26 + "您进入的是显示名片页面!" + "-" * 26)
      		show_all_user()
      		print("-" * 26 + "您已经退出了显示名片页面!" + "-" * 26)
    	elif operating == 6:
      		# 退出系统
      		print("-" * 26 + "您进入的是退出系统页面!" + "-" * 26)
      		exit_system()
    	else:
      		# 错误指令
      		print("你特喵输入了个啥!")
    

1.7 文件操作

1.7.1 路径
  • 绝对路径

    D:/03.自学资料/阿里云大学/text.py

  • 相对路径

    …/test.py

1.7.2 文件的操作
  • 文件的打开与关闭

    1. 文件的打开

      open(文件路径,访问模式)

      file = open("text.txt".mode="r")
      

      访问模式

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EqVZdErA-1664335392584)(.\Img\0248.png)]

    2. 文件的关闭

      file.close()
      
  • 文件的编码方式

    open("test.txt",mode="r",encoding="utf8")
    # encoding用来指定解码方式,默认用操作系统的编码方式
    
  • 文件的读写操作

    1. 文件的读取

      # 打开文件
      file = open("test.txt",mode="r",encoding="utf8")
      file.read()				# 读取文件的内容
      file.read(1024 * 1024)	# 读取文件内容前1M的数据
      file.readable()			# 判断文件是否可读
      file.readline()			# 读取文件的第一行
      file.readlines()		# 读取文件的所有内容
      
    2. 文件的写入

      # 打开文件
      file = open("test.txt",mode="w",encoding="utf8")
      file.write("你是谁".encode("utf8"))		  # 以utf8的编码形式写入文件
      file.writable()								# 判读文件是否可写入
      file.writelines(["你","是","谁","?"])		  # 将列表中的数据以一行的形式写入文件
      
  • 文件的复制

    import os
    
    file_name = input('请输入您要备份的文件路径:') 
    if os.path.exists(file_name):					# 判断文件路径是否存在
     	names = file_name.rpartition('.')			# 将文件名分为三部分
     	new_name = names[0] + '.bak.' + names[2]	# 拼接形成新文件名
     	new_file = open(new_name, 'wb')				# 以二进制写入方式创建并打开新文件
    
     file = open(file_name, 'rb')				# 以二进制的读取方式打卡备份文件
    
     while True:									# 循环读取文件的内容并写入新文件
       	content = file.read(1024 * 1024)		# 每次读取文件1M的内容
       	if not content:
           	break
         	new_file.write(content)					# 将读取的内容写入新文件
    else:
     	print('您输入的文件不存在')
         
    file.close()								# 关闭备份文件
     new_file.close()							# 关闭新文件
    
  • csv文件的读写操作

    1. csv文件的读取

      import csv
      
      file = open('test.csv', mode='r', encoding='utf8')
      
      # csv.reader方法得到的结果是一个 reader 对象,它是一个可迭代对象
      read = csv.reader(file)		
      for i in read:
          print(i)				# 以列表的形式输出
      file.close()
      
    2. csv文件的写入

      import csv
      
      file = open('test.csv', mode='w', encoding='utf8', newline='')
      
      writer = csv.writer(file)
      writer.writerows([					# 以表格嵌套表格的形式写入文件
          ['name', 'gender', 'age'],
          ['jack', 'male', 18],
          ['merry', 'female', 20]
      ])
      file.close()
      
1.7.3 往内存中写入数据
  • StringIO对象

    from io import StringIO, BytesIO
    
    s = StringIO()								# 创建一个StringIO对象
    print('hello world', file=s)			  	# 将 hello world 写入内存s
    print('你好呀', file=s)					  # 将 你好呀 写入内存s
    print(file=s)								# 将 \n 写入内存s			
    print('今天心情真好', file=s)					# 将 今天心情真好 写入内存s
    
    print(s.getvalue())							# 输出内存s存储的数据
    
  • BytesIO对象

    from io import StringIO, BytesIO
    
    file = open('timg.jpg', 'rb')				# 以二进制读取的方式打开文件
    content = file.read()						# 读取文件内容
    b = BytesIO()								# 创建一个BytesIO对象
    b.write(content)							# 将读取到的内容写入内存b
    
    print(b.getvalue())							# 输出内存b存储的数据
    
1.7.4 文件的序列化
  • 序列化

    定义:将python中的对象(字典、列表等)转为字符串或二进制,进行保存或者传递的过程。

  • 序列化为字符串的方式

    1. 使用repr()

      person = {'name': 'zhangsan', 'age': 18, 'height': 175.5}
      
      n = repe(person)			# 将字典person转为字符串
      
    2. 使用str()

      person = {'name': 'zhangsan', 'age': 18, 'height': 175.5}
      
      n = str(person)				# 将字典person转为字符串
      
    3. 使用json模块

      import json
      
      person = {'name': 'zhangsan', 'age': 18, 'height': 175.5}
      file = open('test.txt', 'w', encoding='utf8')	# 打开文件
      
      n = json.dumps(person)							# 将对象转为字符串
      file.write(n)									# 将字符串写入文件
      
      json.dump(person,file)							# 将对象转为字符串并写入文件
      
      file.close()									# 关闭文件
      
  • 序列化为二进制的方式

    1. 使用pickle模块

      import pickle
      
      person = {'name': 'zhangsan', 'age': 18, 'height': 175.5}
      
      file = open('test.txt', 'wb')					# 打开文件
      
      n = pickle.dumps(person)						# 将对象转为二进制
      file.write(n)									# 将二进制写入文件
      
      pickle.dump(person,file)						# 将对象转为二进制并写入文件
      
      file.close()									# 关闭文件
      
1.7.5 文件的反序列化
  • 反序列化

    定义:将字符串或者二进制转换成为Python对象,进行操作的过程。

  • 将字符串反序列化为python对象

    1. 使用eval()

      n = "{'name': 'zhangsan', 'age': 18, 'height': 175.5}"
      
      di = eval(n)			# 将字符串转为python对象
      
    2. 使用json模块

      import json
      
      file = open('test.txt', 'r', encoding='utf8')	# 打开文件
      
      n = file.read()									# 读取文件的内容
      di_1 = json.loads(n)							# 将字符串转为python对象
      
      di_2 = json.load(file)							# 读取文件内容并转为python对象
      file.close()									# 关闭文件
      
  • 将二进制反序列化为python对象

    1. 使用pickle模块

      import pickle
      
      file = open('test.txt', 'r', encoding='utf8')	# 打开文件
      
      n = file.read()									# 读取文件的内容
      di_1 = pickle.loads(n)							# 将字符串转为python对象
      
      di_2 = pickle.load(file)						# 读取文件内容并转为python对象
      file.close()									# 关闭文件
      
  • json模块和pickle模块的区别

    1. json模块

      json本质是字符串,主要使用就是在不同的平台之间传递数据

      不是所有的 python 对象都能转换成为 json字符串

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NL8q1WA3-1664335392585)(.\Img\0254.png)]

    2. pickle模块

      pickle序列化是将对象按照一定的规则转换成为二进制保存,它不能跨平台传递数据。

      pickle的序列化会将对象的所有数据都保存。

1.7.6 异常的介绍
  • try…except

    1. 语法

      try:
      	可能出现错误的语句
      except 错误类型:
      	处理语句
      
    2. 例如

      try:
          file = open('test.txt', 'r')
          print('hello')
          print(1 / 0)
          file.close()
      except (FileNotFoundError, ZeroDivisionError) as e:
          print(f'出错了,错误是{e}')
      

1.8 常见模块

1.8.1 random模块
  • random模块

    import random
    
    random.random()						# 生成[0,1)的浮点数
    random.choice(['hello', 'good'])	# 从迭代对象中随机选取一个
    random.sample(['hello', 'good'], 2)	# 从迭代对象中随机选取2个
    random.randint(1, 20)				# 生成[1,20]的随机整数
    random.randrange(1, 20)				# 生成[1,20)的随机整数
    li = [1,2,3,4,5,6]
    print(random.shuffle(li))			# 对列表中的数据无序输出
    
1.8.2 math模块
  • math模块

    import math
    
    math.fabs(-10)						# 负数的绝对值,返回的是浮点数
    math.sin(math.pi / 6)				# 求sinx的值
    math.ceil(10.2)						# 向上取整
    math.ceil(-9.8)
    math.floor(2.9)						# 向下取整
    math.factorial(5)					# 求阶乘
    math.pow(2, 10)						# 幂运算
    2 ** 10
    pow(2,10)
    
1.8.3 os模块
  • os模块

    import math
    
    os.listdir()						# 查看当前文件所在文件夹下的所有文件
    os.chdir(path)						# 查看路径下的的所有文件
    os.chdir('../')						# 查看当前文件的上一级文件夹下的所有文件
    os.name								# 操作系统的名字:win返回nt,类unix返回posix
    os.path.exists("test.txt")			# 判断文件或文件夹是否存在
    os.remove("text.txt")				# 删除一个文件
    os.mkdir(demo)						# 创建一个文件夹
    os.getcwd()							# 获得当前文件的工作路径
    os.rename('test.txt', 'ok.txt')		# 对文件重命名
    os.environ							# 获得系统的配置环境 
    os.path.isdir('demo')				# 判断是是否是文件夹
    os.path.isfile('ok.txt')			# 判断是否是文件
    os.path.abspath('ok.txt')			# 获得文件的绝对路径
    os.path.splitext('2020.09.txt')		# 将文件名分割成文名件前缀和后缀
    dir(os)								# 返回os的所有变量
    os.cpu_count()						# 返回cpu的个数
    os.path.sep							# 返回路径分隔符
    
1.8.4 time模块
  • time模块

    import time
    
    time.time()							# 获得当前时间戳
    time.sleep(10)						# 让线程暂停10秒
    
1.8.5 datetime模块
  • datetime模块

    import datetime
    
    d = datetime.date(2020, 9, 2)
    print(d)								# 返回指定时间:2020-09-02
    print(d.ctime)							# 返回:Wed Sep  2 00:00:00 2020
    print(d.day)							# 返回日期的天:2
    print(d.month)							# 返回日期的月:9
    print(d.year)							# 返回日期的年:2020
    x = d.replace(2029, 5, 4)				# 替换时间为:2029-05-04
    datetime.date.today()					# 返回当前日期
    dt = datetime.datetime(2025, 1, 1, 18, 53, 45)	
    print(dt)								# 返回指定日期时间:2025-01-01 18:53:45
    dtsn = datetime.datetime.now()			
    print(dtsn)							# 返回当前时间:2020-09-02 21:43:18.866635
    print(dtdn.date())					# 返回日期
    print(dtsn.time)					# 返回时间
    print(dtsn.hour)					# 返回时间的小时:21
    print(dtsn.minute)					# 返回时间的分钟:43
    print(dtsn.second)					# 返回时间的秒数:18
    print(dtsn.microsecond)				# 返回时间的微秒:866635
    print(dtsn + datetime.timedelta(days=0, hours=0, minutes=0, seconds=1))
    									# 返回时间:2020-09-02 21:43:19.866635
    
1.8.6 calendar模块
  • calendar模块

    import calendar
    
    c = calendar.calendar(2020)		
    print(c)							# 返回的2020年的日历
    c = calendar.TextCalendar()
    c.firstweekday = calendar.SUNDAY	# 指定周天为一周的开始
    print(c.formatyear(2020))			# 在每月后加入年份
    print(c.formatmonth(2020, 9))		# 返回2020年9月的日历
    
    c1 = calendar.HTMLCalendar()
    
    calendar.isleap(2000)				# 判断年份是否是闰年
    calendar.leapdays(1900, 1920)		# 返回[1900,1920)年之间有几个闰年
    calendar.monthrange(2020, 9)		# 返回:(1,30),2020年9月第一天是周二,共30天
    calendar.monthlen(2021, 2)			# 返回2021年2月的天数
    
1.8.7 UUID
  • uuid

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gu8qVqvP-1664335392586)(.\Img\0255.png)]

1.9 面向对象基础

1.9.1 类和对象
  • 类是对很多具有共同特性和行为(函数)的事物的统称,它是一个抽象的概念

  • 对象

    对象就是一个个具体的事物

  • 例如

    class Person:  						# 定义一个Person类
     	def __init__(self, name, age):  # 在这个函数里定义属性
         		self.name = name
         		self.age = age
    
     	def eat(self):  				# 定义一个类的方法
         		print('人正在吃东西')
    
    
    p = Person('zhangsan', 18)  		# 创建一个对象p
    p.eat()  							# 使用对象调用类中的方法
    
1.9.2 魔法方法
  • _ _new_ _方法

    class Person(object):
     	def __new__(cls, *args, **kwargs):  	# 申请内存空间
        		return object.__new__(cls)  		# 重写了__init__方法
    
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
    # 1. 调用 __new__ 方法申请内存空间
    # 2. 调用 __init__ 方法初始化
    p = Person('张三', 18)
    print(p)
    
  • _ _init_ _方法

    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
    # 1. 申请一段内存空间  __new__
    # 2. 调用 __init__ 方法进行初始化;同时 __init__ 方法里的 self 指向创建好的内存空间
    # 3. 把对象 p 也指向创建好的内存空间
    p = Person('zhangsan', 18)
    print(p.name, p.age)
    
  • _ _del_ _方法

    # 重写__del__方法
    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
     	def __del__(self):  				# 当删除对象时被调用
         		print("__del__被调用了!")
    
    p = Person("yang", 18)
    del p  									# 调用 __del__ 方法
    
  • _ _call_ _方法

    # 重写__call__方法
    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
     	def __call__(self, *args, **kwargs):  			# 对象模拟函数的使用
         		print(self.name, self.age, args[0], kwargs["b"])
    
    p = Person("yang", 18)
    p(1, 2, a=3)  										# 对象可像函数一样使用,等效于
    Person.__call__(p, 1, 2, a=3, b=4)  				# Person.__call__()	 
    
  • _ _str_ _方法

    # 不重写__str__方法
    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
    p = Person('zhangsan', 18)  # 创建一个对象
    print(p)  					# 当输出对象时,会调用__str__方法,默认输出类名和对象地址
    
    
    # 重写__str__方法
    class Person:
    	def __init__(self, name, age):
       		self.name = name
         		self.age = age
       
    	def __str__(self):  	# 重写 __str__ 方法
       		return 'yes'
       
    p = Person('zhangsan', 18)  # 创建一个对象
    print(p)  					# 调用 __str__ 方法,输出 yes
    
  • _ _repr_ _方法

    # 不重写__repr__方法
    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
    p = Person("yang", 18)  		# 创建一个对象
    print(repr(p))  				# 调用__repr__方法,默认输出类名和对象地址
    
    
    # 重写__repr__方法
    class Person:
    	def __init__(self, name, age):
       		self.name = name
         		self.age = age
       
    	def __repr__(self): 		# 当对象被转为解释器可读的形式时,将会调用
       		return "yes"
       
    p = Person("yang", 18)  		# 创建一个对象
    print(repr(p))  				# 调用__repr__方法,输出 yes
    
    
  • _ _str_ _方法与_ _repr_ _方法的区别

    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
     	def __str__(self):
         		return f"{self.name}"
    
    
    p1 = Person("yang", 18)
    p2 = Person("ssun", 18)
    print([p1, p2])
    
    
    # 输出       [<__main__.Person object at 0x000002CA66FD4700>,
    #			 <__main__.Person object at 0x000002CA670B8040>]
    
    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
     	def __repr__(self):
         		return f"{self.name}"
    
    
    p1 = Person("yang", 18)
    p2 = Person("ssun", 18)
    print([p1, p2])
    # 输出	[yang, ssun]
    
  • _ _int_ _、_ _getitem_ _、_ _setitem_ _方法

    class Person:
        	def __init__(self, name, age):
            	self.name = name
            	self.age = age
    
        	def __int__(self):  				# 对象强转为int类型时调用
            	return self.age
    
        	def __getitem__(self, item):  		# 使对象可像字典一样获取数据
            	return self.__dict__[item]
    
        	def __setitem__(self, key, value):  # 使对象可像字典一样修改数据
            	self.__dict__[key] = value
    
    
    p = Person("yang", 18)
    print(int(p))  							# 调用__int__方法
    print(p["name"])  						# 调用__getitem__方法
    p["height"] = 170  						# 调用__setitem__方法
    print(p["height"])
    
  • _ _add_ _、_ _sub_ _、_ _mul_ _、_ _truediv_ _、_ _gt_ _、_ _lt_ _、_ _ge_ _、_ _le_ _方法

    class Person:
        	def __init__(self, name, age):
            	self.name = name
            	self.age = age
    
        	def __add__(self, other):  			# 当对象做加法运算时调用
            	return self.age + other
    
        	def __sub__(self, other):  			# 当对象做减法运算时调用
            	return self.age - other
    
        	def __mul__(self, other):  			# 当对象做乘法运算时调用
            	return self.age * 2
    
        	def __truediv__(self, other):  		# 当对象做除法运算时调用
            	return self.age / 2
    
        	def __gt__(self, other):  			# 当对象做大于运算时调用
            	return self.age > other
    
        	def __lt__(self, other):  			# 当对象做小于运算时调用
            	return self.age < other
    
        	def __ge__(self, other):  			# 当对象做大于等于运算时调用
            	return self.age >= other
    
        	def __le__(self, other):  			# 当对象做小于等于运算时调用
            	return self.age <= other
    
    
    p = Person("yang", 18)
    print(p + 2)  							# 调用__add__方法
    print(p - 2)  							# 调用__sub__方法
    print(p * 2) 							# 调用__mul__方法
    print(p / 2)  							# 调用__truediv__方法
    print(p > 18)  							# 调用__gt__方法
    print(p < 18)  							# 调用__lt__方法
    print(p >= 18)  						# 调用__ge__方法
    print(p <= 18)  						# 调用__le__方法
    
1.9.3 身份运算符
  • 身份运算符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-14vEvNyo-1664335392587)(.\Img\0256.png)]

  • _ _eq_ _方法

    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
     	def __eq__(self, other):  			# 当对象使用 == 时调用
         		return self.name == other.name
    
    
    p1 = Person("yang", 18)
    p2 = Person("yang", 19)
    print(p1 == p2)  						# 调用__eq__方法
    

1.10 面向对象高级

1.10.1 私有属性和方法
  • 私有属性和方法的定义

    class Person:
        	def __init__(self, name, age, salary):
            	self.name = name
            	self.age = age
           	self.__salary = salary  			# 定义私有属性
    
        	def __test(self):
           	return self.__salary  				# 定义私有方法
    
  • 访问私有属性和方法

    1. 直接访问(不建议使用)

      class Person:
          def __init__(self, name, age, salary):
              self.name = name
              self.age = age
              self.__salary = salary			# 定义私有属性
      
          def __test(self):
              return self.__salary			# 定义私有方法
          
      p = Person("yang", 18, 10000)
      print(p._Person__salary)				# 在外部对象访问类中的私有属性
      print(p._Person__test())				# 在外部对象访问类中的私有方法
      
    2. 间接访问

      class Person:
          def __init__(self, name, age, salary):
              self.name = name
              self.age = age
              self.__salary = salary
      
          def set_salary(self, salary):
              self.__salary = salary
      
          def get_salary(self):
              return self.__salary
      
      
      p = Person("yang", 18, 10000)
      p.set_salary(20000)					# 调用set_salary方法,修改私有属性
      print(p.get_salary())				# 调用get_salary方法,获取私有属性
      
1.10.2 实例属性和类属性
  • 实例属性和类属性

    class Person:
    	type = "人类"							# 类属性,实例对象和类对象可访问
    	def __init__(self, name, age):
    		self.name = name				 # 实例属性
    		self.age = age
    
  • 类属性的访问和修改

    class Person:
     	type = "人类"
    
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
    
    p = Person("yang", 18)  				# 创建实例对象
    print(p.type)  							# 实例对象访问类属性
    print(Person.type)  					# 类对象访问类属性
    Person.type = "非人类"  				  # 类属性只能通过类对象来修改
    
1.10.3 实例方法、静态方法、类方法
  • 实例方法

    class Person:
        	type = "人类"
    
        	def __init__(self, name, age):
            	self.name = name
            	self.age = age
    
        	def get_name(self):  				# 实例方法,即可访问实例属性,也可访问类属性
            	return self.name, Person.type
    
    
    p = Person("yang", 18)
    print(p.get_name())  					# 实例对象调用实例方法
    print(Person.get_name(p))  				# 类对象调用实例方法
    
  • 静态方法

    class Person:
        	type = "人类"
    
        	def __init__(self, name, age):
            	self.name = name
            	self.age = age
            	self.__class__.type = "非人类"
    
        	@staticmethod  						# 定义为静态方法,不访问任何资源
        	def test():
            	return "我是个植物人"
    
    
    p = Person("yang", 18)
    print(p.test())  						# 实例对象调用静态方法
    print(Person.test())  					# 类对象调用静态方法
    
  • 类方法

    class Person:
        	type = "人类"
    
        	def __init__(self, name, age):
            	self.name = name
            	self.age = age
    
        	@classmethod  						# 定义类方法,只访问了类属性
        	def get_type(cls):
            	return cls.type
    
    
    p = Person("yang", 18)
    print(p.get_type())  					# 实例对象调用类方法
    print(Person.get_type())  				# 类属性调用类方法
    
1.10.4 单例设计模式
  • 单例设计模式

    class Person(object):
        	__address = None  					# 定义类属性
       	__flag = True
    
        	def __new__(cls, *args, **kwargs):  # 重写__new__方法,只申请一次内存
            	if cls.__address is None:
                	cls.__address = object.__new__(cls)
           	 return cls.__address
    
        	def __init__(self, name, age):  	# 初始化,只会初始化一次
            	if self.__flag:
                	self.name = name
                	self.age = age
                	self.__flag = False
    
    
    p1 = Person("yang", 18)  				# 创建实例对象
    p2 = Person("ssun", 18)
    print(p1 is p2)  						# 输出 True
    print(p1.name)  						# 输出 yang
    
1.10.5 继承
  • 继承的基本语法

    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
    
     	def get_name(self):
        		 return self.name
    
    
    class Student(Person): 					# 定义子类,继承父类
     	pass
    
    
    p = Student("yang", 18)  				# 创建实例对象,可使用父类的属性
    print(p.name)  							# 实例对象访问父类的属性
    
    ——————————————————————————————————————————————————————————————————————————————
    
    class Person:
     	def __init__(self, name, age):
        		 self.name = name
         		self.age = age
    
    
    class Student(Person):
     	def __init__(self, name, age, school, user_id):  	# 重写父类中的方法
         		super(Student, self).__init__(name, age)  		# 使用父类中的属性
         		self.school = school  							# 定义自己的属性
         		self.user_id = user_id
    
    
    p = Student("yang", 18, "qust", 1)
    print(p.name, p.user_id)  								# 输出 yang 1
    
  • 父类的私有成员子类不能继承

    class Person:
     	def __init__(self, name, age):
         		self.name = name
         		self.age = age
         		self.__salary = 10000					# 定义私有属性
    
     	def __test(self):							# 定义私有方法
         		return self.__salary
    
    
    class Student(Person):						# 定义子类
     	pass
    
    s = Student("yang",18)						# 创建子类的实例对象
    print(s.name)								# 子类的实例对象访问父类属性
    print(s.__salary)							# 报错,子类不能继承父类的私有属性
    s.__test()									# 报错,子类不能继承父类的私有方法
    
  • 多重继承

    class A:						# 定义一个父类A				
        	def test(self):				# 定义A中的实例方法test
            	print("test_A")
    
    
    class B:						# 定义一个父类B
        	def test(self):				# 定义B中的实例方法test
           	 print("test_B")
    
        	def demo(self):				# 定义B中的实例方法demo
           	 print("demo_B")
    
    
    class C(A, B):					# 定义子类C,继承A、B类
        	pass
    
    
    c = C()							# 创建实例对象c
    c.demo()						# 输出 demo_B
    c.test()						# 输出 test_A
    
    print(C.__mro__)				# 表示子类C调用父类成员时寻找父类的先后顺序
    								# __mro__只能由类对象来调用
    
1.10.6 多态
  • 使用场景

    class Dog:								# 定义父类Dog
        	def __init__(self, name, color):
            	self.name = name
           	self.color = color
    
        	def dog_work(self):
           	 print(f"{self.color}{self.name}正在工作!")
    
    
    class PoliceDog(Dog):					# 定义子类PoliceDog,继承Dog
       	 def dog_work(self):
            	print(f"{self.color}{self.name}是警犬,正在攻击敌人!")
    
    
    class SearchaDag(Dog):					# 定义子类SearchaDag,继承Dog
        	def dog_work(self):
            	print(f"{self.color}{self.name}是搜救犬,正在搜救同伴们!")
    
    
    class GuideDog(Dog):					# 定义子类GuideDog,继承Dog
        	def dog_work(self):
            	print(f"{self.color}{self.name}是导盲犬,正在为盲人引路!")
    
    
    def work(dog):					# 定义一个函数来调用各子类
        	if isinstance(dog,Dog):		# 判断传入的参数对象是否指定类(或其子类)实例化出的对象
            	dog.dog_work()				
        	else:
            	# 自定义异常
            	raise TypeError("参数必须是Dog或者它子类创建出来的实例对象")
    
    
    pd = PoliceDog("大黄", "黑色")	 # 创建实例对象 
    sd = SearchaDag("小黑", "白色")
    gd = GuideDog("小白", "黄色")
    work(pd)						# 输出 黑色的大黄是警犬,正在攻击敌人!
    work(sd)						# 输出 白色的小黑是搜救犬,正在搜救同伴们!
    work(gd)						# 输出 黄色的小白是导盲犬,正在为盲人引路!
    work(12)						# 报错,输出 参数必须是Dog或者它子类创建出来的实例对象
    
1.10.7 property的使用
  • property的类属性

    class Person:
        	def __init__(self, name, age, salary):
            	self.name = name
            	self.age = age
            	self.__salary = salary
    
        	def get_salary(self):
            	return self.__salary
    
        	def set_salary(self, salary):
            	self.__salary = salary
    	
        	# 定义类属性,用于私有属性__salary的快速访问和修改
        	my_salary = property(fget=get_salary, fset=set_salary, doc="")
    
    
    p = Person("yang", 18, 10000)	# 创建实例对象
    print(p.my_salary)				# <==> p.get_salary()
    p.my_salary = 20000				# <==> p.set_salary(20000)
    
  • property的装饰器

    class Person:
        	def __init__(self, name, age, salary):
            	self.name = name
            	self.age = age
            	self.__salary = salary				# 定义私有属性
    
        	@property
        	def money(self):						# 定义此方法可被快速访问
            	return self.__salary
    
        	@money.setter							# 定义此方法可通过指定的名字进行修改
        	def money(self, salary):
            	self.__salary = salary
    
    
    p = Person("yang", 18, 10000)
    print(p.money)								# 访问money(self)
    p.money = 20000								# 访问money(self,salary)
    
1.10.8 常见的内置属性
  • _ _class_ _、_ _dict_ _、_ _module_ _、_ _dos_ _、

    class Person:
        	"""
        	这是一个Person类
        	"""
        	type = "人类"							# 定义类属性
    
        	def __init__(self, name, age):
            	self.name = name
            	self.age = age
            	__class__.type = "非人类"			# 对类属性进行修改
    
    p = Person("yang", 18)
    print(p.__class__.type)					  # 通过__call__获取类对象
    print(p.__dict__)						  # 将对象转为字典,数据以key-values存储
    print(p.__module__)						  # 获得对象对应的模块名
    print(p.__doc__)						  # 获得类的介绍
    
1.10.9 异常
  • 处理异常

    try:
    	x = 1 / 0
    except Exception as e:				# Exception处理所有异常
    	print(e)
    
    try:
    	y = "1" + 1
    	x = 1 / 0
    except (TypeError, ZeroDivisionError) as e:	# 使用元组处理多种异常
    	print(e)
    
    try:
     	y = "1" + 1
     	x = 1 / 0
    except TypeError as e:  					# 使用多个except处理异常
     	print(e)
    except ZeroDivisionError as e:
     	print(e)
    
    try:
        	x = 1 / 0
    except ZeroDivisionError as e:
       	print(e)
    finally:									# 无论有没有异常,都将会执行finally
       	print("我总会被执行!")
    
  • 常见的错误类型

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dMyDNRJC-1664335392588)(.\Img\0257.png)]

  • 自定义异常

    class PwdlenError(Exception):				# 自定义一个异常类,并继承Exception
        	def __init__(self, x, y):
            	self.x = x
            	self.y = y
    
        	def __str__(self):						# 触发异常,将输出的内容
            	return f"密码长度需要在{self.x}~{self.y}之间"
    
    
    def check_password(password):				# 定义一个方法用于核验密码规范
        	if len(password) >= 6 and len(password) <= 12:
            	print("密码合乎规范!")
        	else:
            	print("密码不合乎规范!")
            	e = PwdlenError(6, 12)			# 创建异常类的实例对象
            	raise e							# 将会调用类中的 __str__ 方法
    
    
    password = input("请输入(6~12)位的密码:")
    try:
        	check_password(password)			# 调用check_password()核验密码
    except PwdlenError as e:				
        	print(e)							# 打印错误提示
    
  • with关键字的使用

    class MyManager:								# 自定义个类来管理上下文
     	def __init__(self, file, mode, encoding):
         		self.file = file
         		self.mode = mode
         		self.encoding = encoding
    
     	def __enter__(self):						#重写__enter__方法
         		print("__enter__")
         		return self
    
     	def __exit__(self, exc_type, exc_val, exc_tb):	# 重写__exit__方法
         		print("__exit__")
         		self.close()
    
     	def close(self):
         		print("文件关闭了!")
    
    
    def create_mymanager(file, mode, encoding):			# 实例化对象
     	my_manager = MyManager(file, mode, encoding)
     	return my_manager
    
    # 首先执行with语句,然后调用__enter__方法,当出现异常或with代码块执行完,调用__exit__方法
    with create_mymanager("text.txt", "r", encoding="utf8") as m: # with上下文管理器
     	print(m)   															
    
    with open("text.txt", "r", encoding="utf8") as file:
     	x = file.read()
     	print(x)
     
    # <==> file = open("text.txt","r",encoding="utf8") 
    #	   file.__enter__
    #	   当出现异常或with代码块执行完会调用 __exit__方法
    

    注意:with不具有处理异常的能力

1.10.10 模块和包
  • 导入模块(5种)

    1. import 模块名

      import random						# 导入pytho中的库模块
      
    2. from 模块名 import 功能名

      from random import randint			# 导入random模块下的方法randint
      
    3. **from 模块名 import ***

      from random import *				# 导入random模块下的所有方法和类
      
    4. import 模块名 as 别名

      import random as rd					# 导入random模块并为其起一个别名为rd
      
    5. from 模块名 import 功能名

      from random import randint as ri	# 导入random模块下的方法randint
      									# 并为其起一个别名为ri
      
  • 搜索模块的路径

    print(sys.path)							# 模块的搜索路径存储在变量sys.path
    

    注:通常将模块和包放于项目路径下

  • _ _name_ _测试模块

    print(__name__)							# 在模块中将输出__main__
    
    import 模块							   # 在非模块中运行将输出模块名
    
  • _ _all_ _在模块中的使用

    # 在模块中使用__all__
    # 模块文件 model.py
    __all__ = ["test","a"]
    def test():
        	print("test")
    a = 10 
    b = 20
    def demo():
        	print("demo")
    ______________________________________________________________________________
    
    # 导入模块文件 model.py
    from model import *						# 导入模块model
    
    print(test())							# 可调用模块中的test()
    print(a)								# 可调用模块中的a
    print(b)								# 不可调用模块中的b
    print(demo)								# 不可调用模块中的demo()
    
  • 导入包中的模块

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MaHpiQVT-1664335392589)(.\Img\0258.png)]

    1. import 包名.模块名

        # 导入包中的模块
        import User.userinfo
      
    2. from 包名 import 模块名

        # 导入包中指定的模块
        from User import userinfo
      
    3. **from 包名 import ***

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mvkVUdX5-1664335392590)(.\Img\0259.png)]

      # 导入包下所有模块
      # 当导入包下所有模块,首先会访问__init__.py中的__all__
      
      # __init__.py
      __all__ = ["userinfo"]
      
      ___________________________________________________________________________
      
      # 导入User包下模块
      from User import *
      
      print(userinfo.a)				# 会调用userinfo模块下的a
      print(useraddress.a)			# 报错,因为__init__.py中的__all__位将其包含
      

1.11 正则表达式

1.11.1 正则查找
  • search()

    # search()只匹配一次,查找的是整个字符串
    # 匹配到的结果是一个 re.Match 类型的对象
    import re
    
    n = re.search(r"x", "sedfxfg")
    print(n)
    
  • match()

    # match()只匹配一次,是从头匹配,若开头不匹配则返回None
    # 匹配到的结果是一个 re.Match 类型的对象
    import re
    
    n = re.match(r"x", "xdfhxsdsxsdfsdf")
    print(n)
    
  • fullmatch()

    # 对整个字符串的完整匹配
    import re
    
    
    n = re.fullmatch(r"s\d+r", "s1234r")	# 等效于 re.match(r"^s\d+r$", "s1234r")
    print(n)
    
  • findall()

    # 匹配字符串中满足正则表达式的所有子串,并返回一个列表,若无匹配结果,返回空列表
    import re
    
    n = re.findall(r"\d+", "s12ddds45qw123q")
    print(n)
    
  • finditer()

    # 匹配字符串中满足正则表达式的所有子串,并返回一个迭代器,其每个元素都为re.Match 类型的对象
    import re
    
    n = re.finditer(r"\d+", "sd12sdaaw45awe123wq")
    print(list(n))
    
1.11.2 re.Match类型
  • re.Match类型

    当调用re.search()、re.match()、re.finditer()得到结果,

    并对其进行迭代获取的数据的数据类型是re.Match类型

  • 属性和方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1vfviQLM-1664335392591)(.\Img\0260.png)]

    import re
    
    # string、re、start()、end()
    a = re.search(r"\d+", "a23kdfjl123askjd456")
    print(a.string)				# 匹配的源字符串
    print(a.re)					# 正则表达式规则,<==>re.compile("\\d+")
    print(a.start())			# 匹配到结果的开始下标
    print(a.end())				# 匹配到结果的最后下标
    
    # 使用()进行分组,使用group()获取分组匹配的结果
    b = re.match(r".*c(\d+).*r(\d+)", "abc13def456r789qwqeqwr")
    print(b.group(0))			# 满足正则表达式的子串
    print(b.group(1))			# 返回第1组的数据
    print(b.group(2))			# 返回第2组的数据
    
    # 使用(?P<name>)为分组起别名,可使用别名来使用分组
    c = re.match(r".*c(?P<a>\d+).*r(\d+)", "ablc13def456r789qwqeqwr")
    print(c.start("a"))			
    print(c.end("a"))
    print(c.group("a"))
    
    # groupdict()以字典的形式保存分组数据
    d = re.match(r".*c(?P<a>\d+).*r(?P<b>\d+)", "ablc13def456r789qwqeqwr")
    print(d.groupdict())		# 以字典的形式保存分组的数据,key为分组别名
    print(d.groupdict()["b"])	# 获取字典中key为b的数据
    
    # span()
    e = re.search(r".*c(?P<a>\d+).*r(?P<b>\d+)", "ablc13def456r789qwqeqwr")
    print(e.span("b"))			# 以元组的形式返回别名为b分组的开始下标和结束下标
    
1.11.3 re.complie的使用
  • re.complie

    p = re.complie(r"\d+")
    print(type(p))				# 返回p的类型为 <class 're.Pattern'>
    print(p.search("lkj123lk"))	# 返回<re.Match object; span=(3, 6), match='123'> 
    
1.11.4 正则模式
  • 非打印字符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EKvKTTrG-1664335392592)(.\Img\0261.png)]

  • 特殊字符

    若要匹配这些特殊字符,必须首先使字符"转义

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XjZget1B-1664335392592)(.\Img\0262.png)]

  • 定位符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V8WcZwAL-1664335392593)(.\Img\0263.png)]

  • 限定符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pecZPPJ-1664335392594)(.\Img\0264.png)]

  • 正则表达式

    1. 标点符号

      # .	:表示匹配除了换行符以外的任意字符
      # * :表示前面字符出现的任意次数,等效于{0,}
      # ? :表示前面字符最多出现一次,等价于{,1};可将贪婪模式转换为非贪婪模式
      # + :表示前面字符至少出现一次,等价于{1,}
      # [] :表示单个字符的取值范围,常结合 - 配合使用
      # - :表示范围
      # {m,n} :表示元素出现 m ~ n 次
      # () :用来进行分组
      # (?P<name>) :给分组起别名
      # (?:) :表示一个非捕获分组
      # | :用来表示取值范围,通常配合 () 使用
      # ^ :用来表示以指定的字符开始
      # $ :用来表示以指定的字符结束
      
    2. 字母的转义

      # \r :匹配回车
      # \n :匹配换行
      # \t :匹配制表符
      # \s :匹配非打印字符
      # \S :匹配打印字符
      # \w :匹配数字、字母、下划线,等效于[0-9a-zA-Z_]
      # \W :匹配非数字、字母、下划线,等效于[^0-9a-zA-Z_]
      # \d :匹配数字,等效于[0-9]
      # \D :匹配非数字,等效于[^0-9]
      # \u :表示Unicode编码,匹配汉字[\u4E00-\u9FA5]
      
1.11.5 正则替换
  • 语法

    # 参数
    # pattern:正则表达式
    # repl:替换的字符串或函数
    # string:被替换的原字符串
    # count:模式匹配后的替换的最大次数,默认值为0,表示替换所以匹配项
    re.sub(pattern,repl,string,count=0)
    
  • re.sub()

    # 将数字替换为字母x
    print(re.sub(r'\d+', 'x', 'h43df19la28f'))
    
    # 提取电话号码
    print(re.sub(r'\D', '', "2004-959-559 # 这是一个电话号码"))
    
    
    def test(arg):
    	return str(int(arg.group("num")) * 2)
    
    # 将字符串中的数字替换成其数值的两倍
    b = re.sub(r'(?P<num>\d+)', test, 'h43df19la28f')
    print(b)			# 输出 h86df38la56f
    
1.11.6 贪婪模式和非贪婪模式
  • 贪婪模式

    # 贪婪模式是尽可能多个匹配
    x = re.search(r'h(.+)(\d+)t(.{2,4})(\d+)', 'h6789t123456')
    print(x.group(1))  # 输出 678
    print(x.group(2))  # 输出 9
    print(x.group(3))  # 输出 1234
    print(x.group(4))  # 输出 56
    
  • 非贪婪模式

    # 在 * ? + {n,m}后加上?,可将贪婪模式转为非贪婪模式
    # 非贪婪模式是尽可能少的匹配
    x = re.search(r'h(.?)(\d+)t(.{2,4}?)(\d+)', 'ht6789t123456')
    print(x.group(1))  # 输出 t
    print(x.group(2))  # 输出 6789
    print(x.group(3))  # 输出 12
    print(x.group(4))  # 输出 3456
    
1.11.7 正则修饰符
  • 修饰符

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xpGptmGT-1664335392595)(.\Img\0325.png)]

  • 修饰符的使用

    # re.I
    print(re.search(r'H', 'hello', re.I))
    # 输出 <re.Match object; span=(0, 1), match='h'>
    
    # re.S
    print(re.search(r'.', '\n', re.S))
    # 输出 <re.Match object; span=(0, 1), match='\n'>
    
    # re.M
    print(re.findall(r'\w+$', 'hello world\nyes no\nok\nhi', re.M))
    # 输出 ['world', 'no', 'ok', 'hi']
    

1.12 迭代器和生成器

1.12.1 迭代器
  • 常见的可迭代对象

    字符串、列表、元组、字典、集合、range()、map()、filter

  • 判断一个对象是否是可迭代对象

    from collections.abc import Iterable
    
    print(isinstance([1, 2, 3], Iterable))
    # 输出 True
    
  • 可迭代对象的本质

    可迭代对象通过 _ _iter_ _ 方法向我们提供一个迭代器,我们在迭代一个可迭代对象的时候,实际上就是先获取该对象提供的一个迭代器,然后通过这个迭代器来依次获取对象中的每一个数据。
    那么也就是说,一个具备了 _ _iter_ _ 方法的对象,就是一个可迭代对象。

  • 什么是迭代器

    一个实现了 _ _iter_ _ 方法和_ _next_ _ 方法的对象就是迭代器

  • 判断一个对象是否是迭代器

    n=[1,2,3]
    
    # 调用__iter__方法
    print(n.__iter__())
    # 输出 <list_iterator object at 0x0000026205B886D0>
    
    # 调用内置函数iter()
    print(iter(n))
    # 输出 <list_iterator object at 0x0000026205B886D0>
    
    # 使用isinstance()
    print(isinstance(iter(n),Iterable))
    # 输出 True
    
  • 自定义迭代器

    # 自定义迭代器
    class Demo(object):
    	def __init__(self, n):
    		self.n = n
    		self.count = 0
    
    	def __iter__(self):
    		return self
    
    	def __next__(self):
    		self.count += 1
    		if self.count <= self.n:
    			return self.count - 1
    		raise StopIteration
            
    d =Demo(5)
    for i in d:
       	print(i)
    # 输出 0 1 2 3 4
    
  • 使用迭代器计算斐波那契数列

    class Fibonacci:
    	def __init__(self, n):
    		self.n = n
    		self.num1 = self.num2 = 1
    		self.count = 0
    
    	def __iter__(self):
    		return self
    
    	def __next__(self):
    		self.count += 1
    		x = self.num1
    		if self.count <= self.n:
    			self.num1, self.num2 = self.num2, self.num1 + self.num2
    			return x
    		raise StopIteration
    
    fib = Fibonacci(12)
    
    for f in fib:
    	print(f)
    # 输出 1 1 2 3 5 8 13 21 34 55 89 144
    
  • 迭代器和列表的区别

    列表是将整个给数据保存在内存中,占用空间,操作熟读快

    迭代器不将数据保存在内存中,布占用空间,操作速度相对慢

1.12.2 生成器
  • 什么是生成器

    生成器是一类特殊的迭代器

  • 创建生成器

    # 方法一
    g = (i * 10 for i in range(5))
    
    print(g)
    # 输出 <generator object <genexpr> at 0x000002176054AD60>
    
    for i in g:
       	print(i)
    # 输出 0 10 20 30 40
    
    # 方法二
    def Demo(n):
    	i = 0
    	while i < n:
    		yield i * 10
            i = i * 10
            
    g = Demo(5)
    print(g)
    # 输出 <generator object Demo at 0x0000026CE196AD60>
    
    for i in g:
       	print(i)
    # 输出 0 10 20 30 40
        
    print(next(g))	# 输出 0
    print(next(g))	# 输出 10
    print(next(g))	# 输出 20
    print(next(g))	# 输出 30
    print(next(g))	# 输出 40
    
  • 生成器求斐波那契数列

    def fibonacci(n):
    	num1 = num2 = 1
    	count = 0
    	while count < n:
    		yield num1
    		num1, num2 = num2, num1 + num2
    		count += 1
    
    fib = fibonacci(12)
    
    print(fib)
    # 输出 <generator object fibonacci at 0x0000020BCAB89E40>
    
    for i in fib:
    	print(i)
    # 输出 1 1 2 3 5 8 13 21 34 55 89 144
    

1.13 加密方式

1.13.1 base64编码
  • base64编码

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I85UuADZ-1664335392596)(.\Img\0326.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wbx9UiUP-1664335392597)(.\Img\0327.png)]

  • 实现base64编码

    import base64
    
    s = "魔狼"
    
    # 将字符串转为二进制
    s_b = s.encode()
    
    print(s_b)
    # 输出 b'\xe9\xad\x94\xe7\x8b\xbc'
    
    # 将二进制进行base64编码
    be64_v = base64.b64encode(s_b)
    
    print(be64_v)
    # 输出 b'6a2U54u8'
    
    # 对base64编码后的字符串进行解码
    bde64_v=base64.b64decode(be64_v)
    
    print(bde64_v)
    # 输出 b'\xe9\xad\x94\xe7\x8b\xbc'
    
1.13.2 常见的加密算法
  • 加密方式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JRhgKgEX-1664335392598)(.\Img\0328.png)]

  • MD5加密

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZK9vLwUr-1664335392599)(.\Img\0329.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JDtZI6rP-1664335392599)(.\Img\0331.png)]

  • MD5加密的实现

    import hashlib
    
    s = "魔狼"
    # 将字符串转为二进制
    s_b = s.encode(encoding="utf8")
    
    print(s_b)
    # 输出 b'\xe9\xad\x94\xe7\x8b\xbc'
    
    # 创建MD5对象
    hl = hashlib.md5()
    # 对转为二进制的字符串进行md5加密
    hl.update(s_b)
    # 获取对字符串进行加密后的密文
    s_md5 = hl.hexdigest()
    
    print(s_md5)
    # 输出 2b84329c56da0f383cbabf85c498f215
    
  • SHA加密

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FcBpomNl-1664335392600)(.\Img\0330.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nANuuuyU-1664335392601)(.\Img\0332.png)]

  • SHA加密的实现

    import hashlib
    
    s = "魔狼"
    s_b = s.encode(encoding="utf8")
    
    print(s_b)
    # 输出 b'\xe9\xad\x94\xe7\x8b\xbc'
    
    # 对转为二进制的字符串进行SHA加密,不同的SHA加密方式密文长度不同
    h_s1 = hashlib.sha1(s_b)
    h_s224 = hashlib.sha224(s_b)
    h_s256 = hashlib.sha256(s_b)
    
    print(h_s1.hexdigest())
    # 输出 7631e6d3f5304af63ff02dbf05da1e0f18e8685f
    print(h_s224.hexdigest())
    # 输出 66072ff0456a11273ca3c6b393a9390f838ce06e07139445886a6752
    print(h_s256.hexdigest())
    # 输出 ea975dcc88a3efd81cdb1de1838b92d0391a80fb32aefc2d9ac2f7e8d6d94907
    

1.14 网络通信

1.14.1 ip地址
  • ip地址分类

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ybmjCkVV-1664335392603)(.\Img\0333.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LWY7GO71-1664335392604)(.\Img\0334.png)]

1.14.2 upd发送、接收消息
  • upd发送消息

    import socket
    
    # 创建一个基于udp的socket链接
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 调用sendto()方法给指定的主机和端口发送信息
    # 发送的数据需要转为二进制
    s.sendto("你好".encode("utf8"), ("10.11.16.228", 8090))
    # 接受的数据也是二进制
    data = s.recv(1024).decode("utf8")
    print(data)
    s.close()
    
  • upd接收消息

    # 被动的接受消息需要绑定端口
    s.bind(("10.11.16.134", 9090))
    while 1:
        	# recvfrom接收的是个元组
        	# 第0个元素是对方发送的内容
        	# 第2个元素是对方的地址和端口所组成的元组
        	data,address=s.recvfrom(1024)
        	print(data)
        	print(address)
    
1.14.3 基于udp的聊天
  • 实现

    import socket, threading
    
    # 发送消息
    def send_msg():
        	send_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        	ip = input('请输入您要发送的目标IP地址:')
        	port = int(input('请输入对方的端口号:'))
        	while True:
            	content = input('请输入您要发送的内容:')
            	if content == 'stop':
                	break
               send_socket.sendto(content.encode('utf8'), (ip, port))
        	send_socket.close()
    
    # 接收消息
    def recv_msg():
        	recv_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        	recv_socket.bind(('10.11.62.66', 8000))
        	file = open('msg.txt', 'w', encoding='utf8')
        	while True:
            	data, address = recv_socket.recvfrom(1024)
            	print(f'接收到来自{address[0]}:{address[1]}的消息,\
                  	  内容是:{data.decode("utf8")}', file=file)
            	# 将缓冲区的数据写入文件中,并清空缓冲区
            	file.flush()
    
    t1 = threading.Thread(target=send_msg)
    t2 = threading.Thread(target=recv_msg)
    t1.start()
    t2.start()
    
1.14.4 多任务
  • 实现

    import time, threading
    
    def dance():
    	for i in range(100):
    		print('我正在跳舞')
    		time.sleep(0.2)
    
    def sing():
    	for i in range(100):
    		print('我正在唱歌')
    		time.sleep(0.2)
    
    t1 = threading.Thread(target=dance)
    t2 = threading.Thread(target=sing)
    
    t1.start()
    t2.start()
    
1.14.5 tcp发送、接收消息
  • tcp发送消息

    import socket
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # tcp 发送消息之前,必须要先建立连接
    s.connect(('10.11.62.66',6060))
    # 将数据(二进制)发送出去
    s.send('下午好'.encode('utf8'))
    s.close()
    
  • tcp接收消息

    import socket
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 绑定 IP地址和端口号
    s.bind(('10.11.62.66', 6060))
    
    # 把socket变成一个被动的socket
    s.listen(128)
    
    # 接收客户端的请求,得到的结果是一个元组
    # 元组里第0个元素是客户端的socket连接
    # 元组里第1个元素是客户端的IP地址和端口号
    client_socket, client_addr = s.accept()
    
    # 从客户端的socket里获取到客户端发送过来的数据
    content = client_socket.recv(1024).decode('utf8')
    print(f'接收到了来自{client_addr[0]}:{client_addr[1]}的请求,内容是:{content}')
    s.close()
    
1.14.6 文件下载
  • 服务器

    import socket, os
    
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 127.0.0.1 表示的是本机,如果绑定的是这个IP地址,只能本机访问,别的主机不能访问
    # 0.0.0.0 表示所有可用的地址
    server_socket.bind(('0.0.0.0', 9090))
    
    # 把socket变成一个被动的socket
    server_socket.listen(128)
    
    while True:
        	# 获取客户端发送过来的数据
        	client_socket, client_addr = server_socket.accept()
        	file_name = client_socket.recv(1024).decode('utf8')
    
        	# 根据客户端的请求来读取文件,并将读取到的数据发送到客户端
        	if os.path.exists(file_name):
            	file = open(file_name, 'rb')
            	content = file.read()
            	client_socket.send(content)
            	client_socket.close()
    
  • 客户端

    import socket
    
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 与服务器建立链接
    client_socket.connect(('127.0.0.1', 9090))
    file_name = input('请输入您要下载的文件名:')
    
    # 向服务器发送请求数据
    client_socket.send(file_name.encode('utf8'))
    
    # 创建文件用以保存服务器返回的数据
    file = open(file_name, 'wb')
    while True:
        	data = client_socket.recv(1024 * 1024 * 10)
        	if not data:
            	break
        	file.write(data)
    client_socket.close()
    file.close()
    
1.14.7 HTTP服务器
  • 实现

    import socket
    
    http_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    http_socket.bind(('0.0.0.0', 8080))
    http_socket.listen(129)
    while True:
        	client_socket, client_address = http_socket.accept()
        	data = client_socket.recv(1024).decode('utf8')
        	print(f'接收到了来自{client_address[0]}:{client_address[1]}的数据,内容是:')
        	print(data)
    
        	# 先返回HTTP响应头,每个响应头后面都要有换行
        	client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8'))
        	client_socket.send('Content-Type: text/html;\
                           	charset=utf-8\n'.encode('utf8'))
        	# 响应头结束以后,再发送一个换行,用来表示响应头已经结束,接下来再接收到的数据就是内容
        	client_socket.send('\n'.encode('utf8'))
        	# 返回数据
        	# client_socket.send('hello'.encode('utf8'))
        	# client_socket.send('<h1 style="color:red;">hello</h1>'.encode('utf8'))
        	file = open('test.html', 'rb')
        	content = file.read()
        	client_socket.send(content)
        	file.close()
        	client_socket.close()
    

1.15 操作数据库

1.15.1 sqlite数据库
  • 操作sqlite数据库

    import sqlite3
    
    # 与sqlite数据库建立链接
    conn = sqlite3.connect("data.sqlite")
    
    # 执行sql语句,创建表
    conn.execute("create table if not exists student \
                 	  (id int primary key,name vachar(16))")
    
    # 执行insert语句
    conn.execute("insert into student(id,name) values(1,'yang'),(2,'lang')")
    
    # 执行select,返回一个Cursor对象
    cursor = conn.execute("select * from student")
    print(cursor.fetchall())
    # 输出 [(1, 'yang'), (2, 'lang')]
    
    cursor.close()
    conn.commit()
    conn.close()
    
1.15.2 pymysql
  • pymysql操作数据库

    pip install pymysql
    pip install mysqlclient
    
    import MySQLdb
    
    # 与mysql数据库建立链接
    conn = MySQLdb.connect(host="127.0.0.1", user="root", password="123456",\
                              database="text", port=3306, charset="utf8")
    # 获取游标对象,通过游标对象来操作数据库
    cursor = conn.cursor()
    
    # 执行sql语句,创建表
    cursor.execute("create table if not exists studnet\
    				(id int primary key,name varchar(16))")
    # 执行insert语句
    cursor.execute("insert into studnet values(1,'yang'),(2,'lang')")
    # 执行select语句,返回的结果是影响的记录数
    result = cursor.execute("select * from studnet")
    
    print(result)
    # 输出 2
    
    print(cursor.fetchall())
    # 输出 ((1, 'yang'), (2, 'lang'))
    
    conn.commit()
    conn.close()
    
1.15.3 避免sql注入
  • 避免sql注入

    name = input("请输入用户名:")
    password = input("请输入密码:")
    # 执行sql语句
    # 当name值以 "# 结尾时,就会发生sql注入的风险F
    cursor.execute(f'select * from user \
    				where name="{name}" and password="{password}"')
    
    # 避免sql注入
    sql = 'select * from user where name=%s and password=%s' 
    cursor.execute(sql, (name, password))
    
1.15.4 sqlalchemy
  • sqlalchemy操作数据库

    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, create_engine
    from sqlalchemy.orm import sessionmaker
    
    Base = declarative_base()
    
    
    class User(Base):
        	__tablename__ = "user"
        	id = Column(Integer, primary_key=True)
        	name = Column(String)
        	password = Column(String)
    
        	def __repr__(self):
            	return f"id={self.id},name={self.name},password={self.password}"
    
    # 链接数据库
    conn_info = "mysql+pymysql://root:123456@127.0.0.1:3306/text"
    engine = create_engine(conn_info, encoding="utf8")
    # 使用连接引擎创建一个session
    session = sessionmaker(bind=engine)()
    
    # 添加数据
    s1 = User(id=1, name="yang", password="123456")
    session.add(s1)
    s2 = User(id=2, name="lang", password="456123")
    s3 = User(id=3, name="ssun", password="741258")
    session.add_all([s2, s3])
    
    # 删除数据
    user_1 = session.query(User).filter_by(id=3).first()
    session.delete(user_1)
    
    # 更新数据
    session.query(User).filter_by(id=2).update({"name":"ssun"})
    
    # 查询数据
    print(session.query(User).all())
    print(session.query(User).filter_by(name="ssun").first())
    
    session.commit()
    

的数据,内容是:')

	print(data)

	# 先返回HTTP响应头,每个响应头后面都要有换行
	client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8'))
	client_socket.send('Content-Type: text/html;\
                   	charset=utf-8\n'.encode('utf8'))
	# 响应头结束以后,再发送一个换行,用来表示响应头已经结束,接下来再接收到的数据就是内容
	client_socket.send('\n'.encode('utf8'))
	# 返回数据
	# client_socket.send('hello'.encode('utf8'))
	# client_socket.send('<h1 style="color:red;">hello</h1>'.encode('utf8'))
	file = open('test.html', 'rb')
	content = file.read()
	client_socket.send(content)
	file.close()
	client_socket.close()

1.15 操作数据库

1.15.1 sqlite数据库
  • 操作sqlite数据库

    import sqlite3
    
    # 与sqlite数据库建立链接
    conn = sqlite3.connect("data.sqlite")
    
    # 执行sql语句,创建表
    conn.execute("create table if not exists student \
                 	  (id int primary key,name vachar(16))")
    
    # 执行insert语句
    conn.execute("insert into student(id,name) values(1,'yang'),(2,'lang')")
    
    # 执行select,返回一个Cursor对象
    cursor = conn.execute("select * from student")
    print(cursor.fetchall())
    # 输出 [(1, 'yang'), (2, 'lang')]
    
    cursor.close()
    conn.commit()
    conn.close()
    
1.15.2 pymysql
  • pymysql操作数据库

    pip install pymysql
    pip install mysqlclient
    
    import MySQLdb
    
    # 与mysql数据库建立链接
    conn = MySQLdb.connect(host="127.0.0.1", user="root", password="123456",\
                              database="text", port=3306, charset="utf8")
    # 获取游标对象,通过游标对象来操作数据库
    cursor = conn.cursor()
    
    # 执行sql语句,创建表
    cursor.execute("create table if not exists studnet\
    				(id int primary key,name varchar(16))")
    # 执行insert语句
    cursor.execute("insert into studnet values(1,'yang'),(2,'lang')")
    # 执行select语句,返回的结果是影响的记录数
    result = cursor.execute("select * from studnet")
    
    print(result)
    # 输出 2
    
    print(cursor.fetchall())
    # 输出 ((1, 'yang'), (2, 'lang'))
    
    conn.commit()
    conn.close()
    
1.15.3 避免sql注入
  • 避免sql注入

    name = input("请输入用户名:")
    password = input("请输入密码:")
    # 执行sql语句
    # 当name值以 "# 结尾时,就会发生sql注入的风险F
    cursor.execute(f'select * from user \
    				where name="{name}" and password="{password}"')
    
    # 避免sql注入
    sql = 'select * from user where name=%s and password=%s' 
    cursor.execute(sql, (name, password))
    
1.15.4 sqlalchemy
  • sqlalchemy操作数据库

    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, create_engine
    from sqlalchemy.orm import sessionmaker
    
    Base = declarative_base()
    
    
    class User(Base):
        	__tablename__ = "user"
        	id = Column(Integer, primary_key=True)
        	name = Column(String)
        	password = Column(String)
    
        	def __repr__(self):
            	return f"id={self.id},name={self.name},password={self.password}"
    
    # 链接数据库
    conn_info = "mysql+pymysql://root:123456@127.0.0.1:3306/text"
    engine = create_engine(conn_info, encoding="utf8")
    # 使用连接引擎创建一个session
    session = sessionmaker(bind=engine)()
    
    # 添加数据
    s1 = User(id=1, name="yang", password="123456")
    session.add(s1)
    s2 = User(id=2, name="lang", password="456123")
    s3 = User(id=3, name="ssun", password="741258")
    session.add_all([s2, s3])
    
    # 删除数据
    user_1 = session.query(User).filter_by(id=3).first()
    session.delete(user_1)
    
    # 更新数据
    session.query(User).filter_by(id=2).update({"name":"ssun"})
    
    # 查询数据
    print(session.query(User).all())
    print(session.query(User).filter_by(name="ssun").first())
    
    session.commit()
    

F

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值