Python入门

一、变量和输出

def main():  
      
      在这里编程
      
    pass  
  
  
if __name__ == '__main__':  
    main()
def main():  
  
    # 1.变量  
    a = 1  
    b = "haha ni ye hao"  
    c = b  
    #print(a)  
    #print(b)    #print(c)  
    # 2.注释  
    #单行注释  
  
    '''  
    多行注释  
    '''  
    # 3.拼接  
    #name = input("请输入你的姓名:")  
    #print("欢迎",name)  
    #print("欢迎" + name + "过来")  
    #print("haha nihao")  
  
    '''   
    4.布尔型  
    true = 1    false = 0    '''    #d = True  
    #print(d)  
    #格式化输出  
    name = input("姓名:")  
    age = input("年龄:")  
    job = input("工作:")  
  
    info = "name is %s ! age is %s ! job is %s"%(name,age,job)  
    print(info)  
  
  
  
    pass  
  
if __name__ == '__main__':  
    main()

二、运算符

'''  
运算符  
+ - * / %  **  
!= < >  
==  
> < >= <=  
'''  
  
  
''' a = 4  
#a += 1 # a = a+1  
b = 2  
c = a % b  
print(c)  
'''  
  
#成员运算符  
a = 'abc'  
b = 'fiosejfapoksaopfkengabcfpjoweaabcoo[afke'  
print(a in b)

三、流程控制

input 进来的东西都是字符串!!!
利用 int 强制转换成数字

# if语句  
"""  
age = 17  
if age > 18:  
    print("成年了")  
elif age < 16:  
    print("aaa")else:  
    print("还没有")  
 """  
# while语句  
"""  
print("小游戏开始")  
num = 101  
  
while True:  
    guess = int(input("你猜猜数字是啥:"))  #input里面的都是字符串!  
    if guess < num:        print("哈哈 小了")  
    elif guess > num:        print("哈哈 大了")  
    else:        print("答对了")  
        break """

四、字符串切片

计算机大多数情况计算从0开始

#字符串切片  
"""  
a = "abcdefghijklmn"  
print(a[0:3])#从第0个开始取3个  
print(a[2:])#从第2个开始,到最后  
print(a[2:-1])#从第2个开始,取 到! 倒数第一个之前  
print(a[1:10:2])#从第1个开始取到直到第十个,步长为2  
"""

五、常用字符串处理方法

"""  
a = "aABCabc123haha!"  
b = "haha nihao wo ye hao"  
c = "**ha**ha**"  
d = "192.168.1.2"  
# 1.capitalize()首字母大写,其他自动小写  
print(a.capitalize())  
  
# 2.swapcase()大小写反转  
print(a.swapcase())  
  
# 3.title()每个单词首字母大写  
print(b.title())  
  
# 4.center 变量居中,用8个位置,空的位置用*代替  
print(c.center(8,"*"))  
  
# 5.startswith() 判断以什么开头  
print(c.startswith("h"))  
#从计算机的第五个(人类第6个)取到人类的第7个是不是ni  
print(b.startswith("ni",5,7))  
  
# 6.endswith() 判断以什么结尾  
print(b.endswith("ao",18,20))  
  
# 7.发现ih的i在计算机的第几个  
print(b.find("ih"))  
  
# 8.replace() 替换,前两个a替换为N  
print(a.replace('a','N',2))  
  
# 9.isalpha() 判断字符串中是否都是字母  
print(c.isalpha())  
  
# 10.isnumberic() 判断字符串中是否是纯数字  
print(a.isnumeric())  
  
# 11.strip() 只能去掉左右的*,中间去不掉  
    #lstrip() 去掉左边的  
    #rstrip() 去掉右边的  
  
print(c.strip('*'))  
  
# 12.split 以 . 的形式分割,分割结果是列表  
print(d.split('.'))  
"""

六、列表 [ ]

如何去重:
列表→集合
集合→列表

"""  
# 列表 [ ]
li = ['xiaoming','xiaoli','xiaohong']  
# 1.访问  
print(li[2])  
  
# 2.插入  
li.insert(1,'haha')  
print(li)  
  
# 3.插入到最后  
li.append('nihao')  
print(li)  
  
# 4.删除最后一个  
li.pop()  
print(li)  
  
# 5.批量删除  
del li[1:3]  
print(li)  
  
# 6.精确删除  
li.remove('xiaoming')  
print(li)  
  
# 7.修改  
li[0] = 'wobuzhidao'  
print(li)  
  
# 8.删除所有  
li.clear()  
print(li)  
  
zz = [1,2,3,4,2,5,6,2,7,8]  
  
# 9.计算2出现的次数  
ret = zz.count(2)  
print(ret)  
  
# 10.计算 5 第一次出现的位置  
net = zz.index(5)  
print(net)  
"""

七、字典 { }

字典是无序的,而且是以 键值对 来记录数据

"""  
#字典 { }dic = {"name":"xiaoming","age":"18","job":"driver"}  
  
# 1.增加数据  
dic["home"] = "xuanwuqu"  
print(dic)  
  
# 2.删除  
dic.pop("age")  
print(dic)  
  
# 3.修改  
dic["job"] = "lose"  
print(dic)  
  
# 4.查  
value = dic["name"]  
print(value)  
  
  
value2 = dic.get("a","xxxxxx")# 查找a,如果查不到就返回xxxxxx  
print(value2)  
  
# 遍历字典的内容  
for key,value in dic.items():  
    print(key + "--------" + value)  
# 只遍历键值对里的键  
for i in dic:  
    print(i)  
# 只遍历键值对中的值  
for j in dic:  
    print(dic[j])  
print(dic.keys())  
print(dic.values())  
"""

八、集合 { }

{ }
无序,但是不允许重复

 """  
 #集合  
 set1 = {1,2,8,9,3,4,5,6,5,7,2,1} set2 = {7,8,1,9,1,9,8,7} print(set1)  
 # 1.增  
 set1.add('aaa')  
 # 2.删除  
 set1.remove(3)#删除3这个值,并且自动排序  
 print(set1)  
 # 3.随机删除  
 set1.pop()# set1.clear() #删除所有  
  
 # 4.取交集  
 print(set1 & set2)  
 # 5.取并集  
 print(set1 | set2)  
 # 6.取差集  
 print(set1 - set2)  
 # 7.取反交集  
 print(set1 ^ set2) """

九、元祖 ( )

( )
tuple
无法改变 没有增,删,改

"""  
#元祖 tuple  
x = ['l1','l2','l3','l2','l4']  
y = ("haha1","haha2","haha3")  
#print(y)  
  
# 列表 → 元祖  
x1 = tuple(x) # 对数据的保护,防止别人修改  
print(x1)  
  
# 列表 → 集合  
x2 = set(x) #对数据去重  
print(x2)  
  
# 元祖 → 列表  
y1 = list(y)  
print(y1)  
"""

十、文件操作

r – 读
w – 写
a – 追加

r+ w+ a+ 基于字符的读写

对于二进制的读写
rb wb ab

文件的本指 – 句柄(唯一标识符)

10.1 读操作

读写文件基本操作

"""    
#f就是句柄  
f = open("./a.txt","r") #若对f操作,即对a.txt操作  
print(f)  
  
#从句柄中读取内容  
data = f.read()  
print(data)  
  
#关闭文件句柄  
f.close()  
"""
import os


f = open("./a.txt", "r")  
  
"""  
#判断文件是否存在  
print(os.path.isfile("D:/ObsidianNotes/Python/a.txt"))  
print(os.path.isfile("./a.txt"))  
  
#一行一行读  
data = f.readline()  
print(data)  
#读取每一行,并且保存 每一行 为列表(\n换行符也读出)  
data1 = f.readlines()  
print(data1)  
"""  
  
while True:  
    info = f.readline(4) # 每次读取4个字  
    print(info)  
    if len(info) == 0: # 什么时候读不出来了  
        break

10.2 写操作

f = open("./a.txt", "w")  
  
# 写入的内容,原来内容会被清空  
# 如果文件不存在,则会自动创建  
f.write("wobuhao")

10.3 追加操作

f = open("./a.txt", "a")  
# 追加内容  
f.write("heiheihei")  
  
f.close()

10.4 免关闭

# 免关闭文件操作  
with open("./a.txt","a") as f:  
    f.write(">>>>>????")  
  
with open("./a.txt","r") as f:  
    print(f.read())

同时操作两个文件

with open("./a.txt","r") as f1,open("./b.txt","a") as f2:  
    data = f1.read()  
    data = data.replace('a','N')  
    f2.write(data)

十一、操作系统命令

import os

#创建文件夹  
os.mkdir("c:/abcd")  
#删除文件夹  
os.rmdir("c:/abcd")  
#列出文件夹的内容  
print(os.listdir("c:/dell"))  
  
#执行操作系统的命令  
os.system("whoami")  
os.system("ipconfig")  
print(os.system("mkdir 123"))

十二、函数介绍

12.1 无返回值

# 有返回值的函数  
def my_len():  
  
    s = 'haha nihao'  
    length = 0  
    for i in s :  
        length += 1  
    print(length)  
  
  
  
  
  
def main():  
    my_len()

12.2 有返回值

# 有返回值的函数  
def my_len():  
  
    s = 'haha nihao'  
    length = 0  
    for i in s :  
        length += 1  
    return length  
  
  
  
  
  
def main():  
    a = my_len()  
    print(a)  
  
    pass

12.3 有参数

# 有参数的函数  
def maxnum(x,y):  
    if x > y:  
        the_max = x  
    else:  
        the_max = y  
    return the_max  
  
  
def main():  
    a = maxnum(10 ,59)  
    print(a)

12.4默认参数

# 默认参数的函数  
def maxnum(x,y=20):  
    if x > y:  
        the_max = x  
    else:  
        the_max = y  
    return the_max  
  
  
def main():  
    a = maxnum(10 ,59)  
    print(a)  
  
    pass

12.5 匿名函数

#匿名函qqqqqqq数  
x = lambda y,z:y+z  
print(x(2,3))

12.6 函数名的写法

函数名里面是一个内存地址
<function fun1 at 0x00000237852EE040>
有这个内存地址的任,加个 () 就可以运行了

def fun1():  
    print("i am fun1")  
    pass  
  
def main():  
    f = fun1 #fun1的内存地址  
    print(fun1)  
    print(f)  
  
    f()
def f1():  
    print("i am fun1")  
    pass  
def f2():  
    print("i am fun2")  
    pass  
def f3():  
    print("i am fun3")  
    pass  
def main():  
    li = [f1,f2,f3]  
    dic = {"hanshu1":f1,"hanshu2":f2,"hanshu3":f3}  
    li[0]()  
      
    dic["hanshu3"]()

十三、函数各种参数类型

13.1 默认参数

默认参数是一个可变数据类型

    #默认参数是可变参数  
def demo(a,li=[]):  
    li.append(a)  
    print(li)  
  
def main():  
    demo('abc')  
    demo('cde')

13.2 不定参数

列表穿参数,但是最后会转换成元祖

    # 不定参数  
def fun1(name,age,*args):  
    print("name is:",name)  
    print("age is:",age)  
    print("args is:",args)  
    print("other is:",args[0])  
    print("other is:",args[1])  
  
    pass  
  
def main():  
    y = ['a', 'b', 'c', 'd']  
    t = ('a','b','c','d')   # 通过元祖或列表加个*,需要前面加*  
    fun1(*y) # 列表穿参数,但是最后会转换成元祖  
    print("----------------")  
    fun1(*t)  
    print("----------------")  
    fun1('a','b','c','d')  
    #print(*(1,2,3,4))  
    #print((1,2,3,4))    pass

13.3 字典参数

    # 传字典参数  
def fun2(**dic):  
    print(dic)  
    pass  
  
def main():  
    dic1 ={"name" : "xiaoming","age" : 12 }  
    fun2(**dic1)  
    pass

13.4 多种参数

*args元祖,用于非关键字参数
**kwargs字典,用于关键字参数

    #多种参数传递  
def fun1(a,b,*args,**kwargs):  
    print(a)  
    print(b)  
    print(args)  
    print(kwargs)  
  
def main():  
    fun1(1,2,3,4,5,name="n1",job="n2")

十四、作用域

14.1 locals()

locals()
本地(本函数)定义的所有变量都会以字典的形式存在这里

14.2 globals()

globals()
在外部定义的所有变量都会以字典的形式存在这里
全局变量在用之前,需要声明

# 全局变量  
c = 100  
  
def fun1():  
    # 声明要使用全局变量  
    global c  
    c = c+ 2  
    print(c)  
    pass  
  
  
def main():  
    fun1()

但是列表、字典以及集合直接用,不用声明

li = [1,2,3]  
dic = {"name":"xiaoming","age":"18"}  
  
def fun1():  
    li.append(99)  
    print(li)  
    print(dic)  
  
  
  
def main():  
    fun1()

14.3 仅使用上一层变量⭐⭐⭐

def add_b():  
    b = 1  
  
    def do_global():  
        b = 10  #b=30  
  
        def dd_nonlocal():  
            #使用上一层的b,上一层b以及做了修改  
            nonlocal b #b=10  
            b = b+20 #b=30  
            print(b)  
            pass  
        pass        dd_nonlocal()  
        print(b)  
        pass  
    do_global()  
    print(b)  
  
    pass  
  
def main():  
    add_b()

14.4 函数的嵌套

# 函数的嵌套  
def mymax(x,y):  
    m = x if x > y else y  
    return m  
  
def maxmax(a,b,c,d):  
    res1 = mymax(a,b)  
    res2 = mymax(res1,c)  
    res3 = mymax(res2,d)  
    return res3  
  
def main():  
    ret = maxmax(23,156,78,200)  
    print(ret)

十五、闭包

分为两层,外函数和内函数
闭包可以直接调用外层参数和变量

15.1 闭包基础

# 外函数  
def outer(a):  
    b = 10  
    # 内函数  
    def inner():  
        print(a+b)  
    #外函数返回值是内函数的引用(内存地址)  
    print(inner.__closure__)    # 判断inner是否是闭包,如果是,就返回cell,如果不是就返回none  
    return inner  
def main():  
  
    a = outer(15)  
    #print(a)  
    a()  
  
    #b = outer(17)  
    #b()
def wrapper():  
    money = 1000  
    def func():  
        name = "apple"  
  
        def inner():  
            print(name,money)  
  
        return inner  
      
    return func  
  
  
def main():  
    f  = wrapper()# 此时f应该是func的内存地址  
    i = f() #此时的i应该是inner的内存地址  
    i()

15.2 闭包传参

# 闭包传参  
def func(a,b):  
  
    def inner(x):  
        return a*x+b  
  
    return inner  
  
  
def main():  
  
    f = func(4,5) # f是inner的内存地址,并且此时这个inner里面4*x+5,等待传输x  
    print(f(2))
import time  
  
def fun1():  
  
    time.sleep(3)  
    print("i am fun1")  
  
  
def timer(fun):  
  
    def inner():  
        start = time.time()# 获取开始时间  
        fun()  
        print(time.time() - start)#结束时间-开始时间  
  
    return inner  
  
def main():  
  
    a = timer(fun1)  
    a()  
    pass

15.3 装饰器

15.3.1 带参数

import time  
  
# 带参数的装饰器  
def timer(fun):  
    def inner(a):   #闭包函数需要携带参数  
        start = time.time()  
        fun(a)  #执行的时候也要携带参数  
        end = time.time()  
        print(end - start)  
  
  
    return inner  
  
# 装饰器,在运行装饰器装饰的函数 (fun1) 的时候,会把目标函数(fun1)放到装饰器(timer)里运行  
@timer  
def fun1(a):  
    time.sleep(a)  
    print('hello world')  
  
def main():  
  
    fun1(5)

15.3.2 带多种参数

import time  
  
# 包含多种参数的装饰器  
def timer(func):  
  
    def inner(*args,**kwargs):  
        func(args,kwargs)  
    return inner  
  
@timer  
def func(*args,**kwargs):  
    print(args,**kwargs)  
  
  
def main():  
  
    func('a','b',123,124,name="haha1",age="18")  
  
    pass

15.3.3 额外知识

def func():  
    '''  
    我是注释的内容  
    '''    print("i am fun1")  
  
  
  
  
def main():  
  
    print(func.__doc__) #打印函数中的注释内容  
    print(func.__name__)#打印函数名

15.3.4 装饰器传参

def outer(flag):  
    def timer(func):  
        def inner(a):  
            if flag:  
                print("函数开始执行")  
                func(a)  
                print("函数执行结束")  
            else:  
                print("请开启flag")  
        return inner  
    return timer  
  
@outer(True)    # flag = True  
def func1(a):  
    print("haha---",a)  
  
def main():  
    func1("haha nihao")

15.3.5 多个装饰器

# 多个装饰器,注意多个装饰器的启动和结束规律:  
# 1开始 2开始 运行 2结束 1结束  
# 关于函数自身运行对称  
def wrapper1(func):  
    def inner():  
        print("装饰器1号启动")  
        func()  
        print("装饰器1号结束")  
    return inner  
  
def wrapper2(func):  
    def inner():  
        print("装饰器2号启动")  
        func()  
        print("装饰器2号结束")  
    return inner  
  
@wrapper1  
@wrapper2  
def func1():  
    print("haha")

十六、迭代器

16.1 手工迭代

li = [1,2,3,4,5]  
#开始使用迭代器迭代  
li_iter = li.__iter__()  
#迭代一个,手工迭代  
item1 = li_iter.__next__()  
print(item1)  
  
item2 = li_iter.__next__()  
print(item2)  
  
item3 = li_iter.__next__()  
print(item3)  
  
item4 = li_iter.__next__()  
print(item4)  
  
item5 = li_iter.__next__()  
print(item5)  
  
#没有东西可以迭代,所以报错  
item6 = li_iter.__next__()  
print(item6)

16.2 自动迭代

def main():  
    li = [1,2,3,4,5]  
    li_iter = li.__iter__()  
    #自动迭代  
    while True:  
        try:# 捕获异常,如果try里的东西出现异常,就直接执行except的内容  
            item = li_iter.__next__()  
            print(item)  
        except:  
            print("迭代结束")  
            break

十七 、生成器

主函数通过next去控制,
几个next就到几个yield
每一个yield就返回一个东西

17.1 手动生成器

yield 和 next 搭配 也可以是send()

# 生成器  
  
def gen_func1():  
    a = 1  
    print("将a赋值")  
    yield a # 中断函数 并且return a,等待下一个next才会继续执行  
    b = 2  
    print("将b赋值")  
    yield b  
  
  
  
def main():  
    g1 = gen_func1()  
    print(next(g1))  
    time.sleep(2)  
    print(next(g1))

17.2 自动生成器

17.2.1 方法一

#自动生成  
def produce():  
    for i in range(100):  
        yield "生产了%s个包子"%(1+i)  
  
def main():  
    p = produce()  
    num = 0  
    for i in p:#此时p.__next__()就是i  
        print(i)#相当于调用了yield  
        num += 1  
        if num == 12:  
            break

17.2.2 方法二

#自动生成  
def produce():  
    for i in range(100):  
        yield "生产了%s个包子"%(1+i)  
  
def main():  
    p = produce()  
    num = 0  
    for i in range(12):  
        print(p.__next__()) #相当于调用yield

17.3 yield传入参数

# yield 传入参数  
def gen():  
    print(123)  
    content = yield 1 # 中断,return 1,外边send内容给content  
    print("========",content)  
    print(456)  
    yield 2  
  
  
  
def main():  
    g = gen() # 拿到生成器,才可以去控制  
    ret1 = g.__next__() # ret1 = 1  
    print("第一个yield返回",ret1)  
    ret2 = g.send("haha i am coming") # 传入参数 给第一个yield发东西,发完自动执行next  
    print("第二个yield返回",ret2)

十八、推导式

用一句话来表达

18.1 列表推导式

#列表推导式  
#列表里的数据都是i,i的范围是0~30,如果i整除3是0,则加入列表  
mul = [ i for i in range(30) if i%3 is 0]  
print(mul)
fruits = [['apple','banana','orange','almond','date','coconut'],['fig','hazel','grape','haw','greengage']]  
#找到嵌套列表中包含2个a字母的水果的名字  
# 一个大列表fruits 有两个小列表 lstprint([name for lst in fruits for name in lst if name.count('a')>=2])

18.2 函数列表推导式

def squared(x):  
    return x*x  
def main():  
    mul = [ squared(i) for i in range(30) if i%3 is 0]  
    print(mul)

结果
[0, 9, 36, 81, 144, 225, 324, 441, 576, 729]

18.3 字典推导式

键值对调换

dic1 = {'a':1,'b':2}  
dic2 = {dic1[k]:k for k in dic1}  
  
"""  
 k    dic[k]
'a'     1  
'b'     2  
"""  
  
print(dic2)

18.4 集合推导式

li = [1,2,3,4,-1,-2]  
s = {x**2 for x in li}  
print(s)

十九、执行函数

19.1 eval

eval 执行字符串所代表的代码,并且返回结果
eval函数十分危险!因为会把传入的字符串当作Python代码执行

#因为用 ' ' 包裹起来所以是字符串,所以不会当作程序来执行  
s = 'print("haha")'  
print(s)  
# 把s里面的字符串,当作python代码来执行  
eval(s)  
pass

19.1 exec

exec 与eval同样危险

s = 'os.system("ipconfig")'  
exec(s)

二十、模块

每一个py文件都是一个模块
(对于py起的文件名,必须避开关键字)

20.1 导入全部模块

#import test123  #引入外部文件

def main():  
    #test123.func1() 如果用import test123
from test123 import *   #引入test123中的所有函数
def main():  
    func1()  
	func2()

20.2 导入部分模块

from test123 import func1   #如果只需要引入某个函数
def main():  
    func1() #直接调用

20.3 取别名

import test123 as nn    #给test123引入之后取一个别名,叫nn
def main():  
    nn.func1() #import test123 as nn

20.4 引用限制

__all__=['func1','func3']   #人家引用你的时候,最多只能用func1,func3  
  
  
def func1():  
    print("func1")  
def func2():  
    print("func2")  
def func3():  
    print("func3")

20.5 Python自带模块

20.5.1 json模块

import json  
def main():  
    #序列化  
    dic = {'k1':'v1','k2':'v2','k3':'v3'}  
    str = json.dumps(dic)   #将一个字典转化为字符串  
    print(type(dic))  
    print(type(str))  
  
    #反序列化  
    dic2 = json.loads(str)  
    print(type(dic2))

20.5.2 加密模块

hashlib模块(MD5)

import hashlib  
  
def main():  
  
    md5 = hashlib.md5() #使用md5对以后的数据进行摘要加密操作  
    md5.update('hahanihao'.encode('utf-8')) #对目标进行操作(对字符串加密之前要转为utf-8)  
    print(md5.hexdigest())  #结果就是字符串md5加密后的密文(十六进制)

20.5.3 配置文件

import configparser  
  
def main():  
  
    #初始化  
    conf = configparser.ConfigParser()  
    conf['default'] = {'money':100,'go':'yes','weapon':'no'}  
    conf['home'] = {'island':'xiaodao1'}  
    with open('./config','w') as f:  
        conf.write(f)   #配置文件的写入(固定的格式填入配置文件)

![[Pasted image 20260315110439.png]]

基本操作

import configparser  
  
def main():  
  
    #初始化  
    conf = configparser.ConfigParser()  
    conf.read('config') #读取配置文件  
    print('home' in conf)   #判断是否存在  
    #遍历所有的key  
    for key in conf['default']:  
        print(key)  
    #获取键对应的值  
    print(conf.get('default','money'))  #section 键  
    #获取所有的键值对                                   # option 条目  
    print(conf.items('default'))  
    #获取所有的键  
    print(conf.options('default'))  
    #增加键  
    conf.add_section('tank')  
    #删除键  
    conf.remove_section('home')  
    #删除条目  
    conf.remove_option('default','weapon')  
    #修改条目  
    conf.set('default','money','777')  
  
    conf.write(open('config.new','w'))

20.5.4 坐标系模块

from collections import namedtuple  #坐标系  
  
  
def main():  
    #定义一个名为point的坐标,坐标两个参数分别叫x,y  
    point = namedtuple('point',['x','y','z'])  
    p = point(7,8,9)  
    print(p.x,p.y,p.z)

20.5.5 时间模块

import time  
  
def main():  
    print("start")  
    time.sleep(2)  
    print("end")
import time  
  
def main():  
  
    #输出当前时间戳(从1970-1-1 0:0:0 一直到现在的秒数)  
    print(time.time())  
    #输出当前的24小时时间  
    print(time.strftime('%y-%m-%d %X'))  
    print(time.strftime('%y/%m/%d %H:%M'))

20.5.6 日期模块

import datetime  
import time  
  
def main():  
    sjc = time.time()  
    print(sjc)  
  
    #显示当前日期时间  
    now = datetime.datetime.now()  
    print(now)  
  
    #3周后的时间  
    print(datetime.datetime.now() + datetime.timedelta(weeks=3))  
  
    print(now.replace(year = 1977,month=1,day=1))  
  
    #时间戳转为当前时间  
    print(datetime.date.fromtimestamp(sjc))

二十一、包

模块可以是一个文件,但是一个包可以是很多模块

![[Pasted image 20260315100131.png]]

新建文件夹,文件夹里必须包含文件名为__init__.py!的文件
![[Pasted image 20260315100658.png]]

二十二、随机数

#随机数  
import random  
def main():  
  
  
    # 输出0-1之间的小数  
    print(random.random())  
  
    # 取0-4之间的小数  
    print(random.uniform(0,4))  
  
    # 取1-5之间的整数  
    print(random.randint(1,5))  
  
    #取1-10之间的奇数  
    print(random.randrange(1,10,2))  
    # 取1-10之间的偶数  
    print(random.randrange(0,10,2))  
    #随机选择一张牌  
    ret = random.choice(['梅花4','黑桃Q','方块K'])  
    print(ret)  
    #随机选择两张牌  
    a,b = random.sample(['梅花A','梅花2','梅花3','梅花4','方块A'],2)  
    print(a,b)  
  
    item = ['梅花A','梅花2','梅花3','梅花4','方块A']  
    random.shuffle(item)  
    print(item)

22.1 生成验证码

生成验证码小程序

import random  
  
def v_code():  
    code = ''  
    for i in range(4):  
        num = random.randint(0,9)  
        Alf = chr(random.randint(65,90)) #chr(65) chr(65) = A  
        alf = chr(random.randint(97,122))  
        add = random.choice([num,Alf,alf])  #在0-9和A-Z子母中随便选一个  
        code = "".join([code,str(add)]) #加入到code里面  
    return code  
  
def main():  
    yzm = v_code()  
    print(yzm)

二十三、正则表达式 ⭐⭐⭐

23.1 查找

23.1.1 re.findall()

查找字符串中匹配条件的内容,搜索整个字符串

`r '关键字'` 
查找某一个关键字
import re  
  
def main():  
    str1 = "fjasopefjkl210-48239-rtfujawp[e12-=e4145j39r"  #目标  
	s = r'jkl'     #寻找jkl,如果找到,会将其加入list,正则表达式  
  
  
    print(re.findall(s,str1))
`r't[io]p'`   不知道具体关键字,但是知道部分

r'^abc'   寻找以abc开头
寻找范围:在整个目标语句中,不被空格或其他干涉
`r'486$'`    寻找以abc结尾
寻找范围:在整个目标语句中,不被空格或其他干涉

`r'^q\$y'`
寻找以 q$y 开头的
利用转义字符 \ ,将本会被计算识别的`$`(结尾),识别成正常的 `$`
	\ 转义字符,如果\接符号,转为正常意思
	         如果\接字母,具体对待

`r'\d'` 寻找所有的数字
`r'\D'`寻找所有的非数字(包括空格之类的)

 `r'\s'`匹配空字符
`r'S'`匹配非空字符

`r'\w'` 匹配字母和数字
`r'\W'` 匹配非字母和数字

r'^010-\d{8}' 以 010- 开头并且后面跟了8个数字的东西

r'ab*' * 匹配0到多次
r'ab++ 匹配 1到多次
r'ab?' ? 匹配0或者1
r'ab{2,4}' 匹配b出现2-4次
r'ab\d{1,2}' 匹配ab后面跟了1-2个随机数字
'<(\w*)>.*</\1>' 匹配 <h1>haha</h1> 使用search()
r'a.b' . 匹配任意字符一次
.* 贪婪匹配

23.1.2 re.match().group()(邮箱,手机号)

从头开始搜,开头没有就没有,相当于 search ^xxxx

r'[a-zA-Z0-9]{4,20}@(163|126|qq|sohu|gmail)\.com$'

s = r'[a-zA-Z0-9]{4,20}@(126|163|sohu|qq|gmail)\.com$'  
str = "480181612@qq.com"  
  
print(re.match(s,str).group())

23.1.3 re.search().group()

search 搜索整个字符串

s = r'<(\w*)>.*</\1>'#.* 贪婪匹配,  
# . 匹配除换行符(\n、\r)之外的任何单个字符,相等于 [^\n\r]# * 匹配0到多次  
# \w 匹配字母,数字,下划线  
str1 = "wadfawsdfaw<h1>haha</h1>wafaefeafw"  
print(re.search(s,str1).group())

![[Pasted image 20260319093840.png]]

23.2 替换

23.2.1 sub()

s = r'\d+'  
str1 = "阅读数:7777"  
#print(re.search(s, str1).group(2))  
#sub 替换  
print(re.sub(s,"100",str1)) #替换

23.3 编译

#正则表达式的编译  
obj = re.compile('\d{2}')  
print(obj.search("abcd123hahaha").group())  
print(obj.search("a6725123442523hah124").group())

23.4 迭代

#正则表达式+迭代器  
ret  = re.finditer('\d{3}','fvaef15648123565')  
print(ret)  
#print(next(ret).group())  
#print(next(ret).group())  
print([i.group() for i in ret])

23.5 爬虫

爬取标签+内容

s = r'<(\w+)>.*</\1>'
ret = re.finditer(s,str1)
print(next(ret).group())
爬取内容

<p><code class = "bjh-p"> 是 Python 正则表达式处理中非常强大且高效的工具,特别是当你需要处理大量文本或者需要获取详细匹配信息(如位置索引)时,它是首选。</code></p>

爬取标签内的内容

a = r'<code class = ".*?">(.*?)</code>'  
print(re.findall(a, str1))
s = r'<a .*?>(.*?)</a>'  
print(re.findall(s,str1))

爬取链接内的内容

str1 = '<div><a href="https://www.baidu.com" title="to baidu">去百度看</a> <a href="https://www.qq.com" title="to tengxun">去腾讯看</a></div>'  
  
s = r'<a.*?href="(.*?)".*?>.*?</a>'  
#(.*?) 加括号表示 “捕获这部分内容”,re.findall 会只返回捕获组里的内容,这就是为什么结果只显示链接,而不是整个 <a> 标签。  

print(re.findall(s,str1))

二十四、异常处理

![[Pasted image 20260319170325.png]]

def main():  
    s1 = "index"  
    try:  
        #int(s1)  
        #dic = {"name":"xiaoming"}        
        #dic["age"]       
        #C        
        print("pay 100")  
        
        raise ValueError("请充值") #创造一个异常,主动出发  
        
        print("pay 200")  
  
    except ValueError as e:  
        print('valueerror',e)  
    except KeyError as e:  
        print('keyerror',e)  
    except IndexError as e:  
        print('indexerror',e)  
    except Exception as e:  
        print("未知异常")  
    finally:      
        print("不管怎么样,都要执行")

二十五、面向对象编程

25.1 类

# 定义一个类  
class Human:    #开辟了一个内存空间,只属于Huamn这个类  
    mind = "思想" #类变量  
  
    #自动创建的函数,初始化函数  
    def __init__(self,name,sex,age,money):  #括号内是外部输入进来的变量  
        self.name = name    #self.xxx 是函数里面的变量  
        self.sex = sex  
        self.age = age  
        self.money = money  
  
  
    #类函数  
    def work(self): #self:自己,在类里面定义的函数,会自动定义self,证明函数是类函数  
        print(self.name + '会工作')  
    def tools(self):  
        print(self.name + "会使用工具")  
  
def main():  
    obj = Human('小明','boy','18',"99") #实例化一个对象  
    print(obj.name)  
    print(obj.sex)  
    print(obj.age)  
    print("======================")  
    print("赚钱之前是" + str(obj.money))  
    obj.money = 777  
    print("赚钱之后" + str(obj.money))  
    print("======================")  
  
    print(obj)  
    obj.work()  #谁会工作  
    obj.tools() #谁会使用工具

25.2 类空间

25.2.1 类属性的添加

class A:  
    def __init__(self,name):  
        self.name = name  
  
    def func(self,sex):  
        self.sex = sex  
  
    def func1(self):  
        A.bbb = self  
  
def main():  
    obj = A("xiaoming")  
    obj.age = 18 #外部添加  
    obj.func("boy")  
    print(obj.age)  
    print(obj.sex)  
    A.aaa = 'test'#外部添加  
    A.func1('123')  
    print(obj.__dict__)  
    print(A.__dict__)

25.2.2 类的依赖关系

#类的依赖  
class Elephant:  
    def __init__(self,name):  
        self.name = name  
  
    def open(self,obj1):  
        #打开门  
        print(self.name,"要开门了")  
        obj1.open_door()  
  
    def close(self,obj1):  
        #关上门  
        print(self.name,"要关门了")  
        obj1.close_door()  
        pass  
class Refrigerator:  
    def open_door(self):  
        print("门打开了")  
    def close_door(self):  
        print("门关上了")  
  
def main():  
    el1 = Elephant("大象1号")  
    haier = Refrigerator()  
    el1.open(haier)  
    """  
    el1是Elephant的一个实例化,haier是Refrigerator的一个实例化  
    Elephant.open存在形参obj1 是一个对象,el1.open传入了一个实参haier 是一个对象  
    这样就形成了依赖,可以让el1.open自由调用haier里的方法,也就是obj1.open_door()  
    """    el1.close(haier)  
    pass

25.2.3 类的关联关系

#类的关联  
class Boy:  
    def __init__(self,name,girlFriend = None):  
        self.name = name  
        self.girlFriend = girlFriend  
    def have_a_dinner(self):  
        if self.girlFriend:  
            print("%s 和 %s 一起吃完饭"%(self.name,self.girlFriend.name))  
        else:  
            print("自己吃饭")  
  
class Girl:  
    def __init__(self,name):  
        self.name = name  
  
def main():  
    b = Boy("青山")  
    b.have_a_dinner()  
  
    xue = Girl("小雪")  
    b.girlFriend = xue  
    b.have_a_dinner()  
  
    b = Boy("青山",xue)  
    b.have_a_dinner()
class school:  
    def __init__(self,name,address):  
        self.name=name  
        self.address=address  
        self.teacher_list = []  
    def append_teacher(self,teacher):  
        self.teacher_list.append(teacher)  
  
class teacher:  
    def __init__(self,name,school):  
        self.name=name  
        self.school=school  
  
  
def main():  
    s1 = school("北京校区","北京")  
    s2 = school("南京校区","南京")  
  
    t1 = teacher("T1",s1)  
    t2 = teacher("T2",s2)  
    t3 = teacher("T3",s1)  
  
    s1.append_teacher(t1.name)  
    s2.append_teacher(t2.name)  
    s2.append_teacher(t3.name)  
  
    print(s1.teacher_list)  
    print(s2.teacher_list)  
    print(s2.__dict__)

25.2.4 类的组合

将一个类的对象,封装到另一个类的属性中

#类的组合  
class GameRole:  
    def __init__(self,name,ad,hp):  
        self.name = name  
        self.ad = ad  
        self.hp = hp  
  
    def attack(self,p1):  
        p1.hp = p1.hp - self.ad  
        print(" %s 攻击了 %s , %s 掉了 %s 血,还剩 %s 血"%(self.name,p1.name,p1.name,self.ad,p1.hp))  
  
    #类的组合 将Weapon整个类塞入equip_weapon  
    #捡起武器  
    def equip_weapon(self,Weapon):  
        self.Weapon = Weapon  
  
  
class Weapon:  
    def __init__(self,name,ad):  
        self.name = name  
        self.ad = ad  
  
  
    def weapon_attack(self,p1,p2):  
        p2.hp = p2.hp - self.ad - p1.ad  
        print("%s 使用了 %s , 攻击了 %s , %s 还剩 %s 血"%(p1.name,self.name,p2.name,p2.name,p2.hp))  
  
def main():  
    man = GameRole("人物1",10,100)  
    dog = GameRole("狼狗",5,50)  
  
    dog.attack(man)  
    man.attack(dog)  
  
    m4a1 = Weapon("m4a1",30)  
    man.equip_weapon(m4a1)  
    man.Weapon.weapon_attack(man,dog)  
  
    print(man.Weapon.name,man.Weapon.ad)  

25.3 类的继承

class Animal:  
    type_name = "动物类"  
  
    def __init__(self,name,sex,age):  
        self.name = name  
        self.sex = sex  
        self.age = age  
    def eat(self,x):  
        print("吃",x)  
  
class Person(Animal):  
    pass  
class Dog(Animal):  
    pass  
class Cat(Animal):  
    pass  
def main():  
    """  
    print(Person.type_name)    Person.eat("meat")    """    p1 = Person("青山","boy",18)  
    print(p1.__dict__)  
    print(Person.type_name)  
    Person.type_name = "人类"  
    print(Person.type_name)  
    p1.eat('meat')
class Ren:  
    name = 'name1'  
    age = 20  
    sex = 'None'  
    __bag = 'weapon' # 加 __ 是私有变量,只能类内访问  
    @classmethod #装饰器,加上去之后,Ren.run()可以直接使用,不用初始化  
    def run(self,x):  
        print("running",x)  
        print("i have :",self.__bag)  
          
    #构造函数,当类被初始化的时候,构造函数运行  
    def __init__(self,name,sex,age):  
        print("这个人被制造出来了")  
        self.name=name  
        self.sex=sex  
        self.age = age  
          
    # 析构函数,当类消亡的时候,析构函数运行  
    def __del__(self):  
        print("我死了",flush=True)  
          
    #内部类  
    class Bad:  
        name = "bad person"  
        def badman(self):  
            print("kill you")  
        def __init__(self,name):  
            self.name= name  
            print("坏人出现了",self.name)  
        def __del__(self):  
            print("坏人消失了",flush=True)  
              
class childRen(Ren):  
    def __init__(self):  
        print("孩子出生了")  
    def __del__(self):  
        print("孩子死了",flush=True)  
    def pao(self,x):  
        super().run(x) #继承父类的方法  
  
def main():  
    Ren.run("我没有被创建")  
  
    ren1 = Ren("青山","bot",18)  
    ren1.run("hi")  
    #print(ren1.__bag)  
    print("=========================")  
    ren2 = childRen()  
    ren2.pao("555")  
    print("=========================")  
    ren3 = Ren.Bad("皇帝")  
    ren3.badman()  
  
    pass

25.4 类的约束

#类的约束  
class Payment:  
    #我负责制定标准,谁继承我,必须拥有这些方法  
    def pay(self,money):  
        raise Exception('你没有实现我的pay方法')  
  
  
class QQpay(Payment):  
    def pay(self,money):  
        print("使用QQ钱包付费",money)  
  
class ALipay(Payment):  
    def fuqian(self,money): #这里没按照约束条件写,所以会报错  
        print("使用支付宝",money)  
  
class WeChat(Payment):  
    def pay(self,money):  
        print("使用微信支付",money)  
  
def pay(obj,money):  
    obj.pay(money)  
  
def main():  
    a = ALipay()  
    b = WeChat()  
  
    pay(a,100)  
    pay(b,200)

25.5 静态方法

独立的单纯的函数

import time  
#静态方法  
class TimeTest:  
    def __init__(self,hour,minute,second):  
        self.hour = hour  
        self.minute = minute  
        self.second = second  
  
    @staticmethod   #静态方法,直接使用  
    def showTime():  
        #print(self.hour)  
                        #hour minute second        return time.strftime("%H:%M:%S")  
  
def main():  
    #静态方法的使用,直接一条  
    print(TimeTest.showTime())

25.6 property方法

执行一段功能,然后返回值

class People:  
    def __init__(self, name,weight,height):  
        self.name = name  
        self.weight = weight  
        self.height = height  
  
    @property  
    def bmi(self):  
        return self.weight / (self.height * self.height)  
  
def main():  
    p1 = People("青山",75,1.85)  
    print(p1.bmi)   #加了property属性之后,不需要使用 () 调用了

25.7 类方法

类内使用,而且无须实例化

#类方法  
class Student:  
    __num = 0  
    def __init__(self, name,age):  
        self.name = name  
        self.age = age  
        Student.addNum()  
  
    @classmethod #类方法,可以直接调用  
    def addNum(self):  
        self.__num += 1  
  
    @classmethod  
    def getNum(self):  
        return self.__num  
  
def main():  
    st1 = Student("s1",20)  
    st2 = Student("s2",21)  
    st3 = Student("s3",19)  
  
    print(Student.getNum())


class Goods:  
    def __init__(self):  
        #原价  
        self.original_price = 100  
        #折扣  
        self.discount = 0.8  
  
    @property  
    def price(self):  
        #实际价格  
        new_price = self.original_price * self.discount  
        return new_price  
  
    #以下setter和deleter都是配合property使用  
    @price.setter   #如果obj.price = 200有接收参数的,就用setter去接受,此时默认的original_price就被修改了  
    def price(self, value):  
        self.original_price = value  
  
    @price.deleter  #把original_price恢复  
    def price(self):  
        del self.original_price  
  
def main():  
    obj = Goods()  
    #print(obj.original_price)  
    print(obj.price)  
  
    obj.price = 200  
    print(obj.price)  
  
    del obj.price  
  
    obj.price = 300  
    print(obj.price)

25.8 对象反射

class Foo:  
    f = "haha"  
    def __init__(self,name,age):  
        self.name = name  
        self.age = age  
  
    def say_hi(self):  
        print("hi")  
  
def main():  
  
    obj = Foo("xiaoming",18)  
    #检查obj里是否有say_hi这个方法  
    print(hasattr(obj,"say_hi"))  
    #获取方法内存地址  
    n = getattr(obj,"say_hi","这个方法不存在")  
    print(n)  
  
    #删除属性  
    print(obj.name)  
    #delattr(obj.name)  
    #print(obj.name) 此时是会报错的,因为name已经被删除了  
  
    #设置属性  
    setattr(obj,"job","cooker")  
    print(obj.job)

25.9 魔法方法 len和call

len和call

class B:  
    def __len__(self):  
        return 666  
  
    def __call__(self,*atgs,**kwargs):  
        print("calling")  
  
def main():  
  
    b = B()  
    #len()是测试一个长度,就会出发__len__方法  
    print(len(b))  
    #直接再对象后面加括号,就会触发__call__方法  
    b()

二十六、进程

from mutiprocessing import Process

26.1 概念

process

进程就是正在运行的程序的实例

进程具有一定独立功能的程序,关于某个数据进行运行活动

进程是一个实体
文本区域,数据区域,堆栈

特性:动态性 并发性 独立性 异步性

进程是一个资源分配的总和,线程是拿资源去执行
多进程多任务:多个资源,每个资源至少一个人做事
多线程多任务:一个资源,多个人做事

26.2 进程调度

进程调度:
FCFS 先来先服务 利于长作业

SJF/SPF 短作业优点调度 利于短作业

RR(round robin)时间片轮转

就绪状态 → 运行状态 → 阻塞状态 → 就绪状态
运行状态 → 就绪状态
![[Pasted image 20260321200628.png]]

print("程序开始执行")      #运行状态  
name = input(">>>>>")    #阻塞状态  
print(name)              #运行状态  
time.sleep(1)            #阻塞状态 → 就绪状态  
print("程序结束运行")      #运行状态 → 结束状态

26.3 多进程

import multiprocessing  
import os  
import time  
  
  
def test1(a):  
    print("test1 start",a)  
    print("test1 的进程id",os.getpid())    #查看当前进程的id  
    print("test1 的父进程id",os.getppid()) #查看当前进程的父id  
    time.sleep(5)  
  
def test2(a):  
    print("test2 start",a)  
    print("test2 的进程id",os.getpid())    #查看当前进程的id  
    print("test2 的父进程id",os.getppid()) #查看当前进程的父id  
    time.sleep(5)  
  
def main():  
    print("main函数的进程id是",os.getpid())  
    #创建进程  
    t1 = multiprocessing.Process(target = test1,args=("haha",))  
    t2 = multiprocessing.Process(target = test2,args=("nihao",))  
    #target = 执行的函数 , agrs = 执行函数的参数  
    #test1后面不需要接 ()    #args=("haha",) , 即使后面没东西,也要加 ,  
    #启动进程 同时启动  
    t1.start()  
    t2.start()  
    print("haha")

[[问题]]
![[Pasted image 20260323011954.png]]

26.3 模块

join:阻塞当前进程,直到调用join的方法的进程执行完毕,再继续执行当前进程

import time  
from multiprocessing import Process  
import os  
  
def test1():  
    print("test1 start")  
    #print(os.getppid())  
    time.sleep(5)  
    print("test1 end")  
  
def test2():  
    print("test2 start")  
    #print(os.getppid())  
    time.sleep(2)  
    print("test2 end")  
  
def main():  
  
    print("main start")  
    #print(os.getpid())  
    t1 = Process(target=test1)  
    t2 = Process(target=test2)  
    t1.start()  
    t2.start()  
    t2.join()   #阻塞  
    t1.join()   #阻塞  
    print("main end")

26.4 守护进程

一定要在start之前开启,设置True就是守护进程开启
在父进程代码结束之后,守护进程立马停止运行

import time  
from multiprocessing import Process  
  
def foo():  
    print("foo start")  
    time.sleep(5)  
    print("foo stop")  
      
def bar():  
    print("bar start")  
    time.sleep(5)  
    print("bar stop")  
      
def main():  
    print("main start")  
    t1 = Process(target=foo)  
    t2 = Process(target=bar)  
  
    t1.daemon = True #开启守护进程  
    t2.daemon = True #开启守护进程  
    #一定要在start之前开启,设置True就是守护进程开启  
    #在父进程代码结束之后,守护进程立马停止运行  
    t1.start()  
    t2.start()  
    time.sleep(0.1)  
    print("main stop")

26.5 队列

26.5.1 FIFO

import queue
q = queue.Queue() #先进先出
import queue
q = queue.LifoQueue() #先进后出
import queue
q = queue.PriorityQueue() #优先级队列,越小越优先
q.put(20,'1')
q.put(10,'2')
q.put(40,'3')
q.put(30,'4')

#输出 2143

from mutiprocessing import Queue

from multiprocessing import Queue  
def main():  
  
    q = Queue(3) #定义一个叫q的队列,队列容量:3  
    q.put("x1")  
    q.put("x2")  
    q.put("x3")  
    #q.put("x4")    #如果队列满了,程序就会停在这里,等待数据被人取走,再将数据放入队列  
  
    try:  
        q.put_nowait("x4")  #可以使用put_nowait,如果队列满了就不会阻塞,但是会报错  
    except:  
        print("队列满了,不能放")  
  
    print(q.full()) #判断一下队列是否满了  
  
    #print(q.get())  
    #print(q.get())    #print(q.get())    for i in range(3):  # 同put方法一样,如果队列已经空了,就会继续出现阻塞  
        num = q.get()  
        print(num)  
    try:  
        print(q.get_nowait())  
    except:  
        print("队列已经空了")  
  
    print(q.empty())

26.6 进程间传递数据

生产者消费者模型

import time,os,random  
from multiprocessing import Process,Queue  
import os  
  
def customer(q):  
    while True:  
        res = q.get()   #从队列取出包子  
        if res is None:break  
        time.sleep(random.randint(1,3))  
        print("%s 吃 %s"%(os.getpid(),res))  
  
def producer(q):  
    for i in range(10):  
        time.sleep(random.randint(1,3))  
        res = "包子 %s 号" % i  
        q.put(res)  #把包子加入队列中  
        print("%s 生成了 %s"%(os.getpid(),res))  
    q.put(None) #发出结束讯号  
  
def main():  
    q = Queue()  
    p1 = Process(target=producer, args=(q,))  
    p2 = Process(target=customer, args=(q,))  
  
    p1.start()  
    p2.start()  
  
    print("main")

结束信号None,不一定要由生产者进程发送,可以主进程等生产者完成后,由主进程发送


import time,os,random  
from multiprocessing import Process,Queue  
import os  
  
def customer(q):  
    while True:  
        res = q.get()   #从队列取出包子  
        if res is None:break  
        time.sleep(random.randint(1,3))  
        print("%s 吃 %s"%(os.getpid(),res))  
  
def producer(q):  
    for i in range(10):  
        time.sleep(random.randint(1,3))  
        res = "包子 %s 号" % i  
        q.put(res)  #把包子加入队列中  
        print("%s 生成了 %s"%(os.getpid(),res))  
  
def main():  
    q = Queue()  
    p1 = Process(target=producer, args=(q,))  
    p2 = Process(target=customer, args=(q,))  
  
    p1.start()  #生产者  
    p2.start()  #消费者  
  
    p1.join()  
    q.put(None) #发出结束讯号  
  
    print("main")
import time,os,random  
from multiprocessing import Process,Queue  
import os  
  
def customer(q):  
    while True:  
        res = q.get()   #从队列取出包子  
        if res is None:break  
        time.sleep(random.randint(1,3))  
        print("%s 吃 %s"%(os.getpid(),res))  
  
def producer(name,q):  
    for i in range(10):  
        time.sleep(random.randint(1,3))  
        res = "%s 的 %s 号" %(name,i)  
        q.put(res)  #把包子加入队列中  
        print("%s 生成了 %s"%(os.getpid(),res))  
  
def main():  
    q = Queue()  
    #多个厨师  
    p1 = Process(target=producer,args=("包子",q,))  
    p2 = Process(target=producer,args=("骨头",q,))  
    p3 = Process(target=producer,args=("牛肉",q,))  
  
    #多个消费者  
    c1 = Process(target=customer,args=(q,))  
    c2 = Process(target=customer,args=(q,))  
  
    #循序无所谓  
    p1.start()  
    p2.start()  
    p3.start()  
  
    c1.start()  
    c2.start()  
    #必须保证生产者都处理完毕,才能发出结束信号  
    p1.join()  
    p2.join()  
    p3.join()  
    #有几个消费者发出几个结束信号  
    q.put(None)  
    q.put(None)  
    q.put(None)

26.7 共享进程队列

import time,os,random  
from multiprocessing import Process,JoinableQueue  
import os  
  
#共享进程队列  
#JoinableQueue 创建一个可连接的共享队列  
#允许项目的使用者通知生产者,项目已经被成功处理了  
  
  
def customer(q):  
    while True:  
        res = q.get()  
        if res is None:break  
        time.sleep(random.randint(1,3))  
        print("%s 使用 %s"%(os.getpid(),res))  
        q.task_done()   #向q.join发送一次信号  
                        #证明数据已经被取走了  
  
  
def producer(name,q):  
    for i in range(10):  
        time.sleep(random.randint(1,3))  
        res = "%s 的 %s 号"%(name,i)  
        q.put(res)  
        print("%s 生产了 %s"%(os.getpid(),res))  
  
def main():  
    q = JoinableQueue()  
    #生产者们  
    p1 = Process(target=producer, args=("包子",q,))  
    p2 = Process(target=producer, args=("牛肉",q,))  
    p3 = Process(target=producer, args=("酒",q,))  
  
    #消费者们  
    c1 = Process(target=customer, args=(q,))  
    c2 = Process(target=customer, args=(q,))  
  
    c1.daemon = True  
    c2.daemon = True  
  
    #开始  
    p_1 = [p1,p2,p3,c1,c2]  
  
    for p in p_1:  
        p.start()  
  
    #等待厨师完成  
    p1.join()  
    p2.join()  
    p3.join()  
    # 关键:等待队列中所有数据被消费者处理完  
	q.join()    #生产完毕,使用这个方法进行阻塞。  
            #目的是:直到队列中所有东西被处理
	print("main")

主进程等 p1,p2,p3 c1,c2
p1,p2,p3结束了,证明c1,c2全都收完了p1,p2,p3的数据 q.task_done()
如果没接收完p1,p2,p3,会等他们搞定

搞定完成之后,c1,c2就没有价值了,p1,p2,p3的join也结束了,所以主进程继续执行,
主进程结束之后,顺便使用daemon把c1,c2给关掉

26.8 进程锁

进程之间数据相对独立,一般不实现数据通信,而是通过数据库来实现
如果硬是要实现,一般是进程锁(只能作为临时的解决方案)

from multiprocessing import Manager,Lock  
  
def work(d,lock):  
    with lock:  
        d['count'] -= 1  
  
def main():  
    lock = Lock()   #进程锁  
    with Manager() as m:  
        dic = m.dict({'count':100})  
        p_l = []  
        for i in range(98):  
            p = Process(target=work,args=(dic,lock,))  
            p_l.append(p)  
            p.start()  
        for p in p_l:  
            p.join()  
        print(dic)

26.9 进程池

限制任务去开启进程做事情
池子 – 固定数量的进程

有事情了,从池子里拿一个进程出来做事情,做完事情,不关闭进程!
放回池子里继续等待下一个任务

如果池子里的进程数量不够,任务就需要等待,等什么时候有空闲的进程就继续执行(是被允许的)

from multiprocessing import Pool,Process  
import time  
  
#单进程:0.2668149471282959  
#多进程:2.0607948303222656  
  
def func(n):  
    for i in range(10): #把1-100每个数字打印10次  
        print(n+1)  
  
def main():  
    start = time.time()    #记录开始时间  
  
    #单进程  
    pool = Pool(5)  #池子里五个进程  
    pool.map(func,range(100))   #定义100个任务  
    
    """  
    #多进程  
    p_l = []    
    for i in range(100):        
	    p = Process(target=func, args=(i,))        
	    p_l.append(p)        
	    p.start()    
	for p in p_l:        
	p.join()    
	"""    
	
	t2 = (time.time()-start)  
    print(t2)  
    pass

26.9.1 同步调用

from multiprocessing import Pool,Process  
import os,time  
  
#同步调用  
def work(n):  
    print("%s run"%(os.getpid()))  
    time.sleep(3)  
    return n**2     #n*n  
  
def main():  
    p = Pool(3) #进程池从无到有,创建3个进程  
    res_l = []  
    for i in range(10):  
        res = p.apply(work,args=(i,))   #同步调用,直到拿到结果为止,不管任务是否存在阻塞,同步调用都会原地等着  
        res_l.append(res)  
    print(res_l)

26.9.2 异步调用

#异步调用  
def work(n):  
    print("%s run"%(os.getpid()))  
    time.sleep(3)  
    return n**2     #n*n  
  
def main():  
    p = Pool(3) #进程池从无到有,创建3个进程  
    res_l = []  
    l = []  
    for i in range(10):  
        res = p.apply_async(work,args=(i,))   #异步调用,进程不会同时开启,也不会同时结束,也不会互相等待  
        res_l.append(res)  
    p.close()   #关门,不再接受新的进程  
    p.join()    #异步提交任务,主进程需要使用join,等待进程池里任务都处理完后,可以用get取搜集结果  
    #主进程等所有进程结束            #如果不用join,主进程结束,进程池还没来得及执行,就跟着结束  
    print(res_l)  
    for r in res_l:  
        a = r.get() #需要使用get获取apply_async的结果,因为apply没有get方法,  
                    # 因为apply同步执行,立即获取结果,无需get  
        l.append(a) #l无返回值,不能写成 l = l.append(a)    print(l)

二十七、网络编程基础

同一台电脑,可以使用配置文件
不同电脑可以使用平台

软件:
– 应用类
qq 微信 百度云 优酷

– web类
百度 知乎
webview技术 只能浏览唯一网址

1.架构 从用户层面划分
c/s(Client/Server)

  • Client 客户端:你下载的 APP、软件
  • Server 服务器:远端的电脑,提供数据

b/s(Browser/Server)

  • Browser 浏览器:Chrome、Edge、Safari
  • Server 服务器:网页所在的电脑

27.1 协议 = 标准

27.1 OSI七层模型 理论模型

OSI七层模型
理论模型

** 物 数 网 传 会 表 应**
物理层 数据链路层 网络层 传输层 会话层 表示层 应用层

7 应用层 Application

给软件用的协议

- HTTP、HTTPS、FTP、DNS、SMTP
- QQ、浏览器、微信用的就是这一层

6 表示层 Presentation

数据翻译、加密、压缩

- 把文字→编码,图片→格式
- SSL/TLS 加密也在这层

5 会话层 Session

建立、管理、断开对话

- 保证连接不断、不乱序

4 传输层 Transport

负责端到端传输

- TCP(可靠、慢)
- UDP(快、不可靠)
- 端口号在这里

3 网络层 Network

负责寻址、找路

- IP 协议
- 路由器工作在这层

2 数据链路层 Data Link

负责相邻设备传输

- MAC 地址
- 交换机工作在这层

1 物理层 Physical

硬件传输

- 网线、光纤、无线电波
- 只传 0 和 1

![[Pasted image 20260324235511.png]]

27.2 TCP/IP协议栈

TCP/IP协议栈
真实互联网

应用层
传输层
网络层
网络接口层

4 应用层
(对应 OSI 上三层:应用层 + 表示层 + 会话层)

- 负责软件之间的通信
- 常见协议:
    
    - HTTP / HTTPS(网页)
    - DNS(域名解析)
    - FTP(文件传输)
    - SMTP / POP3(邮件)
    - QQ、微信自定义协议也在这层
    
3 传输层

- 负责端到端传输,用端口号区分程序
- 两个核心协议:
    
    - TCP:可靠、面向连接、不丢包(打电话)
    - UDP:不可靠、快、无连接(发短信)
    
2 网络层

- 负责寻址、路由,找到目标主机
- 核心协议:
    
    - IP 协议(IPv4 / IPv6)
    - ICMP(ping 命令用这个)
    

1 网络接口层(数据链路层 + 物理层)

- 负责跟硬件打交道:网卡、网线、交换机
- 基于 MAC 地址传输

用户进程代表一个程序:比如 QQ 微信,淘宝
用户进程需要使用Socket抽象层来跟TCP/UDP通信
不论是什么协议,TCP/UPD/ICMP/IGMP,最后都需要跟IP去联系起来
因为只有IP才和硬件有联系 硬件就是网卡

Socket 套接字
分为两种 基于文件 和 基于网络

基于文件
af_unix
unix一切都是文件

基于网络
af_inet(ipv4)
af_inet6(ipv6)

![[Pasted image 20260324235613.png]]

27.1.3 TCP/UDP

TCP 可靠的传输,面向连接(打电话),可靠传输但是传输效率低,全双工通信,有拥塞机制(有先来后到)
web浏览器,文件传输,邮件
单工通信 收音机
半双工通信 对讲机
全双工通信 电话

UDP 不可靠的传输,无连接的服务,传输效率高(发送延时小),一对一,一对多,多对一,多对多
面向报文(数据包),尽最大努力服务,无拥塞机制
域名系统(dns),视频,语言

![[Pasted image 20260325002459.png]]

一般同时启用Socket,不过都是服务端先启动

服务器端:
bind()绑定ip地址
listen()监听哪些端口
accpet()开始允许用户连接,此时会阻塞直到用户连接

客户端
connect()建立连接

服务器端
read()读取,证明有人连接,读取客户端write()发来的数据,并且通过write()回应数据给客户端的read()

客户端
write()给服务器发送数据,并用read()接受服务器传来的数据

客户端write() → 服务器read() → 服务器write() →客户端read() 循环
![[Pasted image 20260325003023.png]]

客户端
close()结束

服务端
read()收到来自客户端的结束请求,最后用close()结束

27.2 通信实现

27.2.1 基础C/S架构

服务端:

# /usr/bin/python  
# coding:UTF-8  
  
#服务端程序  
import socket  
  
def main():  
    s = socket.socket() #导入socket模块  
    host = socket.gethostname() #获取自己的IP地址  
    port = 12345 #一会使用12345端口通信  
    s.bind((host,port)) #绑定ip地址和端口  
    s.listen(5) #等待用户连接,最多5个人  
    c,addr = s.accept() #建立和客户端的连接 c = 对方的套接字, addr=对方的ip地址和对方的端口以元祖的形式存在  
    print("对方连接地址是",addr)  
    c.send("welcome".encode("utf-8"))   #通过客户的套接字发送welcome给对方,utf-8编码  
    print(c.recv(1024).decode("utf-8")) #c相当于管道,接受客户信息  
  
  
    c.close()  
  
    pass

客户端:

# /usr/bin/python  
# coding:UTF-8  
  
#客户端程序  
import socket  
  
def main():  
    s = socket.socket()  
    host = '192.168.31.7'   #你要连接谁的ip地址  
    port = 12345  
    s.connect((host,port))  #连接服务端  
    msg = input("您要发送的信息:")  
    s.send(msg.encode("utf-8"))#发送信息  
    print(s.recv(1024).decode("utf-8")) #接收信息  
    s.close()  
  
    pass

27.2.2 循环网络通信

服务端

#服务端程序  
import socket  
  
def main():  
    #socket.AF_INET 使用ipv4通信,socket.SOCK_STREAM使用tcp通信  
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    #绑定端口  
    tcp_server_socket.bind(('',8080))  
    #允许多数人连接我  
    tcp_server_socket.listen(128)  
    #循环为多个客户服务多次  
    while True:  
        #等待用户连接,保存用户的socket和ip地址  
        new_client_socket,client_address = tcp_server_socket.accept()  
        print("the %s connecting"%(str(client_address)))  
        #给客户发送信息  
        new_client_socket.send("welcome".encode("utf-8"))  
        #循环为一个客户服务  
        while True:  
            # 接收来自客户的数据  
            recv_data = new_client_socket.recv(1024)  
            if  recv_data:  
                print(recv_data.decode("utf-8"))  
            else:  
                print("断开连接")  
                break  
        #关闭套接字  
        new_client_socket.close()  
    tcp_server_socket.close()

客户端:

#客户端程序  
import socket  
  
def main():  
    tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    server_ip = '192.168.31.7'  
    server_port = 8080  
    server_add = (server_ip,server_port)  
    #连接服务器  
    tcp_socket.connect(server_add)  
    #接受第一次发来的数据  
    first_data = tcp_socket.recv(1024)  
    print(first_data.decode("utf-8"))  
    while True:  
        #持续发送数据  
        send_data = input("send---->")  
        tcp_socket.send(send_data.encode("utf-8"))  
    tcp_socket.close()

二十八、线程(Thread)

进程
只能在同一时间干一件事情
执行过程中,如果阻塞,比如等待输入,这个适合整个进程是挂起
地址空间相对独立

线程
同一个进程里的各个线程之间共享数据
调度和切换速度快

注意:进程是资源分配的基本单位
线程是CPU调度的最小单位,每个进程中至少一个线程

==================
全局解释锁 GIL
同一时刻只有一个线程在运行

28.1 线程的使用

#多线程  
from threading import Thread  
import time  
  
def sayHi(name):  
    time.sleep(2)  
    print("%s say hello"%(name))  
  
def main():  
    t = Thread(target=sayHi,args=("xiaoming",))  
    t.start()  
    print("主线程")

线程是进程的一部分

#多线程  
from threading import Thread  
from multiprocessing import Process  
import time,os  
  
def work():  
    print("hello",os.getpid())  
  
def main():  
    T1 = Thread(target=work)  
    T2 = Thread(target=work)  
    T1.start()  
    T2.start()  
  
    print("主线程pid:",os.getpid())  
  
    P1 = Process(target=work)  
    P2 = Process(target=work)  
    P1.start()  
    P2.start()

28.2内存数据共享实验

#内存数据共享实验  
from threading import Thread  
from multiprocessing import Process  
import time,os  
  
  
def work_for_Process():  
    global n  
    n = 0  
  
def work_for_Thread():  
    global n  
    n = 0  
  
def main():  
  
    n = 100  
    p = Process(target=work_for_Process)  
    p.start()  
    p.join()  
    print(n) #0  
  
    a = 9  
    t = Thread(target=work_for_Thread)  
    t.start()  
    t.join()  
    print(a) #9

28.3 多线程其他函数


from threading import Thread  
import threading,time  
  
def work():  
    time.sleep(3)  
    print(threading.current_thread().getName()) #获取线程的名字  
  
def main():  
    T1 = threading.Thread(target = work)  
    T2 = threading.Thread(target = work)  
  
    T1.start()  
    T2.start()  
    # 查看主线程的名字  
    print(threading.current_thread().getName())     # MainThread  
    # 查看有谁在运行  
    print(threading.enumerate())  
    # 查看一共有多个线程在运行  
    print(threading.active_count()) # 3

from threading import Thread  
import threading,time  
  
def work():  
    time.sleep(3)  
    print(threading.current_thread().getName()) #获取线程的名字  
  
def main():  
    T1 = threading.Thread(target = work)  
    T1.start()  
    print(T1.is_alive()) #判断线程是否存活  
    T1.join()  
    print("main")  
    print(T1.is_alive()) #判断线程是否存活

28.4 守护线程

  
#守护线程  
from threading import Thread  
import threading,time  
  
def foo():  
    print("123")  
    time.sleep(1)  
    print("end123")  
  
def bar():  
    print("456")  
    time.sleep(3)  
    print("end456")  
  
def main():  
    t1 = Thread(target=foo)  
    t2 = Thread(target=bar)  
    t1.daemon = True  
    t2.daemon = True  
  
    t1.start()  
    t2.start()  
    print("main")  
      
    #123  
    #456main  
    pass  
  
if __name__ == '__main__':  
    main()

28.5 多线程同步锁

lock.acquire()  #加锁  
	... #对数据操作的时候,前后加解锁
lock.release()  #解锁

会让程序从并发执行变成串行,牺牲效率保证数据安全(一般用数据库来完成)

  
from threading import Thread,Lock,current_thread  
import time,os  
  
n = 100  
  
def work(lock):  
    lock.acquire()  
    global n  
    temp = n  
    time.sleep(0.1)  
    n = temp -1  
    lock.release()  
    print("%s is running %s"%(current_thread().getName(),n))  
  
def main():  
    l = []  
    lock = Lock()  
    start_time = time.time()  
    for i in range(100):  
        T = Thread(target=work,args=(lock,))  
        l.append(T)  
        T.start()  
    for p in l:  
        p.join()  
    print(n)  
  
    stop_time = time.time()  
  
    print("主%s %s"%(stop_time - start_time,n))  
  
  
  
  
if __name__ == '__main__':  
    main()

二十九、协程

生成器(yield)= 协程的底层实现

进程是资源分配的最小单位
线程是CPU调度的最小单位

单线程实现并发

协程 – 用户态的轻量级线程
单线程如果遇到 IO , 就会从应用程序级别进行控制和切换

优点:
切换开销更小(属于程序级别的切换,操作系统感知不到)
单线程实现并发效果
一个进程放多个线程,不行
那就一个线程放多个协程

缺点:
本质还是在单线程下运行,无法利用电脑CPU多核
一个程序开启多个进程,每个进程开启多个线程,每个线程开启多个协程
协程都是基于单线程的

以但协程出现阻塞,就会阻塞整个线程

29.1 协程原理

  
def create_num(all_num):  
    print("---1---")  
    a,b = 0,1  
    current_num = 0  
    while current_num < all_num:  
        print("---2---")  
        ret = yield a  
        print("---ret---",ret)  
        print("---3---")  
        a,b = b,a+b #第二次 a=1,b=2        current_num += 1  
  
def main():  
    obj = create_num(10)  
    ret = next(obj)  
    print(ret)  #a  
    ret = obj.send("haha")      # next() 和 send() 都是「唤醒开关」  
  
    #生成器暂停后,只有两个办法能让它继续跑:  
    #next(生成器) → 唤醒,但不传值  
    #生成器.send(值) → 唤醒,同时传一个值  
    print(ret)  #1  
    if __name__ == '__main__':  
    main()

29.2 协程多任务

import time  
  
from scipy.constants import year  
  
  
def task_1():  
    while True:  
        print("---1---")  
        time.sleep(1)  
        yield  
  
def task_2():  
    while True:  
        print("---2---")  
        time.sleep(2)  
        yield  
  
def main():  
    t1 = task_1()  
    t2 = task_2()  
    while True:  
        next(t1)  
        next(t2)

29.3 greenlet

  
import time  
from greenlet import greenlet  
#切换时,只有第一次需要传参,之后无需传参,数据未丢失  
  
def main():  
    def eat(name):  
        print("%s eat 1" % name)    #小明 eat 1        
        g2.switch("小红") #第二步、参数名是小红,函数是play,切换到 print("%s play 1" % name)        
        print("%s eat 2" % name)  
        g2.switch() #第四步、默认参数名是小红,函数是play,切换到 print("%s play 2" % name) ,结束  
  
  
  
    def play(name):  
        print("%s play 1" % name)  
        g1.switch() #第三步、默认参数小明,函数是eat,切换到 print("%s eat 2" % name)          print("%s play 2" % name)  
  
        #切换  
    g1 = greenlet(eat)  #执行eat函数并且执行切换  
    g2 = greenlet(play)  
  
    g1.switch("小明") #第一步、将参数 小明 带入eat  
  
  
  
  
  
if __name__ == '__main__':  
    main()
  
import time  
from greenlet import greenlet  
#切换时,只有第一次需要传参,之后无需传参,数据未丢失  
  
def f1():  
    res = 1  
    for i in range(1000):  
        res += 1  
        time.sleep(1)  
        print(res)  
        g2.switch()  
  
def f2():  
    res = 1  
    for i in range(2000):  
        res += 2  
        time.sleep(1)  
        print(res)  
        g1.switch()  
  
g1 = greenlet(f1)  
g2 = greenlet(f2)  
  
  
def main():  
    start = time.time()  
    g2.switch() #从 def f2() 开局  
    stop = time.time()  
    print(stop-start)  
  
  
  
  
if __name__ == '__main__':  
    main()

29.4 gevent

因为greenlet没有解决效率问题,只是解决了切换问题

gevent可以理解为协程池,greenlet的封装

  
import time  
    #必须放在最前面!在 import time、socket、requests 之前!  
from gevent import monkey;monkey.patch_all()    #必须打上补丁,如果不用gevent.sleep(1)  
  
import gevent  
import threading  
  
  
def eat(name):  
    # Dummy-1 伪线程  
    print(threading.current_thread().getName())  
    print("%s eat 1"%name)  
  
    #gevent.sleep(2)  
    time.sleep(1)  
  
    print("%s eat 2"%name)  
  
  
def play(name):  
    print(threading.current_thread().getName())  
    print("%s play 1"%name)  
  
    #gevent.sleep(2) #模拟拥塞  
    time.sleep(2)  
  
    print("%s play 2"%name)  
  
def main():  
    #spawn 创建协程对象 spawn(函数名,参数)  
    g1 = gevent.spawn(eat,"小明")  
    g2 = gevent.spawn(play,"小红")  
  
    #g1.join()  
    #g2.join()    gevent.joinall([g1,g2])  
  
    print("主")  
  
  
  
  
  
if __name__ == '__main__':  
    main()

29.5 协程同步和异步

import time  
  
    #必须放在最前面!在 import time、socket、requests 之前!  
from gevent import monkey;monkey.patch_all()    #必须打上补丁,如果不用gevent.sleep(1)  
  
import gevent  
import threading  
  
def task(pid):  
    time.sleep(0.5)  
    print("task %s done" % pid)  
  
def main():  
    """  
    #同步 串行,一步一步走  
    for i in range(10):        task(i)    """    #异步 并发,同时进行  
    g_l = [gevent.spawn(task,i) for i in range(10)]  
    gevent.joinall(g_l)  
    print("main done")  
  
if __name__ == '__main__':  
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值