Python 笔记 基础 流程控制 if
if实现的三目运算符
字符串 格式化字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 print (1 )print (1 ,2 ,3 ,4 )a = 1 b = 2.1123 c = 'hello' s = 'a = %d b = %f c = %s' % (a,b,c) s += ' -- world' print (s)s = f'a = {a} b = {b} c = {c} ' print (s)s = 'a = {0:5d} b = {1:.2f} c = {0}' .format (a,b,c) print (s)
字符串切片 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 s = '0123456789' print (s[0 :5 :1 ])print (s[0 :5 :2 ])print (s[3 :6 ]) print (s[:5 ]) print (s[5 :]) print (s[:]) print (s)print (s[10 :20 ]) print (s[-1 :-5 ])print (s[-1 :-5 :-1 ])print (s[::-1 ])
列表 列表推导式 1 2 格式: 列表变量 = [表达式 for 变量 in range (10 )] 表达式中需要使用后面的变量
函数 不定长参数 1 2 3 def some_func (*args): print (args) print (*args)
关键字参数
1 2 3 def some_func (arg1, arg2=1 ): pass some_func(1 , arg2 = 2 )
不定长关键字参数
1 2 3 def some_func (**kwargs): print (kwargs) some_func(arg1=1 , arg2 = 2 )
多种参数混合
1 2 3 4 def some_func4 (arg1, arg2, arg3, *args, arg4=1 , arg5=2 , **kwargs): print (arg1, arg2, arg3, ,arg4, arg5) print (args) print (kwargs)
作用域 Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:
1 2 3 4 5 6 >>> if True :... msg = 'I am from Runoob' ... >>> msg'I am from Runoob' >>>
匿名函数 lambda 格式: lambda [形参1], [形参2], … : [单行表达式] 或 [函数调用]
lambda定义和普通函数的区别:
lambda 没有函数名
lambda 参数列表外没有括号
lambda 函数体中,只能实现简单的表达式计算或函数调用
lambda 函数体中,不能使用Return,if,while,for-in 这些都不行
lambda 函数体中,可以使用if 实现的三目运算符.
使用场景: 变量 = lambda ….
一般情况下,因为lambda的局限性,使得他不能实现复杂功能,只能实现一些简单功能 那么在使用时,一般会实现一个简单的,一次性使用的场景
使用场景
1 2 3 4 list = [1 ,2 ,3 ,4 ,5 ]result = funtools.reduce(lamdba a,b: a + b, list ) result = map (lamdba a: a ** 2 , list )
高阶函数 reduce 函数会对参数序列中元素进行累积
1 2 #import funtools result = funtools.reduce(lamdba a,b: a + b, list) # 对列表进行累加
map 1 result = map (lamdba a: a ** 2 , list )
filter 1 2 3 list = [1 ,2 ,3 ,4 ,5 ,6 ]ret = filter (lamdba a: a%2 ==0 , list ) print (list (ret))
sort 1 2 3 4 5 6 7 8 9 10 11 12 13 list = [7 ,2 ,3 ,4 ,2 ,1 ,2 ]list .sort()my_list = [{'id' : 1 ,'name' : 'tom' ,'age' :12 },{'id' : 3 ,'name' : 'rose' ,'age' :32 },{'id' : 2 ,'name' : 'Jack' ,'age' :22 }] my_list.sort(key=lambda d: d['age' ],reverse=True ) print (my_list)
类 私有属性和方法 1 2 3 4 5 6 7 8 class Person (object ): def __init__ (self, name, age ): self.name = name self.__age = age def __some_func (self ): pass
继承 python支持多继承
1 2 3 4 5 class 类名 (父类名1 ,.....): pass
类方法和静态方法 1 2 3 4 5 6 7 8 9 @classmethod def some_method (): pass @staticmethod def some_method (): pass
导入模块 导入单独模块 1 2 3 4 5 6 7 8 import 模块名import 模块名 as 别名from 模块名 import 成员名from 模块名 import 成员名 as 成员别名from 模块名 import *
导入包中的模块 1 2 3 4 5 6 7 import 包名.模块名 -> 包名.模块名.成员from 包名 import 模块名 -> 模块名.成员from 包名.模块名 import 成员名 -> 直接使用成员from 包名.模块名 import * -> 直接使用成员import 包名from 包名 import *
模块搜索路径 a. 当前程序所在同级目录 b. 当前程序所在工程的根目录 c. PYTHONPATH 环境变量中设置的目录 d. 系统目录 e. site-packages 这个第三方模块安装目录
包 包就是一个文件夹 包和普通文件夹的功能在于 包中有一个 init .py 文件 (导入包时,指定可以导入的模块有哪些)
__name__ 如果__name__ 出现在当前执行的模块中时,得到的值是 main 这个字符串,用来表示执行的是当前文件 如果__name__ 出现在在了被导入模块中时,得到的值是被导入模块的模块名
异常 异常捕获 1 2 3 4 5 try :except Exception: else : finally :
自定义异常 1 2 3 4 5 6 7 8 9 class 异常名Error (Exception ): def __init__ (self,msg='' ): self.__msg = msg def __str__ (self ): return self.__msg raise 异常对象
文件读写 文件的读写方式 以文本方式打开方式的模式 r -> rt -> read text 以文本方式打开文件读,文件存在,打开成功,文件不存在,打开失败 w -> wt -> write text 以文本方式打开文件写,不管文件是否存在,都会新创建一个新文件 a -> at -> append text 以文件方式打开文件追加,文件不存在,创建文件,文件存在,那么打开文件然后将光标移动到文件的最后
以二进制形式打开文件的模式 rb 以二进制形式打开文件读取 wb 以二进制形式打开文件写入 ab 以二进制形式打开文件追加
(了解) r+ 可读可写 不会创建不存在的⽂件 从顶部开始写 会覆盖之前此位置的内容 w+ 可读可写 如果⽂件存在 则覆盖整个⽂件不存在则创建 a+ 可读可写 从⽂件顶部读取内容 从⽂件底部添加内容 不存在则创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 file = open ('static' + path, 'rb' ) file.read() file.write('内容' ) file.close() read() read(size) readline() readlines() write(content) 该函数用来向文件中写入数据 前提: 使用该函数时,打开文件时,必须要给定写入权限,要具有写入模式
with as 打开文件 使用 with as 操作已经打开的文件对象(本身就是上下文管理器),无论期间是否抛出异常,都能保证 with as 语句执行完毕后自动关闭已经打开的文件。
1 2 with open ('a.txt' , 'a' ) as f: f.write("文件内容" )
文件和文件夹操作 1 2 3 4 5 6 7 8 os 模块 rename() remove() mkdir() getcwd() chdir() listdir() 掌握 rmdir()
注意点 当以二进制模式打开文件进行文件操作时. read 函数最终读取文件内容为空时,返回的结果为 b’’ 表示是一个二进制的空字符串 在 Python2.7版本中. ‘’ == b’’ 结果为True 在 Python3.6版本中. ‘’ == b’’ 结果为False
多任务 进程 一个程序运行后至少有一个进程,一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程。
进程简单用法 1 2 3 4 5 6 import multiprocessingsub_process = multiprocessing.Process (target=任务名) sub_process.start()
Process进程类的说明 Process([group [, target [, name [, args [, kwargs]]]]])
group:指定进程组,目前只能使用None
target:执行的目标任务名
name:进程名字
args:以元组方式给执行任务传参
kwargs:以字典方式给执行任务传参
Process创建的实例对象的常用方法:
start():启动子进程实例(创建子进程)
join():等待子进程执行结束
terminate():不管任务是否完成,立即终止子进程
Process创建的实例对象的常用属性:
name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
多进程示例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import multiprocessingimport timedef dance (): for i in range (5 ): print ("跳舞中..." ) time.sleep(0.2 ) def sing (): for i in range (5 ): print ("唱歌中..." ) time.sleep(0.2 ) if __name__ == '__main__' : dance_process = multiprocessing.Process(target=dance, name="myprocess1" ) sing_process = multiprocessing.Process(target=sing) dance_process.start() sing_process.start()
获取当前进程信息 1 2 3 4 5 6 multiprocessing.current_process() os.getpid() os.getppid()
进程的传参方式
元组方式传参(args) : 元组方式传参一定要和参数的顺序保持一致。
字典方式传参(kwargs) : 字典方式传参字典中的key一定要和参数名保持一致。
1 2 3 4 5 sub_process = multiprocessing.Process(target=task, args=(5 ,)) sub_process = multiprocessing.Process(target=task, kwargs={"count" : 3 })
进程注意点
进程之间不共享全局变量
主进程会等待所有的子进程执行结束再结束
主进程退出时销毁子进程
主进程结束时手动销毁子进程
sub_process.terminate()
设置守护主进程
子进程对象.daemon = True
线程 线程是cpu调度的基本单位,每个进程至少都有一个线程,而这个线程就是我们通常说的主线程。
线程的简单用法 1 2 3 4 5 import threadingthread = threading.Thread(target=任务名) thread.start()
线程类Thread参数说明 Thread([group [, target [, name [, args [, kwargs]]]]])
group: 线程组,目前只能使用None
target: 执行的目标任务名
args: 以元组的方式给执行任务传参
kwargs: 以字典方式给执行任务传参
name: 线程名,一般不用设置
线程的传参方式
元组方式传参(args) :元组方式传参一定要和参数的顺序保持一致。
**字典方式传参(kwargs)**:字典方式传参字典中的key一定要和参数名保持一致。
线程注意点
线程之间执行是无序的
主线程会等待所有的子线程执行结束再结束
线程之间共享全局变量
线程之间共享全局变量数据出现错误问题
设置守护线程
threading.Thread(target=someTarget, daemon=True)
线程对象.setDaemon(True)
线程之间共享全局变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 data_list = list () def write_data (): data_list.append('数据' ) def read_data (): print ("read_data:" , data_list) if __name__ == '__main__' : write_thread = threading.Thread(target=write_data) read_thread = threading.Thread(target=read_data)
互斥锁 对共享数据进行锁定,保证同一时刻只能有一个线程去操作。
1 2 3 4 5 6 7 8 9 10 mutex = threading.Lock() mutex.acquire() ...这里编写代码能保证同一时刻只能有一个线程去操作, 对共享数据进行锁定... mutex.release()
使用互斥锁需避免死锁,加锁后必须解锁
进程和线程对比 关系对比
线程是依附在进程里面的,没有进程就没有线程。
一个进程默认提供一条线程,进程可以创建多个线程。
区别对比
进程之间不共享全局变量
线程之间共享全局变量,但是要注意资源竞争的问题,解决办法: 互斥锁或者线程同步
创建进程的资源开销要比创建线程的资源开销要大
进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
线程不能够独立执行,必须依存在进程中
多进程开发比单进程多线程开发稳定性要强
优缺点对比
小结
进程和线程都是完成多任务的一种方式
多进程要比多线程消耗的资源多,但是多进程开发比单进程多线程开发稳定性要强,某个进程挂掉不会影响其它进程。
多进程可以使用cpu的多核运行,多线程可以共享全局变量。
线程不能单独执行必须依附在进程里面
网络编程 客户端流程
创建客户端套接字对象
和服务端套接字建立连接
发送数据
接收数据
关闭客户端套接字
服务端流程
创建服务端端套接字对象
绑定端口号
设置监听
等待接受客户端的连接请求
接收数据
发送数据
关闭套接字
socket 导入 socket 模块
import socket
创建客户端 socket 对象
socket.socket(AddressFamily, Type)
参数说明:
AddressFamily 表示IP地址类型, 分为IPv4和IPv6
Type 表示传输协议类型
方法说明:
connect((host, port)) 表示和服务端套接字建立连接, host是服务器ip地址,port是应用程序的端口号
send(data) 表示发送数据,data是二进制数据
recv(buffersize) 表示接收数据, buffersize是每次接收数据的长度
客户端示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 ''' 基于socket实现的TCP客户端 ''' import socketclient_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client_socket.connect(('192.168.13.73' ,6666 )) data = 'hello,你好' data = data.encode() client_socket.send(data) recv_data = client_socket.recv(1024 ) print ('未解码:' , recv_data)recv_data = recv_data.decode('utf-8' ) print ('解码后:' , recv_data)client_socket.close()
服务端示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 ''' 基于socket实现的TCP服务端 ''' import socketserver_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True ) server_socket.bind(('' ,7777 )) server_socket.listen(128 ) client_socket, ip_port = server_socket.accept() print (f'客户端 {ip_port[0 ]} 使用端口 {ip_port[1 ]} 连接成功...' )data = client_socket.recv(1024 ) if len (data) != 0 : data = data.decode('utf-8' ) print (f'客户端 {ip_port[0 ]} 发送的数据是 {data} ...' ) else : print (f'客户端 {ip_port[0 ]} 关闭了连接...' ) data = '你好也' .encode('utf-8' ) client_socket.send(data) client_socket.close() server_socket.close()
多进程http服务器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 ''' 使用进程实现多任务面向对象返回指定数据的静态web服务器 ''' import socketimport multiprocessingclass StaticWebServer (object ): def __init__ (self,port ): self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True ) self.server.bind(('' , port)) self.server.listen(128 ) def start (self ): while True : client, ip_port = self.server.accept() print (f'客户端 {ip_port[0 ]} 使用 {ip_port[1 ]} 端口连接成功....' ) p = multiprocessing.Process(target=self.task,args=(client,)) p.start() self.server.close() def task (self, client ): request_data = client.recv(1024 ).decode() if len (request_data) == 0 : client.close() else : request_path = request_data.split(' ' )[1 ] print ('请求地址是:' , request_path) if request_path == '/' : request_path = '/index.html' try : with open ('static' + request_path, 'rb' ) as file: file_content = file.read() except Exception as e: response_line = 'HTTP/1.1 404 NOT FOUND\r\n' response_head = 'Server: PSWS1.1\r\n' with open ('static/error.html' ,'r' ) as f: error_data = f.read() response_data = (response_line + response_head + '\r\n' + error_data).encode() client.send(response_data) else : response_line = 'HTTP/1.1 200 OK\r\n' response_head = 'Server: PSWS1.1\r\n' with open ('static' + request_path, 'rb' ) as f: response_body = f.read() response_data = (response_line + response_head + '\r\n' ).encode() + response_body client.send(response_data) finally : client.close() if __name__ == '__main__' : StaticWebServer(8888 ).start()