Python基础+进阶(万字总结,基础案例+执行结果)

Python基础篇

第一章:基础语法

输出相关:

  • 基本输出案例
print("HelloWorld")

# 执行结果:
'''
HelloWorld
'''
  • 转义字符
# 转义字符"/"
# 输出前加"r",输出原始字符串,即去除转义字符
# 输出前加"f",输出填补字符串,和format相似
name = 'c:\\user'
x = '路径c:\\user'
y = r"路径c:\user"
z = f"路径{
      
      name}"
print(x,"\n",y,"\n",z)

# 执行结果:
'''
路径c:\user 
路径c:\user 
路径c:\user
'''
  • 占位符
age = 17
print("我的年龄是:%d岁"%age)

# 执行结果:
'''
我的年龄是:17岁
'''
  • 间隔符
print("www", "baidu", "com", sep = ".")

# 执行结果:
'''
www.baidu.com
'''
  • 控制符
print("hello", end = "")
print("world")

# 执行结果:
'''
helloworld
'''
  • 连接符
name = "World"
print("Hello" + name)

# 执行结果:
'''
HelloWorld
'''
  • 复制符
count = "num "
print(count*3)

# 执行结果:
'''
num num num 
'''
  • 进制转换
x = 100
print(bin(x)) #转换为二进制
print(oct(x)) #转换为八进制
print(hex(x)) #转换为16进制

# 执行结果:
'''
0b1100100
0o144
0x64
'''
  • 去除/替换指定字符
a = "abcd"
print(a.strip("dc"))
print(a.replace('ab','-'))

# 执行结果:
'''
ab
-cd
'''
  • 切割字符串
a = "ab_cd"
# rsplit()从右开始切
# lsplit()从左开始切
print(a.split("_")[0])
print(a.split("_")[1])
# 执行结果:
'''
ab
cd
'''
  • format
x = "我是{name},今年{age}".format(name = 'cjl', age = 18)
print(x)

# 执行结果:
'''
我是cjl,今年18
'''

输入相关:

  • 基础输入案例
password = input("请输入密码:")
print("你输入的密码是:", password)
print(type(password))

# 执行结果:
'''
请输入密码:666
你输入的密码是: 666
<class 'str'>
'''
  • input默认输入后的类型为字符串
  • 输入后类型强转
password = int(input("请输入密码:"))
print("你输入的密码是:", password)
print(type(password))

# 执行结果:
'''
请输入密码:666
你输入的密码是: 666
<class 'int'>
'''

运算符相关:

算法运算符
  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • % 取模
  • ** 指数
  • // 整除
比较运算符
  • < 小于
  • > 大于
  • <= 小等
  • >= 大等
  • == 恒等
  • != 不等
身份运算符
  • is 判断两个变量引用对象是否相同
  • is not 判断两个变量引用对象是否不同
    • 用来检测两个变量是否是同一个变量
成员运算符
  • in 包含
  • not in 不包含
    • 用来检测某成员是否是另一个变量的成员
逻辑运算符
  • not 逻辑非,都为假时运行
  • or 逻辑或,一个为真时就运行
  • and 逻辑与,都为真才运行
    • and看做乘法,or看做加法
    • Ture看做1,False看做0
赋值运算符
  • +=x += 1 == x + 1=
  • -=x -= 1 == x - 1=
  • *=x *= 1 == x * 1=
  • /=x /= 1 == x / 1=
  • %=x %= 1 == x % 1=
  • //=x //= 1 == x // 1=
  • **=x **= 1 == x ** 1=
运算符规则
  • 数值运算可能改变结果的数据类型,类型的改变与运算符有关,有如下基本规则:
    • 整数浮点数混合运算,输出结果是浮点数
    • 整数之间运算,产生结果类型与操作符相关,除法运算的结果是浮点数
    • 整数浮点数复数运算,输出结果是复数

第二章:判断和循环

if条件判断:

  • if基本格式
if 条件1:
    内容
elif 条件2:
    内容
else:
    内容
  • 嵌套if格式
if 条件1:
    if 条件2:
        if 条件3:
            内容
        else:
            内容
    else:
else:
  • 一行式双分支(又叫三元表达式)
age = int(input("输入年龄:"))
print("未成年" if age<18 else "成年了")

'''
#执行结果:
输入年龄:18
成年了
'''
  • if判断案例-石头剪刀布
import random
print("{0}石头剪刀布游戏{1}".format("*"*10, "*"*10))
print("[0代表:石头]", "[1代表:剪刀]", "[2代表:布]", sep = '\n')
game = ["石头", "剪刀", "布"]
num = input("请输入石头、剪刀、布(0、1、2):")
robot = random.randint(0, 2)
if num.isdigit() and int(num) >= 0 and int(num) <= 2:
    num = int(num)
    print("你出的是'%s',"%game[num], end="")
    if (num == 0 and robot == 1) or (num == 1 and robot == 2) or (num == 2 and robot == 0):
        print("而电脑出的是'%s' — 你赢了!"%game[robot])
    elif num == robot:
        print("而电脑出的也是'%s' — 平局!"%game[robot])
    else:
        print("而电脑出的是'%s' — 你输了!"%game[robot])
else:
    print("<输入有误!>")

# 执行结果:
'''
**********石头剪刀布游戏**********
[0代表:石头]
[1代表:剪刀]
[2代表:布]
请输入石头、剪刀、布(0、1、2):2
你出的是'布',而电脑出的也是'布' — 平局!
'''

for循环:

  • for基本格式
for 表达式1 in 表达式2:
    内容
  • 嵌套for格式
for 表达式1 in 表达式2:
    for 表达式1 in 表达式2:
        内容
  • for循环案例-九九乘法表
for i in range(1, 10):
    for j in range(1, i+1):
        print("%d*%d=%d"%(i, j, i*j), end="\t")
    print("\n")

# 执行结果:
'''
略······
'''
  • 一行式九九乘法表
print('\n'.join([' '.join(['%d*%d=%-2d'%(y,x,x*y) for y in range(1,x+1)]) for x in range(1,10)]))
  • for循环案例-打印菱形
for i in range(1, 6, 2): 
	print(('*' * i).center(5))
for i in reversed(range(1, 4, 2)): 
	print(('*' * i).center(5))

# 执行结果:
'''
  *  
 *** 
*****
 *** 
  *  
'''

while循环:

  • while基本格式
while 条件:
    内容
    表达式
  • while实例:
i = 1
sum = 0
while i<=100:
    sum = sum + i
    i += 1
print(sum)

# 执行结果:
'''
5050
'''
  • while-else格式
while 条件:
    内容
    表达式
else:
    内容
  • while-else实例:
num = 0
while num < 3:
    print("num小于3")
    num += 1
else:
    print("num等于或大于3")

# 执行结果:
'''
num小于3
num小于3
num小于3
num等于或大于3
'''

循环扩展:

  • break - 结束整个循环体
  • continue - 结束本次循环

第三章:数据类型

字符串相关:

  • 切片
str = "abcde12345"
print(str)
print(str[0])
print(str[0:5])
print(str[0:5:2]) #str[起始:结尾:步长]

# 执行结果:
'''
abcde12345
a
abcde
ace
'''

list(列表):

  • list基本格式
# 列表名 = [" "," "," "]
nums = ["a",1,"b"]
  • 遍历列表
names = ["李华", "小明", "马瑞"]
for name in names:
    print(name)

# 执行结果:
'''
李华
小明
马瑞
'''
a = [1,2]
b = [3,4]
#******append******
a.append(b) #将列表b内的每个元素,看做一个整体追加在列表a的最后面
print(a)
#******extend******
a.extend(b) #将列表b内的每个元素,拆分开逐一追加在列表a的最后面
print(a)
#******insert******
a.insert(1,5)  #将元素5插入到列表a元素下标为1的位置
print(a)

#执行结果:
'''
[1, 2, [3, 4]]
[1, 2, [3, 4], 3, 4]
[1, 5, 2, [3, 4], 3, 4]
'''
nums = ["a","b","c",1,2,3]
#******del******
del nums[2] #删除列表nums下标为2的元素
print(nums)
#******pop******
nums.pop()  #删除列表nums最后一个元素
print(nums)
#******remove******
nums.remove("b") #删除指定内容的元素
print(nums)

#执行结果:
'''
['a', 'b', 1, 2, 3]
['a', 'b', 1, 2]
['a', 1, 2]
'''
names = ["张三","李四"]
print(names)
names[0] = "小三"
print(names)

#执行结果:
'''
['张三', '李四']
['小三', '李四']
'''
names = ["张三","李四","张三"]
name = input("请输入要查的元素:")
if name in names:
#index查询的元素有多个时,则输出第一个元素的下标
    print("该元素存在,该元素的下标为:%d"%names.index(name))
else:
    print("该元素不存在")
#count查询该元素在列表中出现的次数
print("该列表存在 %d 个%s"%(names.count(name),names[names.index(name)]))

#执行结果:
'''
请输入要查的元素:张三
该元素存在,该元素的下标为:0
该列表存在 2 个张三
'''
  • 列表生成式:
# 一般写法:
l = ['a_666','b_666','c_666',"d"]
new_l1 = []
for i in l:
    if i.endswith('666'):
        new_l1.append(i)
print(new_l1)
# 生成式写法:
new_l2 = [i for i in l if i.endswith('666')]
print(type(new_l2), new_l2)

#执行结果:
'''
['a_666', 'b_666', 'c_666']
<class 'list'> ['a_666', 'b_666', 'c_666']
'''
  • 列表排序:
    • 内置排序函数:
    • nums = [1,2,3,6,5,4]
      print(nums)
      #******reverse******
      nums.reverse() #逆序
      print(nums)
      #******sort******
      nums.sort() #升序
      print(nums)
      nums.sort(reverse=True) #降序
      print(nums)
      #执行结果:
      '''
      [1, 2, 3, 6, 5, 4]
      [4, 5, 6, 3, 2, 1]
      [1, 2, 3, 4, 5, 6]
      [6, 5, 4, 3, 2, 1]
      '''
      
    • 冒泡排序:
    •  def bubbleSort(alist):
           n = len(alist)
           for i in range(n):
               for j in range(0, n-i-1):
                   if alist[j] > alist[j+1] :
                       alist[j], alist[j+1] = alist[j+1], alist[j]
       alist = [64, 34, 25, 12, 22, 11, 90]
       print ("排序前的数组:", alist)
       bubbleSort(alist)
       print ("排序后的数组:", alist)
       # 执行结果:
       '''
       排序前的数组: [64, 34, 25, 12, 22, 11, 90]
       排序后的数组: [11, 12, 22, 25, 34, 64, 90]
       '''
      
    • 插入排序:
    • def insertSort(alist):
          n = len(alist)
          for i in range(1,n):
              while i > 0:
                  if alist[i] < alist[i-1]:
                      alist[i], alist[i-1] = alist[i-1], alist[i]
                      i -=1
                  else:
                      break
      alist = [64, 34, 25, 12, 22, 11, 90]
      print ("排序前的数组:", alist)
      insertSort(alist)
      print ("排序后的数组:", alist)
      # 执行结果:
      '''
      排序前的数组: [64, 34, 25, 12, 22, 11, 90]
      排序后的数组: [11, 12, 22, 25, 34, 64, 90]
      '''
      
  • 枚举
nums = ["a","b","c","d"]
for i,j in enumerate(nums):
    print(i,j)

#执行结果:
'''
0 a
1 b
2 c
3 d
'''
  • 嵌套列表(二位数组)基本格式
列表名 = [["",""],["",""],["",""]]
print(列表名[外列表下标][内列表下表])
  • list列表实例
products = [["redmi k30",1499],\
            ["redmi k30 pro",2699],\
            ["redmi k30 pro变焦版",2999],\
            ["redmi k30至尊纪念版",1999],\
            ["redmi k30S至尊纪念版",2599],\
            ["手机壳",20],\
            ["钢化膜",10],\
            ["OTG",8]]
print("\n------商品列表------")
#遍历商品列表和价格
for x,phones in enumerate(products):
    print(x+1,"%-20s"%phones[0],"%d元"%phones[1])
print("\n------选购环节------")
#用户自行选购
shopping_cart = []
num = input("请输入需要添加进购物车商品的编号:")

while num != "exit":
    if num.isdigit() and int(num)>0 and int(num)<=len(products):
        shopping_cart.append(products[int(num)-1])
        print("请问还需添加其他商品到购物车吗?")
        print("若需添加请输入对应编号,结账请输入:exit")
        num = input("请输入需要添加进购物车商品的编号:")
    else:
        num = input("该商品不存在,请重新输入:")
else:
    print("\n------结账环节------")
    money = 0
    if len(shopping_cart) != 0:
        print("以下是您购物车内的商品:")
        for shopping in shopping_cart:
            print(shopping[0],":%d元"%shopping[1])
            money = money + shopping[1]
        print("您本次共需支付:%d元"%money)
    else:
        print("购物车空空如也。")
print("******感谢您的光临,下次再见~******")

#执行结果:
'''
------商品列表------
1 redmi k30            14992 redmi k30 pro        26993 redmi k30 pro变焦版     29994 redmi k30至尊纪念版       19995 redmi k30S至尊纪念版      25996 手机壳                  207 钢化膜                  108 OTG                  8------选购环节------
请输入需要添加进购物车商品的编号:5
请问还需添加其他商品到购物车吗?
若需添加请输入对应编号,结账请输入:exit
请输入需要添加进购物车商品的编号:7
请问还需添加其他商品到购物车吗?
若需添加请输入对应编号,结账请输入:exit
请输入需要添加进购物车商品的编号:exit

------结账环节------
以下是您购物车内的商品:
redmi k30S至尊纪念版 :2599元
钢化膜 :10元
您本次共需支付:2609******感谢您的光临,下次再见~******

tuple(元组):

  • tuple基本格式
#元组名 = (" "," "," ")
tup = (123,) #单个元素时结尾加逗号
tup = (1,2,3)
  • 遍历元组
    • list列表操作相同
  • 增删改查
    • 增:只能通过连接2个不同的元祖生成一个新元组
    • 删:只能通过del 元组名删除整个元组
    • 改:元组元素不支持修改
    • 查:和list列表操作相同

dict(字典):

  • dict基本格式
#字典名 = {"":"", "":""}
peoples = {
    
    "张三":18, "李四":15}
#创建空字典
person = dict()
  • 遍历字典
peoples = {
    
    "张三":18, "李四":15}
for key,value in peoples.items():
    print(key,value)

#执行结果:
'''
张三 18
李四 15
'''
peoples = {
    
    "张三":18, "李四":15}
age = input("请输入年龄:")
peoples["王五"] = age
print(peoples)

#执行结果:
'''
请输入年龄:17
{'张三': 18, '李四': 15, '王五': '17'}
'''
peoples = {
    
    "张三":18, "李四":15, "王五":17}
del peoples["张三"] #删除指定的键值对
peoples.pop("李四") #和del作用相同
print(peoples)
peoples.clear()   #清空字典内的内容
print(peoples)
del peoples #删除整个字典,删除后不可访问

#执行结果:
'''
{'王五': 17}
{}
'''
peoples = {
    
    "张三":18, "李四":15}
peoples["张三"] = 17
print(peoples)

#执行结果:
'''
{'张三': 17, '李四': 15}
'''
peoples = {
    
    "张三":18, "李四":15}
#******keys******
print(peoples.keys()) #得到所有键
#******values******
print(peoples.values()) #得到所有值
#******items******
print(peoples.items()) #得到所有键值对
#******get******
print(peoples.get("小三","该键不存在")) #查找指定键对应的值

#执行结果:
'''
dict_keys(['张三', '李四'])
dict_values([18, 15])
dict_items([('张三', 18), ('李四', 15)])
该键不存在
'''
  • 其他操作
    • 合并两个字典:dict1.update(dict2)
    • 把两个列表转换为字典:dict(zip(list1,list2))
  • 字典生成式
keys = [('name','cjl'),('age',18),('sex','男')]
dic = {
    
    k:v for k,v in keys if k != 'sex'}
print(type(dic), dic)

#执行结果:
'''
<class 'dict'> {'name': 'cjl', 'age': 18}
'''

set(集合):

  • set基本格式
#集合名 = {"", "", ""}
nums = {
    
    "a", 1, "b", 2}
  • set独有操作
s = {
    
    1010, "张三", 78, 9}
t = {
    
    1010, "李四", 12.3, 1010}
print(s - t) # 差集
print(s & t) # 交集
print(s ^ t) # 补集
print(s | t) # 并集

#执行结果
'''
{'张三', 9, 78}
{1010}
{'张三', 9, '李四', 12.3, 78}
{1010, '张三', 9, '李四', 12.3, 78}
'''
  • 集合类型的常用操作函数或方法
s = {
    
    1010, "python", 78.9}
print("初始元组为:",s) # s.add(x):如果数据项x不在集合s中,将x增加到s
s.add('大数据')
print("添加后:",s)
s.remove(1010)          # s.remove(x):如果x在集合s中,移除该元素;元素不存在则产生KeyError异常
print("删除后:",s)
s.clear()               # s.clear():移除s中所有数据项
print("清空后:",s)
print("元素个数:",len(s)) # len(s):返回集合s元素个数
print("1010是s元组内:",1010 in s) # x in s:如果x是s的元素,返回True,否则返回False
print("1010不是s元组内:",1010 not in s) # x not in s:如果x不是s的元素,返回True, 否则返回False
print("输出元组s:",s)

#执行结果:
'''
初始元组为: {'python', 1010, 78.9}
添加后: {'python', 1010, '大数据', 78.9}
删除后: {'python', '大数据', 78.9}
清空后: set()
元素个数: 0
1010是s元组内: False
1010不是s元组内: True
输出元组s: set()
'''
  • set()函数将其他的组合数据类型变成集合类型,返回结果是一个无重复且排序任意的集合,set()函数也可以生成空集合变量。
a = set()
print(a)
s = set("知之为知之不知为不知")
print(s)

#执行结果:
'''
set()
{'之', '知', '为', '不'}
'''
  • 集合生成式
keys = ['name','age','sex']
set_1 = {
    
    key for key in keys}
print(type(set_1), set_1)

#执行结果:
'''
<class 'set'> {'name', 'age', 'sex'}
'''

小结对比:

NULL 是否有序 是否可变类型
列表["",""] 有序 可变类型
元祖("","") 有序 不可变类型
字典{"":""} 无序 键不可变,值可变
集合{"",""} 无序 可变类型(不重复)

第四章:函数

函数的定义和调用:

  • 定义函数格式
#def 函数名(形参):
#    内容
def Num(a,b):
    return a+b
print(Num(5,10))

#执行结果:
'''
15
'''

函数的参数:

  • 必选参数
def sum(a,b):
    sum = a+b
    print(sum)
sum(333,333)

#执行结果:
'''
666
'''
  • 缺省参数
def sum(a=333,b=111):
    sum = a+b
    print(sum)
sum(b=333)

#执行结果:
'''
666
'''
  • 可选参数

传入的参数列表为元祖

def sumCount(*args):
    result = 0
    for item in args:
        result += item
    print(result)
sumCount(111,222,333)

#执行结果:
'''
666
'''
  • 关键字参数

传入的参数列表为字典

def demo(**dict):
    print(dict)
    pass
demo(name='cjl', age=18)

#执行结果:
'''
{'name': 'cjl', 'age': 18}
'''
  • 参数相关案例
def people(name, age=18, *phone, **contact):
    print("我是{0},今年{1}岁".format(name,age))
    print("我的手机号是:{0}".format(phone))
    print("我的其他联系方式:%s"%contact)
people("cjl","19",12345,54321,qq="2653644677",wechat="chen2653644677")

#执行结果:
'''
我是cjl,今年19岁
我的手机号是:(12345, 54321)
我的其他联系方式:{'qq': '2653644677', 'wechat': 'chen2653644677'}
'''

参数的引用:

  1. 在python当中万物皆对象,在函数调用的时候,实参传递的就是对象的引用
  2. 了解了原理之后,就可以更好的去把控在函数内部的处理是否会影响到函数外部的数据变化
  • 参数传递是通过对象引用来完成的
li=[]
def test(parms):
    li.append([1,2,3])
    print(id(parms))
    print("内部的{}".format(parms))
print(id(li))
test(li)
print("外部的{}".format(li))

#执行结果:
'''
2712787529992
2712787529992
内部的[[1, 2, 3]]
外部的[[1, 2, 3]]
'''

函数返回值:

  • return
def fun(a,b):
    sum = a + b
    return sum, sum * a
rs1,rs2 = fun(10,10)
print('rs1={0},rs2={1}'.format(rs1,rs2))

#执行结果:
'''
rs1=20,rs2=200
'''

函数的嵌套:

  • 从上向下执行
def fun1():
    print("111")
def fun2():
    print("*****")
    fun1()
    def fun3():
        print("333")
    fun3()
    print("*****")
fun2()

#执行结果:
'''
*****
111
333
*****
'''

变量作用域:

  • 局部变量
def text1():
    a = 123
    print("修改前:%d"%a)
    a = 666
    print("修改后:%d"%a)
def text2():
    a = 888
    print("text2的a值和text1中的a值不冲突--%d"%a)
text1()
text2()

#执行结果:
'''
修改前:123
修改后:666
text2的a值和text1中的a值不冲突--888
'''
  • 全局变量
a = 666  #全局变量
def text1():
    print(a) #调用全局变量a
def text2():
    print(a) #调用全局变量a
text1()
text2()

#执行结果:
'''
666
666
'''
  • 局部、全局变量名相同时
a = 100  #全局变量a
def text1():
    a = 123 #局部变量a和全局变量同名时,局部优先
    print("修改前:%d"%a)
    a = 666
    print("修改后:%d"%a)
def text2():
    print("a的值为:%d"%a) #没有局部变量,默认调用全局变量
def text3():
    global a #声明全局变量在函数中的标识符
    a = 200
    print("使用global修改全局变量后:%d"%a)
text1()
text2()
text3()

#执行结果:
'''
修改前:123
修改后:666
a的值为:100
使用global修改全局变量后:200
'''

匿名函数:

  • 既然叫匿名函数,所以该函数定义时就不需要定义函数名
  • 和一般函数的区别:匿名函数仅用于临时调用一次,调用完就被回收
  • 常用于调用其他函数时,嵌套在其他函数内使用
  • lambda表达式
a = 6
b = 10
# 方式一(违背了`匿名`原则):
rs1 = lambda x,y:max(x,y)
print(rs1(a,b))
# 方式二(其他函数被lambda被动调用):
rs2 = (lambda x,y:max(x,y))(a,b)
print(rs2)
# 方式三(推荐使用):
dic = {
    
    
    "ls": 175,
    "zt": 178,
    "zc": 175,
    "cjl": 184
}
def func(k):
    return dic[k]
res = max(dic, key=func)
print(res)

#执行结果:
'''
10
10
cjl
'''

递归函数:

  • 递归的本质就是循环,函数自己调用自己,默认递归上限1000次
    • 没有尾递归优化
  • 递归的两个阶段
    • 回溯:
      • 一层一层调用下去
    • 递推:
      • 满足某种结束条件,结束递归调用,然后一层一层返回
# 理由递归计算阶乘
def digui(n):
    if n == 1:
        return 1
    else:
        return n*digui(n-1)
print(digui(5))

#执行结果:
'''
120
'''
  • 递归的应用:
# 取出列表内的值
l = [1,2,[3,[4,[5,[6,[7,[8,[9,[10]]]]]]]]]
def fun(list1):
    for x in list1:
        if type(x) is list:
            fun(x)
        else:
            print(x,end=' ')
fun(l)

#执行结果:
'''
1 2 3 4 5 6 7 8 9 10 
'''
  • 递归二分法搜索
nums = [1,2,15,-5,-56,-26,-2,54,62,56,66,99]
def binary_search(find_num, nums):
    print(nums)
    if len(nums) == 0:
        print("要找的值不存在")
        return
    cen_num = len(nums) // 2
    if find_num > nums[cen_num]:
        nums = nums[cen_num+1:]
        binary_search(find_num, nums)
    elif find_num < nums[cen_num]:
        nums = nums[:cen_num]
        binary_search(find_num, nums)
    else:
        print("找到了")
find_num = int(input("请输入要查的数字:"))
nums.sort()
binary_search(find_num, nums)

# 执行结果:
'''
请输入要查的数字:-2
[-56, -26, -5, -2, 1, 2, 15, 54, 56, 62, 66, 99]
[-56, -26, -5, -2, 1, 2]
找到了
'''

内置函数:

  • max(x):获取最大值
    • 一般比较用法:max(列表)
    • 比较字典的值,获取最大值对应的键
    • dic = {
              
              
          "ls": 175,
          "zt": 178,
          "zc": 175,
          "cjl": 184
      }
      res = max(dic, key=lambda k:dic[k])
      print("最大值对应的键为:" + res)
      # 最大值对应的键为:cjl
      
  • min(x):获取最小值
    • 一般比较用法:min(列表)
    • 比较字典的值,获取最小值对应的键,和获取最大值用法相同
  • cmp(a,b)
    • 用于判断a和b的大小关系,a<b返回-1a==b返回0a>b返回1
  • eval('')
    • 用来执行一个字符串表达式,并返回表达式的值
    • a,b = 10, 6
      print(eval('a*b + pow(b,2) - 66'))
      print(int('3.14'), eval('3.14'))
      # 30
      # 3 3.14
      
  • all(xxx)
    • 如果参数列表中含有False、0则返回False,否则返回True
    • li=[0,1,2]
      print(all(li))
      # False
      
  • any(xxx)
    • 如果参数列表都为False、空、0则返回False,否则返回True
    • li=[0,1,2]
      print(any(li))
      # True
      
  • xxx.sort()
    • 仅对list列表进行排序操作,直接修改原始对象,默认为升序
    • 参数:
      • key=len:按字符串长度排序
      • key=str.lower:忽略大小写排序
      • reverse=True:更改为降序
  • sorted(xxx)
    • 所有可迭代的对象进行排序操作,不改变原来的对象,而是返回一个新的列表,参数reverse=True时排序顺序为降序
    • dic = {
              
              
          "ls": 175,
          "zt": 178,
          "zc": 175,
          "cjl": 184
      }
      res = sorted(dic, key=lambda k:dic[k])
      print(res)
      # ['ls', 'zc', 'zt', 'cjl']
      
  • zip(xx,xx,...)
    • 把序列中对应的索引位置的元素,储存为一个元祖,可强转为list列表输出
    • li=['a','b','c']
      ls=['我','你','他']
      print(list(zip(li,ls)))
      # [('a', '我'), ('b', '你'), ('c', '他')]
      
  • enumerate()
    • 返回一个枚举对象,用于将一个可遍历的数据对象(如:列表、元祖、字符串)组合为一个索引序列
    • li=['你','真','菜']
      for item in enumerate(li,1):
          print(item,end=' ')
      # (1, '你') (2, '真') (3, '菜') 
      
  • hasattr(x,x)
    • 用于判断对象是否包含对应的属性
    • class hasattrDemo:
      a = 1
      demo = hasattrDemo()
      print(hasattr(demo,'a'),hasattr(demo,'b'))
      # True False
      
  • isinstance(a,b)
    • 用于判断a是否是b类型,类似于type()
  • vars()
    • 用于返回对象的属性和属性值的字典对象
  • map()(了解)
    • 据提供的函数对指定序列做映射
    • l = [1,2,3,4,5]
      def square(x):
          return x ** 2
      res = list(map(square, l))
      print(res)
      # 使用lambda匿名函数
      # print(list(map(lambda x: x ** 2, l)))
      
      # 执行结果:
      '''
      [1, 4, 9, 16, 25]
      '''
      
    • 对字典
    • L = ["1","2","3","4","5"]
      def func(key):
          dic = {
              
              "0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6}
          return dic[key]
      res = list(map(func, L))
      print(res)
      
      # 执行结果:
      '''
      [1, 2, 3, 4, 5]
      '''
      
  • reduce()(了解)
    • 对参数序列中元素进行累积
    • from functools import reduce
      L = [1,2,3,4,5]
      def func(x,y):
          return x*10 + y
      res = reduce(func,L)
      print(type(res), res)
      
      # 执行结果:
      '''
      <class 'int'> 12345
      '''
      
  • iter():返回一个迭代器
    • next():获取迭代器中下一个元素
    • lis = [i for i in range(1,3)]
      print(lis)
      ite = iter(lis)
      print(ite)
      print(next(ite))
      print(next(ite))
      
      #执行结果:
      [1, 2]
      <list_iterator object at 0x000002515BCE5370>
      1
      2
      

第五章:面向对象(上)

类和对象:

  • 需用class关键字
  • 类命名
    • 遵循“大驼峰”
    • 首字母大写
#定义一个类
class Student():
#定义空类时,可用pass当做占位符
    pass
#定义类中的函数一般需用self站位(self可替换),例如:   
class StudentAll():
    name = 'cjl'
    age = 18
    language = 'python'
    def hello(self):
        print("你好!")
        
student = StudentAll()
student.hello()
print(student.name, student.age, student.language)

#执行结果:
'''
你好!
cjl 18 python
'''

self:

  • self在对象的方法中表示当前对象本身,如果通过对象调用一个方法,那么该对象会自动传入到当前方法的第一个参数中
  • self并不是关键字,只是一个用于接受对象的普通参数,理论上可以用任何一个普通变量名代替
  • 方法中有self形参的方法成为非绑定类的方法,可以通过对象访问,没有self的是绑定类的方法,只能通过类访问
  • 使用类访问绑定类的方法时,如果类方法中需要访问当前类的成员,可以通过__class__成员名
  • self指的是类实例对象本身,相当于java的this
class Teacher():
    name = "cjl"
    age = 18
    def say(self):
        self.name = "aaa"
        self.age = "19"
        print("my name is {}".format(self.name))
        #调用类内的成员时需要使用__class__
        print("my age is {}".format(__class__.age))
    def sayAgain():
        print(__class__.name)
        print(__class__.age)
        print("hello")
        
t = Teacher()
t.say()
#调用绑定类函数使用类名
Teacher.sayAgain()

#执行结果:
'''
my name is aaa
my age is 18
cjl
18
hello
'''

五种下划线:

  • _:用于临时或无意义变量的名称
  • _xxx:命名约定,说明该属性或方法仅供内部使用,但解释器不会强制执行
  • xxx_:避免声明的变量和关键字冲突
  • __xxx:用于声明属性和方法的私有化,解释权强制执行
  • __xxx__:Python自带的魔术方法,应避免自己声明该命名方式

__init__构造函数:

  • python自带的内置函数具有特殊的函数,使用双下划线包起来的【魔术方法】
  • 是一个初始化的方法用来定义实例属性和初始化数据的,在创建对象的时候自动调用,不用手动去调用
  • 利用传参的机制可以让我们定义功能更加强大并且方便的类
class People():
    def __init__(self,name,age):
        self.name = name
        self.age = age
cjl = People('陈家霖',18)
print('我是{0}今年{1}岁'.format(cjl.name, cjl.age))

#执行结果:
'''
我是陈家霖今年18岁
'''

魔术方法:

  • __name__:输出当前的类名
if __name__ == '__main__':
    ...
  • __all__:在使用from xxx import *导入模块时,不会导入__all__=[]外的方法,但import xxx不受影响
  • __str__:在将对象转换成字符串,相当于java的toString
class People():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '我是{0}今年{1}岁'.format(self.name, self.age)
cjl = People('陈家霖',18)
print(cjl)

#执行结果:
'''
我是陈家霖今年18岁
'''
  • __new__:优先 __init__初始化方法被调用,第一个参数默认为cls
class Person(object):
    def __init__(self, name, age):
        print('执行__init__')
        self.name = name
        self.age = age
    def __new__(cls, name, age):
        print('执行__new__')
        return super(Person, cls).__new__(cls)
    def __str__(self):
        return '<Person: %s(%s)>'%(self.name, self.age)
cjl = Person('cjl', 18)
print(cjl)

#执行结果:
'''
执行__new__
执行__init__
<Person: cjl(18)>
'''
  • __mro__:用于显示类的继承关系
class D():
    def play(self):
        print("'D'类的play")
class C(D):
    def play(self):
        print("'C'类的play")
class B(D):
    pass
class A(B,C):
    pass
demo = A()
demo.play()
print(A.__mro__)

#执行结果:
'''
'D'类的play
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
'''
  • __dict__:用于查看类的所有属性,以字典形式显示
class People():
    def __init__(self,name,age):
        self.name = name
        self.age = age
cjl = People('cjl',18)
print(cjl.__dict__)

#执行结果:
'''
{'name': 'cjl', 'age': 18}
'''

析构方法:

  • __del__:和__init__一样自动执行,用于释放对象实现资源回收,当一个对象调用后,自动执行清理该对象;也可使用del 对象名手动清理
class People():
    def __init__(self,name):
        self.name = name
        print("我是 %s 执行构造方法"%name)
    def __del__(self):
        print("执行析构方法,回收对象")
cjl = People("cjl")
print("--------使用手动清理--------")
del cjl  # 手动清理
print(cjl)

#执行结果:
'''
我是 cjl 执行构造方法
--------使用手动清理--------
执行析构方法,回收对象
NameError: name 'cjl' is not defined
'''

继承:

  • 单继承:一个子类继承一个父类(找亲爹)
class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def eat(self):
        print('吃饭...')
class Men(Person):
    def __init__(self, name, age, height):
        super().__init__(name,age)
        self.height = height
    def play(self):
        print('玩儿...')
    def __str__(self):
        return '我是{}今年{}岁,身高{}'.format(self.name,self.age,self.height)
cjl = Men('cjl',18,183)
print(cjl, '\n调用父类方法:')
cjl.eat()

#执行结果:
'''
我是cjl今年18岁,身高183 
调用父类方法:
吃饭...
'''
  • 多继承:一个子类继承多个父类(认干爹)
class A():
    def a(self):
        print("A:我是C类它祖先类")
    pass
class B(A):
    def b(self):
        print("B:我是C类它父类")
    pass
class C(B):
    pass
num = C()
num.a()
num.b()
print(C.__mro__)

#执行结果:
'''
A:我是C类它祖先类
B:我是C类它父类
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
'''

重写:

  • 所谓重写,就是在子类中有一个和父类一模一样的方法,即子类的方法会覆盖父类的方法
class Dog():
    def __init__(self,name,color):
        self.name = name
        self.color = color
    def bark(self):
        print("父类:汪汪汪的叫...")
class HaShiQi(Dog):
    def __str__(self):
        return '这一只 {0} 的狗叫 {1} '.format(self.color,self.name)
    def bark(self):
        # 重写父类方法
        print("子类:嗷嗷嗷的叫...")
hsq = HaShiQi('哈士奇','白色')
print(hsq)
hsq.bark()

#执行结果:
'''
这一只 白色 的狗叫 哈士奇 
子类:嗷嗷嗷的叫...
'''

多态:

  • 多态的实现需要遵循两个条件:
    • 继承、多态发生在父类和子类之间
    • 重写、子类重写父类的方法
class Animals:
    def say_hello(self):
        print("我是一只小动物...")
class People:
    def say_hello(self):
        print("我是人...")
class Pig(Animals):
    def say_hello(self):
        print("我是可爱的小猪.")
class Cat(Animals):
    def say_hello(self):
        print("我是呆萌的小猫.")
class Dog(Animals):
    def say_hello(self):
        print("我是忠诚的小狗.")
class Student(People):
    def say_hello(self):
        print("我是三年级的小朋友.")
def commonInvoke(obj):
    obj.say_hello()
listObj = [Pig(),Cat(),Dog(),Student()]
for item in listObj:
    commonInvoke(item)
    
#执行结果:
'''
我是可爱的小猪.
我是呆萌的小猫.
我是忠诚的小狗.
我是三年级的小朋友.
'''

类属性和实例属性:

  • 类属性是可以被类对象和实例对象共同访问使用的
  • 实例属性只能由实例对象所访问
class Person:
    age = 18
    def __init__(self,name):
        self.name = name
cjl = Person('cjl')
print(cjl.name)
print(Person.name)

#执行结果:
'''
实例对象: 18 cjl
类对象: 18
AttributeError: type object 'Person' has no attribute 'name'
'''

类方法和静态方法:

  • 类方法用@classmethod来修饰,类方法的第一个参数对象是cls,虽然也能通过实例访问,但不推荐这样调用
class Person:
    people = 'cjl'
    @classmethod
    def get_name(cls):
        return cls.people
    @classmethod
    def change_name(cls,name):
        cls.people = name
print('类方法调用:%s'%(Person.get_name()))
p = Person()
print('实例对象调用(不推荐):%s'%(p.get_name()))
print('--------------修改之后----------------')
Person.change_name('lxl')
print(Person.get_name())

#执行结果:
'''
类方法调用:cjl
实例对象调用(不推荐):cjl
--------------修改之后----------------
lxl
'''
  • 静态方法用@staticmethod来修饰,静态方法可以不带参数,使用类和实例均可调用
import time
class TimeText:
    @staticmethod
    def time():
        return time.strftime('%H:%M:%S',time.localtime())

print('类对象调用:',TimeText.time())
demo = TimeText()
print('实例对象调用:',demo.time())

#执行结果:
'''
类对象调用: 09:44:47
实例对象调用: 09:44:47
'''

第六章:面向对象(下)

装饰器:

  • 装饰器就是在不修改不被装饰器对象源代码与调用方式的前提下为其添加新功能
  • 多个装饰器,则由下往上加载,由上到下运行
  • 无参装饰器模板:
# 无参装饰器基本模板
def outter(func):
    def wrapper(*args, **kwargs):
        # 1.调用原函数
        # 2.为其添加新功能
        res = func(*args,**kwargs)
        return res
    return wrapper
  • 无参装饰器语法糖 -> 使用@修饰函数,例:
# @print -> home=print(home)
@print
def home(x,y):
    pass
print(home)
  • 实例:
def auth(func):
    def wrapper(*args, **kwargs):
        name = input("name>>>:")
        pwd = input("pws>>>:")
        if name == 'root' and pwd == '123':
            res = func(*args,**kwargs)
            return res
        else:
            print("输入错误")
    return wrapper
@auth
def index():
    print("from index")
index()

#执行结果:
'''
name>>>:root
pws>>>:123
from index
'''
  • 带参装饰器模板:
def 有参装饰器(x,y,z):
    def outter(func):
        def wrapper(*args, **kwargs):
            res = func(*args, **kwargs)
            return res
        return wrapper
    return outter
@有参装饰器(1,y=2,z=3)
def 被装饰对象():
    pass
  • 实例:
# 只用套三层,第三层就可以无限接收参数了
def auth(db_type):
    def deco(func):
        def wrapper(*args, **kwargs):
            name = input('your name>>>: ').strip()
            pwd = input('your password>>>: ').strip()
            if db_type == 'file':
                print('基于文件的验证')
                if name == 'egon' and pwd == '123':
                    res = func(*args, **kwargs)  
                    return res
                else:
                    print('user or password error')
            elif db_type == 'mysql':
                print('基于mysql的验证')
            else:
                print('不支持该db_type')
        return wrapper
    return deco
@auth(db_type='file')  
def index(x, y):
    print('index->>%s:%s' % (x, y))
@auth(db_type='mysql') 
def home(name):
    print('home->>%s' % name)
# index(1, 2)
# home('egon')

迭代器:

  • 迭代指的是重复取值的过程,并且每次重复都是基于上一次的结果而继续的;而迭代器则是迭代取值的工具
  • 可迭代对象:
    • 只要内置有__iter__()方法的都称为可迭代对象
      • 字符串,列表,元组,字典,集合,文件对象
    • 调用可迭代对象下的__iter__()方法,会将其转换成迭代对象
  • 迭代器对象:
    • 内置有__next__方法并且内置有__iter__方法的对象
      • __next__(): 得到迭代器的下一个值
      • __iter__(): 得到迭代器本身,
  • for循环工作原理:
    • for i in xxx -> for i in xxx.__iter__()
# while 遍历字典 key
d = {
    
    'a':1, 'b':2, 'c':3}
d_iterator = d.__iter__()
while True:
    try:
        print(d_iterator.__next__())
    except StopIteration:
        break
# for 遍历字典 key
for k in d:
    print(k)
  • 迭代器优缺点:
    • 优点:
      • 为序列和非序列类型提供了一种统一的迭代取值方式
      • 惰性取值;每次只取一个数据,不占内存;迭代器保存的是产生数据的算法,而不是实际的数据
    • 缺点:
      • 除非取尽,否则无法获取迭代器的长度
      • 只能往后依次取值,不能返回头往前取值。就像象棋中的卒,只进不退

生成器:

  • 用关键字yield为函数添加多个返回值,生成器==迭代器
  • yield -> 可以返回无数个值,并将函数挂起
  • return -> 只能返回一次值
def fun():
    print("第一次")
    yield 1
    print("第二次")
    yield 2
    print("第三次")
g = fun()
g.__iter__()
print(g.__next__())
print(g.__next__())

# 执行结果:
'''
第一次
1
第二次
2
'''
  • 自定义迭代器
def my_range(start,stop,step=1):
    while start < stop:
        yield start
        start+=step
for i in my_range(1,10,2):
    print(i,end=' ')
    
# 执行结果:
'''
1 3 5 7 9 
'''
  • yield表达式:
    • .send(): 为yield传值,也可以传列表,但第一次传值必须是Nonenext(x)
    • .close(): 关闭后无法传值
def person(name):
    print("我是%s"%name)
    while True:
        x = yield
        print("%s是%s"%(name,x))
g = person("cjl")
g.send(None)
g.send("小菜B")
g.close()
g.send("大神")

# 执行结果:
'''
我是cjl
cjl是小菜B
报错...
'''

私有化属性:

  • 在属性前加__,私有化后在外部不能调用,子类不能继承
class Person:
    def __init__(self):
        self.__name = 'cjl'
        self.age = 18
    def __str__(self):
        return '我是{0}今年{1}岁了'.format(self.__name, self.age)
class Men(Person):
    def printInfo(self):
        # 无法继承父类的私有化属性
#         print(self.name)
        print(self.age)
p = Person()
print(p)
# 无法在外部访问私有化属性
# print(p.__name)
men = Men()
men.printInfo()

#执行结果:
'''
我是cjl今年18岁了
子类继承父类: 18
'''
  • 私有化方法:
    • 和私有化属性一样,在方法前加__,私有化后在外部不能调用,子类不能继承

property属性函数:

  • 使用property属性函数,用于调用和修改私有化属性
class Person:
    def __init__(self):
        self.__age = 18
    def get_age(self):
        return self.__age
    def set_age(self,age):
        if age < 0:
            print("年龄有误")
        else:
            self.__age = age
    age = property(get_age,set_age)
cjl = Person()
cjl.age = 19
print('修改后的年龄:',cjl.age)

#执行结果:
'''
修改后的年龄: 19
'''
  • 使用装饰器,用于调用和修改私有属性,用关键字@property@xxx.setter进行装饰,推荐使用该方法
class Person:
    def __init__(self):
        self.__age = 18
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,age):
        if age < 0:
            print("年龄有误")
        else:
            self.__age = age
cjl = Person()
cjl.age = 19
print('修改后的年龄:',cjl.age)

#执行结果:
'''
修改后的年龄:19
'''

单例模式:

  • 确保一个类只有一个实例的存在(类似win系统的回收站)
  • 实现方式一:通过类属性保存初次创建的实例对象,如果存在就返回保存的,没有就创建新的实例对象
class DataBase(object):
    _instance = None
    def __init__(self, name, age):
        print(name, age)
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance=super(DataBase,cls).__new__(cls)
        return cls._instance
db1 = DataBase('cjl',18)
print(id(db1))
db2 = DataBase('lxl',15)
print(id(db2))

#执行结果:
'''
cjl 18
2488840593520
lxl 15
2488840593520
'''
  • 实现方式二:只执行一次init方法,通过类变量进行标记控制
class Demo(object):
    __instance = None
    __isinit = True
    def __init__(self, name, age):
        if Demo.__isinit:
            self.name = name
            self.age = age
            __isinit = False
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance=super(Demo,cls).__new__(cls)
            return cls.__instance
        else:
            return cls.__instance
d1 = Demo('cjl',18)
print(id(d1), d1.name,d1.age)
d2 = Demo('lxl',15)
print(id(d2), d2.name,d2.age)

#执行结果:
'''
2488816354400 cjl 18
2488816354400 lxl 15
'''

动态绑定属性方法:

  • 动态添加类属性、方法属性
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '{}今年{}岁了'.format(self.name,self.age)

cjl = People('cjl',18)
People.sex = '男'
print(cjl)
print("动态添加类属性:性别,",cjl.sex)

#执行结果:
'''
cjl今年18岁了
动态添加类属性:性别, 男
'''
  • 动态绑定类方法
import types
def textMothend(self):
    print('{}今年{}岁了,性别:{}'.format(self.name,self.age,self.sex))
@classmethod
def classmethodTest(cls):
    print("类方法...")
@staticmethod
def staticmethodTest():
    print("静态方法...")
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '{}今年{}岁了'.format(self.name,self.age)

cjl = People('cjl',18)
People.sex = '男'
print(cjl)
print("动态添加类属性:性别 -",cjl.sex)
cjl.printInfo = types.MethodType(textMothend,cjl) #动态绑定方法
print("---------------动态绑定后-------------")
cjl.printInfo()
# 绑定类方法 
People.TestMethod = classmethodTest
print("通过类调用:",end='\t\t')
People.TestMethod()
print("通过实例对象调用:",end='\t')
cjl.TestMethod()
# 绑定静态方法 
People.TestMethod = staticmethodTest
print("通过类调用:",end='\t\t')
People.TestMethod()
print("通过实例对象调用:",end='\t')
cjl.TestMethod()

#执行结果:
'''
cjl今年18岁了
动态添加类属性:性别 - 男
---------------动态绑定后-------------
cjl今年18岁了,性别:男
通过类调用:		类方法...
通过实例对象调用:	类方法...
通过类调用:		静态方法...
通过实例对象调用:	静态方法...
'''

__slots__:

  • __slots__ = ():后跟元组,类型是字符串
    • 限制实例添加的属性,括号内为空时,则不允许添加任何属性;
    • 节省空间,使用后则类属性不会被存放在__dict__内,所以无法使用__dict__访问全部类属性;
    • 继承时子类不受影响,但如果子类也声明该方法时,则也会继承父类的属性限制
class Person(object):
    # 添加属性限制
    __slots__ = ('name','age','sex')
    def __init__(self):
        pass
    def __str__(self):
        return '{}........{}'.format(self.name,self.age)
class Men(Person):
    __slots__ = ('school')
    def __init__(self):
        pass
    def __str__(self):
        return '{}....{}....{}'.format(self.name,self.school,self.age)
    pass
cjl = Person()
cjl.name = 'cjl'
cjl.age = 19
# cjl.school = 'sqxy' # 未在属性限制范围内,所以报错
print(cjl)
cjl.sex = '男'
lxl = Men()
lxl.name = 'lxl'
lxl.age = 15
lxl.school = '七中'
print(lxl)

#执行结果:
'''
cjl........19
lxl....七中....15
'''

第七章:文件操作

读写文件:

  • 常用访问模式:
    • r:以只读方式打开(默认模式)
    • w:用于写入,如果文件存在会将其覆盖,不存在则会创建
    • a:用于写入,如果文件存在会在其后追加内容,不存在则会创建
    • rb:以二进制的只读方式打开
    • wb:以二进制的写入模式打开
    • +:打开一个文件进行更新(可读可写)
    • 注: 路径中由于\是转义符,所以表示路径时,使用\\/或路径前加r
  • encoding='utf-8'设置文件编码,二进制读写时不用设置编码
  • 基本格式:
#变量名 = open("文件名","访问模式")
#文件名.close()
txt = open(r'路径', 'r', encoding='utf-8')
print(txt.read())
txt.close()

# 推荐使用with格式,with格式:
# with open("文件名",'访问模式') as 别名:
with open(r'路径', 'r') as txt:
    print(txt.read())
  • 文件读取生成式:
# 生成式读取文件字节
with open('test.txt', 'rb') as r:
    # 生成式
    res = sum(len(line) for line in r)
    print(res)

#执行结果:
'''
38889
  • 文件读写相关方法:
    • .readline():从文件中读入一行内容
    • .readlines():从文件中读入所有行,以每行为元素形成一个列表
    • .write():单行写入,将一个字符串写入文件
    • .writelines():直接将列表类型的各元素连接起来并写入
    • .tell():文件定位,获取当前文件指针读取到的位置
    • .truncate(x):截取输出前x个字符
    • .seek(x,y):改变当前文件操作指针的位置,x的值为偏移量单位字节,y的值(0: 文件开头; 1: 当前位置; 2: 文件结尾)
  • 文件操作实例:
# 文件的读写 - 文件备份
def run(name):
    try:
        old_file = name
        new = old_file.split('.')
        new_file = new[0] + '_备份.' + new[1]
        with open(old_file,'rb') as r, open(new_file, 'wb') as w:
            for line in r:
                w.write(line)
    except Exception as result:
        print("输入的文件名不存在.")
    else:
        print(name, "文件备份完成.")
name = input("请输入需要备份的文件名:")
run(name)

#执行结果:
'''
请输入需要备份的文件名:text.txt
text.txt 文件备份完成.
'''
  • 实例2:
# .seek()的应用 - 监测文件的实时写入
import time
with open('xxx', 'rb') as f:
    f.seek(0,2)
    while True:
        line = f.readline()
        if len(line) == 0:
            time.sleep(0.5)
        else:
            print(line.decode('utf8'))

遍历文件:

  • 从文本文件中逐行读入内容并进行处理是一个基本的文件操作需求。文本文件可以看成是由行组成的组合类型,因此,可以使用遍历循环逐行遍历文件。
with open('路径', 'r') as txt:
    print(txt.readlines())
    for x in txt:
        print(x)

操作文件:

  • 文件重命名
import os
os.rename("原名称", "新名称")
  • 删除文件
import os
os.remove("文件名")
  • 获取当前目录
import os
os.getcwd()
  • 改变默认目录
import os
os.chdir("路径")
  • 遍历目录列表
import os
with os.scandir('d:/') as scan:
    for s in scan:
        print(s.name)
  • 遍历目录文件
import os
basePath = 'd:/'
for s in os.scandir(basePath):
    if os.path.isfile(os.path.join(basePath,s))
        print(s)
  • 创建文件夹
import os
os.mkdir("文件夹名")
  • 删除文件夹
import os
os.redir("文件夹名")

第八章:错误与异常

常见的异常类型:

  • Exception:代表所有异常类型
  • AssertError:断言语句(assert)失败
  • AttributeError:尝试访问未知的对象属性
  • EOFError:用户输入文件末尾标志EOF(Ctrl+d)
  • FloatingPointError:浮点计算错误
  • GeneratorExit:generator.close()方法被调用的时候
  • ImportError:导入模块失败的时候
  • IndexError:索引超出序列的范围
  • KeyError:字典中查找一个不存在的关键字
  • KeyboardInterrupt:用户输入中断键(Ctrl+c)
  • MemoryError:内存溢出(可通过删除对象释放内存)
  • NameError:尝试访问一个不存在的变量
  • NotImplementedError:尚未实现的方法
  • oSError:操作系统产生的异常(例如打开一个不存在的文件)
  • OverflowError:数值运算超出最大限制
  • ReferenceError:弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象
  • RuntimeError:一般的运行时错误
  • StopIteration:迭代器没有更多的值
  • SyntaxError:Python的语法错误
  • IndentationError:缩进错误
  • TabError:Tab和空格混合使用
  • SystemError:Python编译器系统错误
  • SystemExit:Python编译器进程被关闭
  • TypeError:不同类型间的无效操作
  • UnboundLocalError:访问一个未初始化的本地变量(NameError的子类)
  • UnicodeError:Unicode相关的错误(ValueError的子类)
  • UnicodeEncodeError:Unicode编码时的错误(UnicodeError的子类)
  • UnicodeDecodeError:Unicode解码时的错误(UnicodeError的子类)
  • UnicodeTranslateError:Unicode转换时的错误(UnicodeError的子类)
  • ValueError:传入无效的参数
  • ZeroDivisionError:除数为零

异常处理:

  • 基本格式
'''
try:
    内容
except Exception as 别名:
    内容
'''
try:
    print("----text--1----")
    f = open("不存在.txt","r")
    #该文件不存在,报错
    print("----text--2----")
except Exception as result:
    #Exception可以承接所有异常信息
    print(result) #捕获异常后,执行的代码

#执行结果:
'''
----text--1----
[Errno 2] No such file or directory: '不存在.txt'
'''
  • try...finally嵌套,finally内的代码无论有无异常都执行
import time
try:
    f = open("test1.text","r")
    try:
        while True:
            content = f.readline()
            if len(content) == 0:
                break
            time.sleep(2)
            print(content)
    finally:
        f.close()
        print("文件关闭")
except Exception as result:
    print("发生异常···")
    
#执行结果:
'''
发生异常···
'''

手动引发异常:

  • 使用raise关键字实现手动引发异常
try:
    print("我是cjl")
    #手动引发一个异常,注意语法:raise ErrorClassName
    raise ValueError
    print("还没完呀")
except NameError as e:
    print("NameError")
except ValueError as e:
    print ("ValueError")
except Exception as e:
    print("有异常")
finally:
    print("我肯定会被执行")
    
#执行结果:
'''
我是cjl
ValueError
我肯定会被执行
'''

自定义异常:

class TextException(Exception):
    def __init__(self,leng):
        self.len = leng
    def __str__(self):
        return '你输入的数据长度是:' + str(self.len) + ',超过长度了.'
class TextDemo():
    name = input('请输入数据:')
    try:
        if len(name) > 5:
            raise TextException(len(name))
        else:
            print(name)
    except TextException as result:
        print(result)
    finally:
        print("执行完毕.")
TextDemo()

#执行结果:
'''
请输入数据:gfhsuidgoashuidghasu
你输入的数据长度是:20,超过长度了.
执行完毕.
'''

Python进阶篇

第一章:进程、线程与协程

概述:

  • 并发:看上去一起执行,任务数大于CPU核心数
  • 并行:一起执行,任务数必须小于等于CPU核心数
  • 同步:指的是主动请求后等待I/O,数据就绪后读写必须阻塞
  • 异步:指的是主动请求后,可处理其他任务,等I/O完毕后通知
  • 实现多任务的方式:
    • 多进程方式
    • 多线程方式
    • 协程方式
    • 多进程+多线程

多进程:

  • xxx = Process()创建子进程,方法:
    • target():子进程任务
    • args():进程的说明(元组)
    • xxx.start():启动子进程
    • xxx.join():让父进程等待子进程结束之后父进程再结束,参数timeout=父进程的等待时间(单位s)
from multiprocessing import Process
import time
import os
def func(self):
    print("子进程---",os.getpid())
    time.sleep(1.5)
    print("子进程结束...")
if __name__ == '__main__':
    print("父进程启动...")
    p = Process(target=func, args=("python",))
    p.start()
    p.join()
    print("父进程---",os.getpid())
    print("父进程结束...")
        
#执行结果:
'''
父进程启动...
子进程--- 8900
子进程结束...
父进程--- 20308
父进程结束...
'''
  • 在子进程中修改全局变量,对父进程中的全局变量没有影响
  • 创建子进程的时候,其实是对全局变量做了一个备份
  • 所有进程对全局变量的修改都不会影响其它进程
from multiprocessing import Process
num = 100
def run1():
    print("孙子进程开始...")
    global num
    num += 1
    print("孙子进程num值: ", num)
    print("孙子进程结束...")
def run():
    print("子进程开始...")
    p1 = Process(target=run1)
    p1.start()
    p1.join()
    global num
    num += 1
    print("子进程num值: ", num)
    print("子进程结束...")
if __name__ == '__main__':
    print("父进程开始...")
    p = Process(target=run)
    p.start()
    p.join()
    print("父进程num值: ", num)
    print("父进程结束...")

#执行结果:
'''
父进程开始...
子进程开始...
孙子进程开始...
孙子进程num值:  101
孙子进程结束...
子进程num值:  101
子进程结束...
父进程num值:  100
父进程结束...
'''
  • 多进程另一种调用方法 -> 继承进程类
from multiprocessing import Process
class MyProcess(Process):
    # run()是固定的,当线程被执行的时候,被执行的就是run()
    def run(self):
        for i in range(100):
            print("子进程:", i)
if __name__ == '__main__':
    t = MyProcess()
    # t.run() -> 调用该方法为单线程
    t.start() # 启动子线程
    for i in range(100):
        print("主进程", i)

进程池:

  • python内置的进程池Pool,导入from multiprocessing import Pool模块,方法:
    • pool.map(x,y):使进程阻塞直到返回结果(),参数x为方法,y为一个迭代器
    • pool.apply(): 同步执行(串行)(不建议使用)
    • pool.apply_async(): 异步执行(并行),非阻塞且支持结果返回进行回调
    • pool.terminate(): 立刻关闭进程池,不在处理未处理的任务
    • pool.close(): 等待所有进程结束后,才关闭进程池,使其不在接受新的任务
    • pool.join(): 主进程等待所有子进程执行完毕。必须在close()terminate()之后。
from multiprocessing import Pool
import time
def task(i):
    time.sleep(1)
    print("任务%s执行结束..." % i)
if __name__ == '__main__':
    # 实例化进程对象
    pool = Pool(2)
    for i in range(1,6):
        pool.apply_async(func=task, args=(i, ))
    pool.close()
    pool.join()

#执行结果:
'''
任务1执行结束...
任务2执行结束...
任务3执行结束...
任务4执行结束...
任务5执行结束...
任务6执行结束...
'''
  • 一次性开辟一些进程。我们用户直接给进程池子提交任务。进程任务的调度交给进程池来完成
from concurrent.futures import ProcessPoolExecutor
def fun(name):
    for i in range(100):
        print(name,i)
if __name__ == '__main__':
    # 创建进程池
    with ProcessPoolExecutor(10) as t:
        for i in range(50):
            t.submit(fun, name=f'进程{
      
      i}')
    print("进程任务执行完毕...")

进程锁:

  • 为了防止和多线程一样的出现数据抢夺和脏数据的问题,同样需要设置进程锁
from multiprocessing import Process
from multiprocessing import Array
from multiprocessing import RLock, Lock, Event, Condition, Semaphore
import time
def func(i,lis,lc):
    lc.acquire()
    lis[0] = lis[0] - 1
    time.sleep(1)
    print('say hi', lis[0])
    lc.release()
if __name__ == "__main__":
    array = Array('i', 1)
    array[0] = 5
    lock = RLock()
    for i in range(5):
        p = Process(target=func, args=(i, array, lock))
        p.start()

#执行结果:
'''
say hi 4
say hi 3
say hi 2
say hi 1
say hi 0
'''

多线程:

  • 线程的内存空间是共享的,每个线程都共享同一个进程的资源,但数据量大时容易引发数据混乱
  • xxx = threading.Thread()创建子线程,方法:
    • target():子线程任务
    • args():线程的说明(元组)
    • xxx.start():启动子线程
    • xxx.join():让主线程等待子线程结束之后主线程再结束,参数timeout=主线程的等待时间(单位s)
import threading,time
def run(num):
    print("子线程%s开始..."%(threading.current_thread().name))
    time.sleep(2)
    print(num)
    time.sleep(2)
    print("子线程%s结束..."%(threading.current_thread().name))
if __name__ == '__main__':
    print("主线程%s开始..."%(threading.current_thread().name))
    # 创建子线程
    t = threading.Thread(target=run,args=(1,),name='runThread')
    t.start()
    t.join()
    print("主线程%s结束..."%(threading.current_thread().name))

# 执行结果:
'''
主线程MainThread开始...
子线程runThread开始...
1
子线程runThread结束...
主线程MainThread结束...
'''
  • 多线程另一种调用方法 -> 继承线程类
from Thread import threading
class MyThread(Thread):
    # run()是固定的,当线程被执行的时候,被执行的就是run()
    def run(self):
        for i in range(1000):
            print("子线程:", i)
if __name__ == '__main__':
    t.MyThread()
    # t.run() -> 调用该方法为单线程
    t.start() # 启动子线程
    for i in range(1000):
        print("主线程", i)

线程锁:

  • xxx = threading.Lock()创建互斥锁,用于避免数据混乱(一个线程执行完毕才开始执行下一个线程),但会影响多线程的并发执行,从而效率会大大降低
    • lock.acquire(): 加锁
    • lock.release(): 解锁
    • with lock:和文件操作相同,执行完自动解锁
import threading
# 创建锁对象
lock = threading.Lock()
num = 0
def run(n):
    global num
    for i in range(1000000):
        # 调用锁对象
        with lock:
            num += n
            num -= n
if __name__ == '__main__':
    t1 = threading.Thread(target=run,args=(6,))
    t2 = threading.Thread(target=run,args=(9,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("num = ",num)

# 执行结果:
'''
num =  0
'''

生产者消费者模式:

  • 先进先出的数据结构,即队列
import time,queue,threading
q = queue.Queue(10)
def product(i):
    while True:
        time.sleep(2)
        print("厨师%s 做了一个包子!" % i)
        q.put("厨师%s 做的包子!" % i)
def consume(j):
    while True:
        time.sleep(1)
        print("顾客%s 吃了一个%s !" % (j, q.get()))
for i in range(3):
    a = threading.Thread(target=product, args=(i, ))
    a.start()
for j in range(10):
    b = threading.Thread(target=consume, args=(j, ))
    b.start()

信号量:

  • xxx = threading.Semaphore(x)同时启用x个多线程同时执行
import threading,time
# 创建2个多线程同时执行
sem = threading.Semaphore(2)
def run():
    with sem:
        print("%s--开始..."%(threading.current_thread().name))
        time.sleep(1)
        print("%s--结束..." % (threading.current_thread().name))
if __name__ == '__main__':
    for i in range(5):
        t = threading.Thread(target=run)
        t.start()

# 执行结果:
'''
Thread-1--开始...
Thread-2--开始...
Thread-1--结束...
Thread-2--结束...
Thread-3--开始...
Thread-4--开始...
Thread-3--结束...
Thread-4--结束...
Thread-5--开始...
Thread-5--结束...
'''

线程池:

  • 一次性开辟一些线程。我们用户直接给线程池子提交任务。线程任务的调度交给线程池来完成
from concurrent.futures import ThreadPoolExecutor
def fun(name):
    for i in range(1000):
        print(name,i)
if __name__ == '__main__':
    # 创建线程池
    with ThreadPoolExecutor(50) as t:
        for i in range(100):
            t.submit(fun, name=f'线程{
      
      i}')
    print("线程任务执行完毕...")
  • 限定创建一定数量的线程
import threading,queue,time
class MyThreadPool:
    # 一次限制最多2个线程
    def __init__(self,maxsize=2):
        self.maxsize = maxsize
        self.__pool = queue.Queue(maxsize)
        for _ in range(maxsize):
            self.__pool.put(threading.Thread)
    def get_thread(self):
        return self.__pool.get()
    def add_thread(self):
        self.__pool.put(threading.Thread)

def task(i,pool):
    print("执行任务...", i)
    time.sleep(1)
    # 一个线程结束后再添加一个线程
    pool.add_thread()

if __name__ == '__main__':
    pool = MyThreadPool()
    # 假如执行6个任务
    for i in range(1,6):
        obj = pool.get_thread()
        t = obj(target=task, args=(i, pool))
        t.start()

# 执行结果:
'''
执行任务... 1
执行任务... 2
执行任务... 3
执行任务... 4
执行任务... 5
执行任务... 6
'''

异步&协程:

  • 协程的切换不同于线程切换,是由程序自身控制的,没有切换的开销。协程不需要多线程的锁机制,因为都是在同一个线程中运行,所以没有同时访问数据的问题,执行效率比多线程高很多。
  • 当程序遇见了IO操作的时候,可以选择性的切换到其他任务上.
  • Python3.8之后废弃装饰器写法,而是以async(异步)和await(等待)代替
  • 协程的四种状态:
    • GEN_CREATED:  等待开始执行。
    • GEN_RUNNING:  协程正在执行。
    • GEN_SUSPENDED: 在yield表达式处暂停。
    • GEN_CLOSED:   执行结束。
import asyncio,time
async def fun1():
    print("我是aaa")
    await asyncio.sleep(3)
    print("我是aaa")
async def fun2():
    print("我是bbb")
    await asyncio.sleep(2)
    print("我是bbb")
async def fun3():
    print("我是ccc")
    await asyncio.sleep(4)
    print("我是ccc")
async def main():
    tasks = [
        asyncio.create_task(fun1()),
        asyncio.create_task(fun2()),
        asyncio.create_task(fun3()),
    ]
    await asyncio.wait(tasks)
if __name__ == '__main__':
    t1 = time.time()
    asyncio.run(main())
    t2 = time.time()
    print("耗时:",t2-t1)

# 执行结果:
'''
我是bbb
我是aaa
我是ccc
我是bbb
我是aaa
我是ccc
耗时: 4.018770217895508
'''
  • 协程实例:
import asyncio
import datetime
async def display_date(num, loop):
    end_time = loop.time() + 10.0
    while True:
        print("Loop: {} Time: {}".format(num, datetime.datetime.now()))
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(2)  # 阻塞直到协程sleep(2)返回结果
if __name__ == '__main__':
    loop = asyncio.get_event_loop()  # 获取一个event_loop
    tasks = [display_date(1, loop), display_date(2, loop)]
    loop.run_until_complete(asyncio.gather(*tasks))  # “阻塞"直到所有的tasks完成
    loop.close()

# 执行结果:
'''
Loop: 1 Time: 2021-10-24 13:46:47.247362
Loop: 2 Time: 2021-10-24 13:46:47.248363
Loop: 1 Time: 2021-10-24 13:46:49.252192
Loop: 2 Time: 2021-10-24 13:46:49.252192
'''

第二章:命令行参数

获取命令行参数:

  • sys.argv: 获取输入的参数列表
import sys
print("参数个数为:",len(sys.argv),"个参数.")
print("参数列表为:",str(sys.argv))

argparse模块:

  • argparse 模块是 Python 内置的一个用于命令项选项与参数解析的模块,可以让人轻松编写用户友好的命令行接口。
  • 通过在程序中定义好我们需要的参数,然后 argparse 将会从 sys.argv 解析出这些参数。
  • argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。
  • 必须在命令行内执行,python xxx.py 参数...
  • xxx = argparse.ArgumentParser()创建解释器对象,参数列表:
    • prog: 程序的名称(默认值:sys.argv[0])
    • usage: 描述程序的用途
    • description: help信息前显示的信息
    • epilog: help信息后显示的信息
    • 实例:
import argparse
parser = argparse.ArgumentParser(prog='程序的名称',usage='程序的用途',description='help信息前显示的信息',epilog='help信息后显示的信息')

add_argument:

  • xxx.add_argument()添加参数,参数列表:
    • metaver: 帮助信息中显示的参数名称
    • const: 保存一个常量
    • default: 默认值
    • type: 参数类型,默认str
    • choices: 设置参数值的范围,如果参数不是参数串,要设置type类型
    • required: 是否必选,默认True
    • dest: 参数名
    • 实例:
# 添加必选参数(位置参数)
parser.add_argument('name',type=str,help='请输入你的名字')
parser.add_argument('age',type=int,help='请输入你的年龄')
# 添加可选参数
parser.add_argument('-s','--sex',default='男',choices=['男','女'],type=str,help='请输入你的性别')
  • 实例:
# 模仿MySQL命令行登陆
import argparse
#创建一个解释器对象
parser = argparse.ArgumentParser(prog='系统登录',usage='%(prog)s [otions] usage',
                                 description='系统自定义的命令行文件',epilog='my - epilog')
#添加必选参数
parser.add_argument('loginType',type=str,help='登陆MySQL账户')
#添加可选参数
parser.add_argument('-u',dest='user',type=str,help='你的用户名')
parser.add_argument('-p',dest='password',type=str,help='你的密码')
#执行解析参数
result = parser.parse_args()

if (result.user == 'root' and result.password == '123456'):
    print('login sucess!')
else:
    print('login fail!')

第三章:正则表达式

re.match():

  • re.match(r'a',xxx,参数)仅匹配xxx中以a开头的字符串,匹配成功返回匹配的对象,反则返回None
    • 使用xxx.group()匹配成功返回该字符,失败则报错
    • 参数re.I忽略大小写
    • 参数re.M多行匹配
    • 参数re.S让.可以匹配换行符
import re
data = "Aagsdfh"
result = re.match(r'a',data,re.I | re.M) #精确匹配
print(type(result))
print(result.group())

#执行结果:
'''
<class 're.Match'>
A
'''

re.search():

  • re.search(r'a',xxx)用于匹配axxx第一次出现的位置,匹配成功返回匹配的对象,反则返回None
import re
data = "vAagasdfh"
result = re.search(r'a',data) #精确匹配
print(result.group())

#执行结果:
'''
a
'''

re.findall():

  • 用于在字符串中找到所匹配的所有子串,并以list列表结构返回,反则返回空列表
  • matchsearch是匹配一次,findall匹配所有
import re
data = "<title>xxx</title><body>我是主体</body>"
result = re.compile(r'<.*?>')
print(result.findall(data))

#执行结果:
'''
['<title>', '</title>', '<body>', '</body>']
'''

re.finditer():

  • 用于在字符串中找到所匹配的所有子串,但返回的结构是迭代器,所以效率要高于re.findall()
import re
data = re.finditer(r"\d+", "我的电话是12345,而不是54321")
for i in data:
    print(i.group())

#执行结果:
'''
12345
54321
'''

re.compile():

  • 用于预加载正则表达式,生成一个正则表达式对象,供match()search()findall()finditer()函数使用
import re
data = r'atabac'
res = re.compile(r'a')
result1 = res.match(data)
print(result1.group())
result2 = res.search(data,2)
print(result2.group())
result3 = res.findall(data)
print(result3)
result4 = res.finditer(data)
for i in result4:
    print(i.group())

#执行结果:
'''
a
a
['a', 'a', 'a']
a
a
a
'''

常用匹配模式:

  • 普通字符:
    • .匹配除换行符外的一个字符
    • ^匹配字符串的开头
    • $ 匹配字符串的结尾
    • |相当于逻辑or
    • *匹配出现次数(包含零次)的一个字符
    • +匹配出现次数(至少一次)的一个字符
    • ?匹配出现0-1次的一个字符
    • {x,y}匹配指定出现x-y次数的一个字符
    • [abc]匹配abc中任意一个字符
    • [^abc]匹配不包含abc中的一个字符
  • 特殊字符(元字符):
    • \d匹配数字
    • \D匹配非数字
    • s匹配空白,即匹配\f\n\r\t\v
    • S匹配非空白,即匹配\f\n\r\t\v之外的
    • w匹配单词字符,即a-zA-Z0-9
    • W匹配非单词字符

贪婪模式:

  • 正则默认匹配就是贪婪模式,也就是默认去更多的匹配符合规则的数据
import re
data = "<title>我是标题</title><body>我是主体</body>"
result = re.compile(r'<.*>')
print(result.findall(data))

#执行结果:
'''
['<title>我是标题</title><body>我是主体</body>']
'''

非贪婪模式:

  • 和贪婪模式正好相反,也就是默认去更少的匹配符合规则的数据,即在筛选条件中加上?
import re
data = "<title>我是标题</title><body>我是主体</body>"
result = re.compile(r'<.*?>')
print(result.findall(data))

#执行结果:
'''
['<title>', '</title>', '<body>', '</body>']
'''

提取内容:

  • (?P<xxx>正则式),用于将正则式提取出来的值赋给xxxxxx为自定义的变量名
import re
data = """
<title>我是标题1</title><body>我是主体1</body>
<title>我是标题2</title><body>我是主体2</body>
"""
res = re.compile(r"<title>(?P<a>.*?)</title><body>(?P<b>.*?)</body>", re.S)
obj = res.finditer(data)
for i in obj:
    print(i.group("a"))
    print(i.group("b"))

#执行结果:
'''
我是标题1
我是主体1
我是标题2
我是主体2
'''

第四章:操作数据库

操作MySQL数据库:

  • 需要安装pymysql模块 -> pip install pymysql
  • xxx = pymysql.connect()连接数据库,参数:
    • host: 数据库IP地址
    • user: 数据库账号
    • password: 数据库密码
    • database: 要连接的数据库名字
    • charset: 字符编码
  • yyy = xxx.cursor(): 创建游标对象
  • yyy.execute(): 执行SQL语句
  • yyy.fetchall(): 获取全部数据
  • yyy.fetchone():获取单条数据
  • yyy.rollback():数据回滚
import pymysql
# 创建数据库连接
con = pymysql.connect(host='localhost',user='root',password='123456',database='people',charset='utf8')
# 创建一个游标对象,利用该对象进行数据库操作
try:
    cur = con.cursor()
    # 执行SQL语句
    cur.execute('select * from account')
    result = cur.fetchall()
    for item in result:
        print(item)
    print("sucess!")
except Exception as ex:
    print(ex)
finally:
    cur.close()
    con.close()

#执行结果:
'''
('1', '张三', '男', '河南汝州市', '[email protected]')
('2', '李四', '女', '河南商丘市', '[email protected]')
sucess!
'''

第五章:网络编程

服务端搭建:

  • 导入socket模块 -> 套接字
    • import socket
  • 创建socket类对象
    • xxx = socket.socket(family,type)
      • 参数family:
        • socket.AF_INET: IPV4传输
        • socket.AF_INET6: IPV6传输
        • socket.AF_UNIX: UNIX传输
      • 参数type:
        • socket.SOCK_STREAM: TCP协议
        • socket.SOCK_DGRAM: UDP协议
  • 绑定IP地址端口(元祖)
    • xxx.bind(('IP地址',端口))
  • 设置最大监听数
    • xxx.listen(x)
# 服务端
import socket #导入模块
# 创建 socket 对象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #采用TCP协议
# sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #采用UDP协议
# 绑定端口和IP IP 如果为空的话,表示绑定所有IP
sock.bind(("127.0.0.1",8001))
# 设置监听
sock.listen(3)
print("服务已启动...")
result = True
while result == True:
    # con接收sock对象,add接收IP和端口号
    con,add = sock.accept()
    # print(con)
    # print(add)
    print("%s 已连接成功..."%add[0])
    while True:
        recvs = con.recv(512)
        print(recvs.decode("utf-8"))
        if recvs.decode("utf-8") == "break":
            break
        sends = input("请输入要发送给客户端的消息:")
        con.send(sends.encode("utf-8"))
        # con.sendto(sends.encode("utf-8"),("127.0.0.1",8001)) #UDP协议写法
        if sends == "break":
            result = False
            break
sock.close()

客户端搭建:

  • 参数模块和服务器都相同
# 客户端
import socket #导入模块
# 必须和服务端的协议保持一致
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #采用TCP协议
# sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #采用UDP协议
# 连接服务器
sock.connect(("127.0.0.1", 8001))
while True:
    # 发送消息
    sends = input("请输入要发送给服务端的消息:")
    sock.send(sends.encode("utf-8"))
    if sends == "break":
        break
    # 接收消息,recv()设置最大接收数据(单位bit)
    recvs = sock.recv(512)
    print(recvs.decode("utf-8"))
    # con.sendto(sends.encode("utf-8"),("127.0.0.1",8001)) #UDP协议写法
    if recvs.decode("utf-8") == "break":
        break
sock.close()

第六章:JSON

Json基本方法:

  • Json是一种表示数据的语法格式,当前被Web API接口广泛采用。
  • json.loads():将json数据转换为dict字典
  • json.dumps():将dict字典转化为json数据
  • 写入json文件时
    • 使用indent=1可使内容换行
    • 使用ensure_ascii=False避免乱码
    • 例如:json.dumps(字典, indent=1, ensure_ascii=False)
  • Json基本格式:
{
    
    
    "one":1,
    "two":2,
    "three":[
        {
    
    
            "four":4,
            "five":5
        },
        {
    
    
            "six":6,
            "seven":7
        }
    ]
}

猜你喜欢

转载自blog.csdn.net/qq_44091819/article/details/121451404