day1

输入输出

a = input("输入字符串:")
b = int(input("输入int:"))
print(type(a))
print(type(b))
#格式化输出
print('{} {} {}'.format('aaron',18,'teacher'))
print('{1} {0} {1}'.format('aaron',18,'teacher'))
print('{name} {age} {job}'.format(job='teacher',name='aaron',age=18))

input 默认输入为string。

字符串的索引与切片

# 0是列表中第一个元素的索引,-1 是列表中最后一个元素的索引,满足顾头不顾尾的原则
a = "ABCDEF"
print(a[0:-1])#结果为 ABCDE

字符串处理

words = "beautiful is better than ugly."
words.capitalize()   #首字母大写
words.swapcase()     #大小写翻转
words.title()        #每个单词的首字母大写

# 内容居中,总长度,空白处填充 center(总长度,"填充符号")
ret = a.center(20,"*")

# startswith 判断是否以...开头
# endswith 判断是否以...结尾 
# return 布尔值
a.startswith("a")
a.endswith("j")
a.startswith('sdj',2,5)
a.endswith('ado',7,10)

# split 以什么分割,最终形成一个列表此列表不含有这个分割的元素。
ret = words.split(' ')
ret = words.rsplit(' ',2) # 加数字指定分割次数

# strip
a = '****asdasdasd********'
print(a.strip('*'))  #清除所有该元素
print(a.lstrip('*')) #清除左侧所有该元素
print(a.rstrip('*')) #清除右侧所有该元素

# replace
print(words.replace('e','a',2)) # 字符串从左向右开始,把e替换成a,一共替换两次
print(words.isalnum()) #字符串由字母或数字组成
print(words.isalpha()) #字符串只由字母组成
print(words.isdigit()) #字符串只由数字组成

列表处理(增删改查)

li = [1,'a',2,'d',4]
li.insert(0,22)     # 按照索引去增加
li.append('ddd')    # 增加到最后
li.extend(['q,a,w'])    # 迭代的去增
li.extend(['q,a,w','das'])    # 迭代的去增
a = li.pop(1)   # 按照位置去删除,有返回值
print(a)        #删除成功后a = 1
del li[1:3]     # 按照位置去删除,也可切片删除没有返回值。
li.remove('f')  # 删除指定字符。
li.clear()      #清空列表
li[1] = 'aaa'   #修改指定字符
li[2:3] = [3,'e']#修改对应切片字符

元组(不可修改)

tuple = (1, 2, 3, [1, 4, 7])
print(tuple)
tuple[3][2] = 100#可以修改元组里的列表中的数据
print(tuple)

字典(增删改查)

dic = {"age": 18, "name": "aaron"}
dic['li'] = ["a", "b", "c"]
dic.setdefault('k', 'v')# 在字典中添加键值对时,如果指定的键已经存在则不做任何操作,如果原字典中不存在指定的键值对,则会添加。

#删除
dic['name'] = 'demo'
dic_pop = dic.popitem()
# 随机删除字典中的某个键值对,将删除的键值对以元祖的形式返回
dic.pop()#随机删除
dic.pop('age')
dic_pop = dic.pop('sex', '查无此项')#如存在该键,则值为对应是数值,否则为后面的默认值。
dic_clear = dic.clear()# 清空字典

#修改
dic['li'] =["a","b"]

dic = {"age":18, "name":"aaron", 'sex':'male'}
dic2 = {"age":30, "name":'demo'}
dic2.update(dic)# 将dic所有的键值对覆盖添加(相同的覆盖,没有的添加)到dic2中

#查询
a1 = dic['age']        #若无该键,无返回值
print(a1)
a2 = dic.get('ll', 'qqq')#若无该键,有返回值
print(a2)

集合

集合是无序的,不重复确定性的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的。以下是集合最重要的两点:

  • 去重,把一个列表变成集合,就自动去重了。
  • 关系测试,测试两组数据之前的交集、差集、并集等关系。
set1 = set({1,2,'barry'})
set2 = {1,2,'barry'}

set1 = {'abc','def',123,'asdas'}# add()函数的参数只能接收可哈希数据类型,即不可变数据类型,比如整型、浮点型、元组、字符串
set1.add('qwer')

set1.update('A')#update:迭代着增加

set1.pop()#随机删除

del set1#删除集合

set1 | set2# | 并集,& 交集,- 差集,^ 反交集

s = frozenset(set1)#frozenset不可变集合,让集合变成不可变类型<class 'frozenset'>
s.add(7) # 不可以修改,会报错

按存储空间的占用分(从低到高)

  1. 整型
  2. 字符串
  3. 集合:无序,即无序存索引相关信息
  4. 元组:有序,需要存索引相关信息,不可变
  5. 列表:有序,需要存索引相关信息,可变,需要处理数据的增删改
  6. 字典:无序,需要存key与value映射的相关信息,可变,需要处理数据的增删改

流程控制之 --if

False:[],{},()

True:其他

"""
if 条件:
    满足条件执行代码
else:
    if条件不满足就走这段
"""

流程控制之 --while

"""
while 条件:
     循环体
"""

循环中止语句

break

用于完全结束一个循环,跳出循环体执行循环后面的语句

continue

continue 只是终止本次循环

day2

文件操作

1.打开文件

2.读写文件

3.关闭文件

# 1. 打开 - 文件名需要注意大小写
file = open("README")   #变量 = open("文件名", "访问方式")
# 2. 读取
text = file.read()
print(text)
# 3. 关闭
file.close()

text1 = file1.readline().strip()#按行读写

f=open('a.txt','r',encoding='utf-8')#按规定编码打开文件

with

with open('a.txt','r') as read_f,open('b.txt','w') as write_f:#with方法:open(文件名) as 变量
    data=read_f.read()
    write_f.write(data)

文件操作方法

def close(self, *args, **kwargs): # real signature unknown
        关闭文件
        pass

def fileno(self, *args, **kwargs): # real signature unknown
    文件描述符  
    pass

def flush(self, *args, **kwargs): # real signature unknown
    刷新文件内部缓冲区
    pass

def isatty(self, *args, **kwargs): # real signature unknown
    判断文件是否是同意tty设备
    pass

def read(self, *args, **kwargs): # real signature unknown
    读取指定字节数据
    pass

def readable(self, *args, **kwargs): # real signature unknown
    是否可读
    pass

def readline(self, *args, **kwargs): # real signature unknown
    仅读取一行数据
    pass

def seek(self, *args, **kwargs): # real signature unknown
    指定文件中指针位置
    pass

def seekable(self, *args, **kwargs): # real signature unknown
    指针是否可操作
    pass

def tell(self, *args, **kwargs): # real signature unknown
    获取指针位置
    pass

def truncate(self, *args, **kwargs): # real signature unknown
    截断数据,仅保留指定之前数据
    pass

def writable(self, *args, **kwargs): # real signature unknown
    是否可写
    pass

def write(self, *args, **kwargs): # real signature unknown
    写内容
    pass

def __getstate__(self, *args, **kwargs): # real signature unknown
    pass

def __init__(self, *args, **kwargs): # real signature unknown
    pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
    """ Create and return a new object.  See help(type) for accurate signature. """
    pass

def __next__(self, *args, **kwargs): # real signature unknown
    """ Implement next(self). """
    pass

def __repr__(self, *args, **kwargs): # real signature unknown
    """ Return repr(self). """
    pass

函数

def getnum(a):#定义函数getnum,传入参数a
    #函数内容
    global b     #在函数中调用全局变量
    b*=b
    rutrun b#函数返回值,若不声明则为None

闭包

内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数

例子:在调用某个函数的内部函数时,使用闭包可以直接访问到内部函数,如果多次调用时,就只需要运行一次该函数。

from urllib.request import urlopen
def func():
    content = urlopen('http://myip.ipip.net').read().decode('utf-8')
    def get_content():
        return content
    return get_content

code = func()
content = code()
print(content)

content2 = code()
print(content2)

装饰器

让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。 装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。

def a(x):
    def a1():
        print("c")
        x()
        print("a")
    return a1
@a   #b=a(b)  让b函数获得了a函数中的内容
def b():
    print("b")
b()  #其中b函数的运行顺序为a函数中函数的顺序
     #b.__name__ = a1

day3

迭代器

我们已经知道可以对list、tuple、str等类型的数据使用for...in...的循环语法从其中依次拿到数据进行使用,我们把这样的过程称为遍历,也叫迭代。在python的数据类型中,只有整形不可迭代。

# 字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的
from collections.abc import Iterable

l = [1, 2, 3, 4]
t = (1, 2, 3, 4)
d = {1: 2, 3: 4}
s = {1, 2, 3, 4}

print(isinstance(l, Iterable))
print(isinstance(t, Iterable))
print(isinstance(d, Iterable))
print(isinstance(s, Iterable))

生成器

一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。

def genrator_func1():
    a = 1
    print('将a赋值')
    yield a
    b = 2
    print('将b赋值')
    yield b

g1 = genrator_func1()

print(g1,next(g1))
print(next(g1))

推导式

  1. 把列表解析的[]换成()得到的就是生成器表达式

  2. 列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

  3. Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和

    variable = [out_exp_res for out_exp in input_list if out_exp == 2]
      out_exp_res:  列表生成元素表达式,可以是有返回值的函数。
      for out_exp in input_list:  迭代input_list将out_exp传入out_exp_res表达式中。
      if out_exp == 2:  根据条件过滤哪些值可以。
    

合并大小写对应的value值,将k统一成小写

dic1 = {'a':1,'b':2,'y':1, 'A':4,'Y':9}

dic2 = {k.lower():dic1.get(k.lower(),0) + dic1.get(k.upper(),0) for k in dic1.keys()}
print(dic2)

内置函数

截止到python版本3.6.2,现在python一共为我们提供了68个内置函数。

image-20240331101156834

匿名函数

函数名 = lambda 参数 :返回值,实参

  1. 参数可以有多个,用逗号隔开
  2. 匿名函数不管逻辑多复杂,只能写一行,且逻辑执行结束后的内容就是返回值
  3. 返回值和正常的函数一样可以是任意数据类型
calc = lambda n: n ** n
print(calc(10))

递归

汉诺塔小游戏:

def move(n, a, b, c):
    if n == 1:
        print(a, "-->", c)
    else:
        move(n - 1, a, c, b)
        print(a, "-->", c)
        move(n - 1, b, a, c)


move(3, "a", "b", "c")
递归:高级
def search(num,l,start=None,end=None):
    start = start if start else 0
    end = len(l)-1 if end is None else end
    mid = (end - start)//2 + start
    if start > end:
        return None
    elif l[mid] > num :
        return search(num,l,start,mid-1)
    elif l[mid] < num:
        return search(num,l,mid+1,end)
    elif l[mid] == num:
        return mid

ret = search(18,l)
print(ret)

day4

模块与包

模块调用:

import module_name as name #module_name为模块名,name为调用名,可省略。
import  sys, os, re        #import可以同时导入多个模块

常用模块

序列化模块

json模块:

Json模块提供了四个功能:dumps、dump、loads、load。

dump和load为对文件的操作。

import json

dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic)
# 序列化:将一个字典转换成一个字符串

print(type(str_dic),str_dic)
dic2 = json.loads(str_dic)
print(type(dic2),dic2)
# 反序列化:将一个字符串格式的字典转换成一个字典

list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic)
print(type(str_dic),str_dic)

list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2)

pickle模块

用于python特有的类型 和 python的数据类型间进行转换。

import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = pickle.dumps(dic)
print(str_dic)

dic2 = pickle.loads(str_dic)
print(dic2)

import time
struct_time = time.localtime(time.time())
print(struct_time)
f = open('pickle_file','wb')
pickle.dump(struct_time,f)
f.close()

f = open('pickle_file','rb')
struct_time2 = pickle.load(f)
print(struct_time2.tm_year)

os模块

image-20240420194332154

re模块(正则表达式)

image-20240413153441857

url = '<img width="100" alt="(.*?)" src="(.*?)" class="">'

day5

异常处理

try:
    a = 'a'
    a = int(a)
except:
    print('发生错误')

image-20240420194114017

垃圾回收机制

如何管理内存:

如何优化内存:

day6

面向对象

class Light:#创建类
    def __init__(self, color):#类的初始化属性
        self.color = color

    def changecolor(self):#类的方法
        pass

class Redlight(Light):#创建类redlight继承light
    def changecolor(self):
        print('红灯停')


if __name__ == "__main__":
    ludeng = Redlight('red')#实例化
    ludeng.changecolor()#调用类的方法
    print(ludeng.__dict__)

继承

父类私有化

  • 父类的对象不能直接访问 __num2 属性
  • 父类的对象不能在 demo 方法内访问 __num2 属性
  • 父类的对象可以在 demo 方法内,调用父类的 test 方法
  • 父类的 test 方法内部,能够访问 __num2 属性和 __test 方法
class a:
    def __eat(self):
        print('eat')
class b(a):
    pass
b = b()
b.eat()

封装

  1. 封装 是面向对象编程的一大特点
  2. 面向对象编程的 第一步 —— 将 属性方法 封装 到一个抽象的
  3. 外界 使用 创建 对象,然后 让对象调用方法
  4. 对象方法的细节 都被 封装类的内部
class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def detail(self):
        print(self.name)
        print(self.age)

obj1 = Foo('chensong',18)
obj2 = Foo('aaron',16)

print(obj1.name)
print(obj2.age)
# 通过对象直接调用被封装的内容

obj1.detail()
obj2.detail()
# 通过self间接调用被封装的内容

多态

鸭子类型

class Duck:
    def quack(self):
        print("嘎嘎叫!")

    def fly(self):
        print("扑哧扑哧的飞!")


class Person:
    def quack(self):
        print("我喜欢跟鸭子一样嘎嘎叫")

    def fly(self):
        print("我也喜欢跟鸭子一样飞")


def make_it_quack_and_fly(obj):
    obj.quack()
    obj.fly()


duck = Duck()
person = Person()

make_it_quack_and_fly(duck)
make_it_quack_and_fly(person)。

类的约束

  1. 提取⽗类. 然后在⽗类中定义好⽅法. 在这个⽅法中什么都不⽤⼲. 就抛⼀个异常就可以了. 这样所有的⼦类都必须重写这个⽅法. 否则. 访问的时候就会报错.
  2. 使⽤元类来描述⽗类. 在元类中给出⼀个抽象⽅法. 这样⼦类就不得不给出抽象⽅法的具体实现. 也可以起到约束的效果.
  3. 先用第一种方法解决问题
class Payment:
    """
    此类什么都不做,就是制定一个标准,谁继承我,必须定义我里面的方法。
    """
    def pay(self,money):
        raise Exception("你没有实现pay方法")

class QQpay(Payment):
    def pay(self,money):
        print('使用qq支付%s元' % money)

class Alipay(Payment):
    def pay(self,money):
        print('使用阿里支付%s元' % money)

class Wechatpay(Payment):
    def fuqian(self,money):
        print('使用微信支付%s元' % money)


def pay(obj,money):
    obj.pay(money)

a = Alipay()
b = QQpay()
c = Wechatpay()
pay(a,100)
pay(b,200)
pay(c,300)

super()

继承类调用被继承类中的方法。

class A:
    def f1(self):
        print('in A f1')

    def f2(self):
        print('in A f2')


class Foo(A):
    def f1(self):
        super().f2()
        print('in A Foo')


obj = Foo()
obj.f1()

day7

socket

  • TCP(Transmission Control Protocol)
    • 可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;文件传输程序。
  • UDP(User Datagram Protocol)
    • 不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文(数据包),尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

TCP

服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

import socket
# 初始化格式如下
socket.socket(socket_family,socket_type,protocal=0)
# socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为 0。

# 获取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用 'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。
# 例如
tcpSock = socket(AF_INET, SOCK_STREAM)

UDP

服务器端先初始化Socket,然后与端口绑定(bind),recvform接收消息,这个消息有两项,消息内容和对方客户端的地址,然后回复消息时也要带着你收到的这个客户端的地址,发送回去,最后关闭连接,一次交互结束

服务端:

import socket
udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
udp_sk.bind(('127.0.0.1',9000))        #绑定服务器套接字
msg,addr = udp_sk.recvfrom(1024)
print(msg)
udp_sk.sendto(b'hi',addr)                 # 对话(接收与发送)
udp_sk.close()                         # 关闭服务器套接字

客户端:

import socket
ip_port=('127.0.0.1',9000)
udp_sk=socket.socket(type=socket.SOCK_DGRAM)
udp_sk.sendto(b'hello',ip_port)
back_msg,addr=udp_sk.recvfrom(1024)
print(back_msg.decode('utf-8'),addr)

粘包

1.接收方没有及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

2.发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据也很小,会合到一起,产生粘包)

struct模块

import struct
# 将一个数字转化成等长度的bytes类型。
ret = struct.pack('i', 18334)
print(ret, type(ret))

# 通过unpack反解回来 返回一个元组回来
ret1 = struct.unpack('i',ret)[0]
print(ret1, type(ret1))

# 但是通过struct 处理不能处理太大

multiprocess模块

multiprocess.process模块介绍

image-20240420195047821

创建进程:

import os
from multiprocessing import Process

def f(x):
    print('子进程id:',os.getpid(),'父进程id:',os.getppid()) #查看子进程id:os.getpid(),查看父进程id:os.getppid()
    return x*x

if __name__ == '__main__':
    print('主进程id: ',os.getpid())
    p_lst = []
    for i in range(5):
        p = Process(target=f,args=(i,))
        p.start()

守护进程

import os
import time
from multiprocessing import Process

class Myprocess(Process):
    def __init__(self,person):
        super().__init__()
        self.person = person
    def run(self):
        print(os.getpid(),self.name)
        print('%s正在和女主播聊天' %self.person)

if __name__ == '__main__':
    p=Myprocess('陈松')
    p.daemon=True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行
    p.start()
    time.sleep(10) # 在sleep时查看进程id对应的进程
    print('主')