Python基础知识笔记
=================Python基础知识相关笔记=====================
- / 表示浮点数除法,//表示整数除法,返回不大于结果的一个最大的整数。
- 操作系统的作用:
- 把硬件丑陋负责的接口隐藏起来,为应用程序提供良好接口
- 管理,调用进程,并且把进程之间对硬件的竞争变得有序化
- linux下的
- 多道技术:
- 产生背景:为了实现单CPU下的并发效果
- 分为两部分:
- 空间上的复用(必须实现硬件层面的隔离)
- 时间上的复用(复用CPU时间片)
- 什么时候切换?
- 正在执行的任务遇到阻塞
- 正在执行的任务运行时间过长
- 什么时候切换?
- 进程介绍
- 正在进行的一个过程或者说一个任务。而负责执行任务的则是cpu。
- 进程与程序的区别:
- 程序仅仅只是一堆代码而已,而进程指的是程序运行的过程。
- 同一个程序执行两次,那也是两个进程。 比如打开暴风影音。虽然是同一个软件,一个播放的是苍空井,一个播放的是饭岛爱。
- 并发与并行:
- 无论是并行还是并发,在用户看来都是同时运行的,不管是进程还是线程,都只是一个任务而已,真正干活的是cpu,cpu来做这些任务,而一个cpu同一时刻只能执行一个任务
- 并行:真正的同时运行,只是具备多个cpu才能实现并行
- 并发:伪并行,即看起来是同时运行。单个cpu+多道基数就可以实现并发(并行也属于并发)
- 同步与异步:
- 同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,知道收到返回消息才继续执行下去。
- 异步是指进行不需要一直等下去,而是继续执行下面的操作不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
- 举个例子:打电话就是同步通信,发短信就是异步通信。
- 系统的调用:
- linux:fork
- win:CreateProgress
- linux下的进程与windows下的区别:
- linux的进程有父子关系,是一种树形结构,windows没有这种关系
- linux创建新的进程需要copy 父进程的地址空间,wind下从最开始创建进程,两个进程之间就是不一样。
- 线程介绍:
- 在传统操作系统中,每个进程都有一个地址空间,而且默认就有一个控制线程。
- 进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是CPU上的执行单位。eg: 北京地铁是一个进程,地铁里的13号线是一个线程。
- 多线程指的是:在一个进程哩开启多个线程,简单的讲:如果多个任务公用一块地址空间,那么必须在一个进程内开启多个线程。
- 为何要用多线程:
- 多线程共享一个进程的地址空间
- 线程比进程更轻量级,线程比进程更容易撤销,在许多操作系统中,创建一个线程比创建一个进程要快10~100倍,在有大量线程需要动态和快速修改时,这一特性很有用
- 对于计算/CPU密集型的应用,多线程并不能提升性能,但对于I/O密集型应用,使用多线程会明显的提升速度(I/O密集型根本用不上多核优势)
- 在多CPU系统中,为了最大限度的利用多核,可以开启多个线程(比开进程开销要小的多)
- 异常处理
- 什么时候用异常处理
- try...except 应该尽量少用,因为它本身就是你附加给你程序的一种异常处理的逻辑,与你的主要工作是没有关系的,这种东西加的多了,会导致你的代码可读性变差。只有在有些异常无法预知的情况下,才应该加上 try...except ,其他的逻辑错误应该尽量修正
- 什么时候用异常处理
- Socket
- 服务端
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET: internet网络;SOCK_STREAM: TCP 流式协议
phone.bind(('127.0.0.1', 8081)) # 相当于插电话卡
phone.listen(5) # 相当于开机
print('starting')
while True: # accept 连接循环
conn, address = phone.accept() # 相当于接听电话
print('client is coming ', address)
while True: # 与conn的通讯循环
try: # 针对windows下,当client断掉之后,会抛异常,需要加一个try except
client_message = conn.recv(1024) # 读取客服端发过来的消息,收消息
if not client_message: break # 在linux机器上,不会识别到client断掉的消息,会不断的收空消息。此时需要加一个判断。
conn.send(client_message.upper()) # 回消息
except Exception: # 捕捉通讯终端异常
break
conn.close() # 挂电话
phone.close() # 关机 - 客户端
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8083)) # 连接服务器的地址
while True:
msg = input('>>>:').strip()
if not msg: continue # 防止客户端发空,当是空消息时,继续输入
phone.send(msg.encode('utf-8')) # 不能直接发字符串,需要发二进制的形式的文件
back_message = phone.recv(1024) # 接受返回的消息
print(back_message.decode('utf-8'))
phone.close() - 通过 socket 实现 远程执行命令:ls,pwd等
- 服务端
mport socket
import subprocess
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET: internet网络;SOCK_STREAM: TCP 流式协议
phone.bind(('127.0.0.1', 8082))
phone.listen(5)
print('starting')
while True:
conn, address = phone.accept()
print('client is coming ', address)
while True:
try:
cmd = conn.recv(1024)
print('receive')
if not cmd: break
res = subprocess.Popen(cmd.decode('utf-8'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
err = res.stderr.read()
if err:
cmd_res = err
print('error')
else:
cmd_res = res.stdout.read()
print('wokao cmd_res', cmd_res)
conn.send(cmd_res)
except Exception:
break
conn.close()
phone.close() - 客户端
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8082)) # 连接服务器的地址
while True:
cmd = input('>>>:').strip()
if not cmd: continue # 防止客户端发空,当是空消息时,继续输入
phone.send(cmd.encode('utf-8')) # 不能直接发字符串,需要发二进制的形式的文件
cmd_res = phone.recv(1024) # 接受返回的消息
print(cmd_res.decode('utf-8'))
phone.close() - 自定义表头解决粘包的问题。
- 只有TCP有粘包,UDP则没有粘包现象。所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
- 服务端:
import socket
import subprocess
import struct
import json
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET: internet网络;SOCK_STREAM: TCP 流式协议
phone.bind(('127.0.0.1', 8082))
phone.listen(5)
print('starting')
while True:
conn, address = phone.accept()
print('client is coming ', address)
while True:
try:
cmd = conn.recv(1024)
print('receive')
if not cmd: break
res = subprocess.Popen(cmd.decode('utf-8'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
err = res.stderr.read()
if err:
cmd_res = err
print('error')
else:
cmd_res = res.stdout.read()
print('wokao cmd_res', cmd_res)
# conn.send(struct.pack('i', len(cmd_res))) # 先发报头,报头 i 格式,会生成 int 类型的4个字节的报头
head_dic = {'filename': None, 'hash': None, 'total_size': len(cmd_res)}
head_json = json.dumps(head_dic)
head_bytes = head_json.encode('utf-8')
conn.send(struct.pack('i', len(head_bytes))) # 先发送报头的长度
conn.send(head_bytes) # 再发送报头的bytes
conn.send(cmd_res) # 最后发送真实是数据
except Exception:
break
conn.close()
phone.close() - 客户端
import socket
import struct
import json
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8082)) # 连接服务器的地址
while True:
cmd = input('>>>:').strip()
if not cmd: continue # 防止客户端发空,当是空消息时,继续输入
phone.send(cmd.encode('utf-8')) # 不能直接发字符串,需要发二进制的形式的文件
# 先收报头的长度
head_struct = phone.recv(4)
head_len = struct.unpack('i', head_struct)[0]
# 再收报头的bytes
head_bytes = phone.recv(head_len)
head_json = head_bytes.decode('utf-8')
head_dic = json.loads(head_json)
print(head_dic)
# 最后根据报头里面的详细信息读取真实数据
total_size = head_dic['total_size']
receive_size = 0
data = b''
while receive_size < total_size:
receive_data = phone.recv(1024)
data += receive_data
receive_size += len(receive_data)
print(data.decode('utf-8'))
phone.close()
- 服务端
- 服务端
- metaclass 元类
- 反射
- 定义: 通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
- 四个方法,适用于类和对象
- hasattr(object,name) # 判断obj下是否有 name 方法
- getattr(object,name, defatult=None) # getattr(p,'x','not exist') 判断p下面是否有x方法,如果没有则返回‘not exist’
import ftpclient
f1 = ftpclient.FtpClient('192.168.1.150')
if hasattr(f1, 'get'): # 通过反射来判断 f1 中是否有get方法,如果有该方法则执行该方法
func = getattr(f1, 'get') # 得到 f1 的 get方法,然后执行它
func()
else:
print('没有该方法,执行其他操作') - setattr(obj,name,value) #setattr(p,'x', 12123232423) # 给 obj 下的name 赋值
- delattr(x,y) # delattr(Chinese,'country') # 删除 Chinese 下的 country 属性
-
class Ftpclient:
def __init__(self,host):
self.host = host
print('ready to connecting')
def run(self):
while True:
inp = input('---->请输入命令').strip()
inp_l = inp.split()
if hasattr(self, inp_l[0]):
func = getattr(self, inp_l[0])
func(inp_l)
else:
print('没有该命令')
def get(self, arg):
print('downloading file ', arg[1])
def ls(self, arg):
print('list the file', arg)
f = Ftpclient('192.168.1.1')
f.run()
- 模块:
- 定义:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
- import 倒入模块干的事情:eg: import spam
- 产生新的名称空间
- 以新建的名称空间为全局名称空间,执行文件的代码执行文件的代码
- 拿到一个模块名spam,指向spam.py产生的名称空间。
- 产生新的名称空间
- 以新建的名称空间为全局名称空间,执行文件的代码执行文件的代码
- 直接拿到的就是 spam.py 产生的名称空间中的名字。
- 优点:方便,不用加前缀。缺点:容易跟当前文件的名称空间冲突
- from xxx improt * // 导入所有。
- __all__=[a,b,c] //__all__ 用来控制 import * 来导入什么。
- import模块之后,模块的查找搜索路径:
- 先在内存中查找,再查找内置函数,最后再 sys.path 路径
- 如果自己写的模块,无法import的时候,就需要操作 sys.path 路径
- import sys
- sys.path.appen('路径') 如果想优先级高: sys.path.insert(0,'路径')
- 这样就可以 import了。
- 包:
- 定义:包是一种通过使用:".模块名" 来组织python模块名称空间的方式。
- 无论是import形式还是 from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
- 包是目录级别的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
- 定义:包是一种通过使用:".模块名" 来组织python模块名称空间的方式。
- __name__控制python文件在不同用途下的行为:
- 当 XXX.py 当作脚本执行时,__name__ = ‘__main__’
- 当 XXX.py 当作模块导出时,__name__ = 模块名(XXX)
- 递归函数与二分法:
- 定义:在调用函数过程总,直接或间接地调用函数本身,这就是函数的递归调用。
- 应用:
- 二分法:
-
# 使用递归的方式来生成斐波那契数列:1、1、2、3、5、8、13、21、34。。。。。
# 格式如此:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
# 数列从第3项开始,每一项都等于前两项之和。
def recur_fibo(n):
if n <=1 :
return n
else:
return (recur_fibo(n-1) + recur_fibo(n-2))
nterms = int(input('请输出几项'))
if nterms <= 0:
print('请输入正数')
else:
print('开始输出斐波那契数列')
for i in range(1,nterms+1):
print(recur_fibo(i)) -
list_a = [1,99,88,77,49,102,53,4,9,80,89]
list_sorted = sorted(list_a)
def search(find_num, li):
if len(li) == 0:
print('not exits')
return
mid_index = len(li) // 2
mid_num = li[mid_index]
if find_num > mid_num:
li = li[mid_index+1:] # 给li 重新赋值一次。
print(li)
search(find_num, li)
elif find_num < mid_num:
li = li[:mid_index]
print(li)
search(find_num,li)
else:
print('find it')
search(0,list_sorted)
- 面向过程的程序设计:是一种流水线式的编程思路,是机械式的
- 优点:程序的结构清晰,可以把负责的问题简单化
- 缺点:扩展性差
- 应用场景:linux内核,git,httpd
- 名称空间与作用域
- 内置名称空间
- 全局名称公交
- 局部名称空间
- 内置和全局名称空间属于全局范围,全局作用域:全局有效,在任何位置都能被访问到,除非被删除(del),否则存活到文件执行结束
- 局部名称空间,局部作用域:局部有效,只能在函数内部被访问到,在函数执行结束后,就释放了。
- 函数对象(第一类对象):
- 函数可以被当数据来传递
- 可以被引用
- 可以当作参数传递给另外一个函数
- 可以作为函数的返回值
- 可以当作容器类型的元素
- 内置函数
- 匿名函数:lambda 只使用一次的函数就用匿名函数
- def func(x,y): return x+y 就是有名函数
- lambda x,y: x+y
- max,min, sorted, zip
-
def func(x,y):
return x + y
# 等同于 func
lambda x, y: x+y
#
salary = {
'egon': 3000,
'alex': 100000,
'better': 20000000,
'hello': 2000
}
print(max(salary)) # 默认按照key值进行比较,最大的值输出来
print(max(salary, key=lambda x: salary[x])) # 按照 value值进行排序,将最大的 key 值输出来
print(min(salary, key=lambda x: salary[x]))
print(sorted(salary, key=lambda x: salary[x])) # 按照value值从小到大进行排序,然后输出 key值。
print(sorted(salary, key=lambda x: salary[x], reverse=True)) # 按照value值从大到小进行排序,然后输出 key值。# res = zip(salary.values(), salary.keys()) # 生成元组对象。
# print(list(res))
-
- map, reduce, filter
-
# map 映射函数,列表+一个 SB 后缀
#
l = ['alex', 'wupeiqi', 'yuanhao']
g = map(lambda x: x + 'SB', l)
print(list(g))
# num元素各自平方 一下
num = [2, 4, 9 ,10]
n = map(lambda x: x**2, num)
print(list(n))
# reduce 合并函数(累积函数),在python2里面,是作为内置函数存在的,在python3里面,则放在了 functools 里面。应用场景:hadloop 大数据
from functools import reduce
numlist = [1,3,5,7,9]
# 求所有元素相加只和
sum = reduce(lambda x,y: x+y, numlist, 10) # 第一个参数是个函数:lambad,第二个参数是一个迭代器。
# 第三个参数是初始值,如果默认没有的话,则为:1+3+5+7+9。如果有初始值的话,则为:10+1+3+5+7+9
print(sum)# filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
# 该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,
# 最后将返回 True 的元素放到新列表中
# 应用1: 过滤出 以SB为结尾的 列表元素
l = ['w_SB', 'b_SB', 'c', 'd_SB']
g = filter(lambda x: x.endswith('SB'), l)
print(list(g))
# 应用2:过滤出列表中所有的奇数
l1 = [1,2,3,4,5,6,7,8]
def is_odd(n):
return n % 2 == 1
new_list = filter(is_odd, l1)
print(list(new_list))
# 应用3:过滤出1~100中平方根是整数的数:
import math
def is_sqr(x):
return math.sqrt(x) %1 == 0
sqr = filter(is_sqr, range(1,101))
print(list(sqr))
-
- 匿名函数:lambda 只使用一次的函数就用匿名函数
- 生成器
- 概念:只要函数体包含yield关键字,该函数就是生成器函数。生成器函数就是迭代器
- yield的功能:
- 相当于为函数封装好__iter__和__next__
- return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行
- yield的两种形式
- 语句形式:yield 1
- 表达式形式:x = yield,下面是表达式形式的使用方法
-
def eater(name):
print(' %s ready to eat' % name)
while True:
food = yield
print('%s start to eat %s' % (name, food))
g = eater('zhang')
next(g) # next() 就相当于 g.send(None),执行 g.send() 之前必须next(g)一次,或者执行 g.send(None)一次。
g.send('wo')
# 可以尝试用一个装饰器,在执行eater() 之前,就初始化,执行了,g.send(None),如下所示:
def init(func):
def wrapper(*args, **kwargs):
g = func(*args,**kwargs)
next(g)
return g
return wrapper
@init
def eater(name):
print('%s ready to eat' % name)
while True:
food = yield
print('%s start to eat %s' % (name, food))
g = eater('zhang') # 输出:zhang ready to eat
g.send('shit') # 输出:zhang start to eat shit
print(g.send('shit2')) # 会输出 None ,原因是 yield 后面没有值,如果想要输出值, yield后面需要有值。
# 如果每次打印上了什么菜。就需要在yield后面加上数据
def init(func):
def wrapper(*args, **kwargs):
g = func(*args,**kwargs)
next(g)
return g
return wrapper
@init
def eater(name):
print('%s ready to eat' % name)
foodlist = []
while True:
food = yield foodlist
foodlist.append(food)
print('%s start to eat %s' % (name, food))
g = eater('zhang') # 输出:zhang ready to eat
#g.send 表示先把shit 赋值给yield,然后由yield再赋值给 food
g.send('shit') # 输出:zhang start to eat shit
print(g.send('shit2')) # 会输出 None ,原因是 yield 后面没有值,如果想要输出值, yield后面需要有值。
print(g.send('shit3'))
-
-
# 通过yeild来实现 【grep -rl 'python' /root 】这个linux命令,意思是:通过递归的方式 找到root目录下所有包含 python 内容的文件名
# os.walk 方法是用来遍历路径的。 r 参数表示用路径用"原生字符串"进行遍历 。意思是"\" python 解释器就不要处理了,r=raw-string。
# 在windows环境需要用 r。在linux下则不需要了
import os
# address = os.walk(r'/Users/zhangzhihui/Desktop/Python/Basic/A')
#
# def search(search_path):
# address = os.walk(search_path)
# for par_dir, _, files in address: # 这里有三个值,【par_dir, _, files】par_dir 表示父目录,
# # _表示子目录(不需要子目录的话,用_表示就可以了),files表示子文件
# for file in files:
# file_abs_path = par_dir + '/' + file
# print(file_abs_path)
#
# search('/Users/zhangzhihui/Desktop/Python/Basic/A')
# 上面的方法只能search一次,如果需要多次执行 search的话,就需要用 yield 方法了,因为yield生成器函数每次都需要执行一次 next(),
# 否则就会报错,所以需要加一个装饰器,让装饰器来每次执行一下 next()方法。 如下代码所示:
def init(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
next(res)
return res
return wrapper
# @init
# def search():
# while True:
# search_path = yield
# address = os.walk(search_path)
# for par_dir, _, files in address:
# print(par_dir)
# for file in files:
# file_abs_path = par_dir + '/' + file
# print(file_abs_path)
# g = search() #search()就是一个生成器
# g.send('/Users/zhangzhihui/Desktop/Python/Basic') # 此时会将 该目录下的所有文件都遍历出来
# 写一个open函数,源源不断的读取传过来的路径,然后打开路径下的文件。
# @init
# def opener():
# while True:
# file_abs_path = yield # 生成器 send一次,会传一次值给 yield 然后赋值给 file_abs_path
# print(file_abs_path)
# # with open(file_abs_path,encoding='utf-8') as f:
# # pass
#
# o = opener()
# o.send('/Users/zhangzhihui/Desktop/Python/Basic/A')
# o.send('/Users/zhangzhihui/Desktop/Python')
- 迭代器
- 概念:重复+上一次迭代的结果为下一次迭代的初始值。重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值
- 为什么要有迭代器:
- 对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式
- 迭代器优缺点:
- 优点:提供一种不依赖索引的迭代方式;节省内存
- 缺点:无法获取长度;一次性
- 装饰器
- 定义:修饰别人的工具,修饰指的是:添加功能;工具指的是:函数。
- 装饰器本身是任何可调用的对象(加括号就可以执行的函数)
- 被装饰得对象也可以是任意可调用的对象
- 为什么要用装饰器:
- 开发封闭原则:对修改是封闭的,对扩展是开放的。
- 装饰器就是为了在不修改源代码以及调用方式的前提下,为其添加新功能
- 装饰器的格式就是一个:闭包函数
- 应用:
-
import time
#定义一个函数,延迟3秒 打印出:I love you。如果在不修改 index的情况下,调用index时,可以打印出运行时间,此时就需要运用到装饰器。
# def index(a):
# time.sleep(3)
# print ('I love you')
# index()
# 定一个装饰器(装饰器就是一个函数,格式相当于闭包函数的格式)
def timer(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
run_time = end_time-start_time
print (run_time)
return wrapper
@timer # @timer 就是装饰器的调用方法,相当于 index = timer(index)
def index():
time.sleep(3)
print ('I love you')
#此时直接调用 index 函数时,就可以在不修改index的情况下,为其添加新功能。
index()
-
- 定义:修饰别人的工具,修饰指的是:添加功能;工具指的是:函数。
- 闭包函数
- 定义:在函数内部使用,包含对外部作用域而非全局作用域的引用。该内部函数就称为:闭包函数。
- eg:f2() 函数就被称为闭包函数
def f1():
x = 2
def f2():
print (x)
return f2
f = f1()
f() - 闭包函数的应用:惰性计算,想什么时候用的时候,直接 "函数名+()" 就可执行:baidu()
-
# 在函数内部使用,包含对外部作用域而非全局作用域的引用
# get() 函数包含了对外部作用域的引用:url
from urllib import urlopen
def index(url):
def get():
res = urlopen(url).read()
return res
return get
baidu = index('http://www.baidu.com')
print (baidu())
# 查看闭包函数引用的值,只要是闭包函数就有一个:__closure__ .它的结果是一个 cell。
url = baidu.__closure__[0].cell_contents
print (url)
=================第三天相关笔记=====================
- 函数
- 按照有参和无参可以将函数调用分两种:有参函数 和 无餐函数。
- foo() #定义时无参,调用时也无需传入参数
- bar('egon') #定义时有参,调用时也必须有参数
- 在python中函数分为:内置函数和自定义函数
- 定义函数的三种形式
- 无参数函数:如果函数的功能仅仅只是执行一些操作而已,就定义成无参函数,无参函数通常都没有返回值
- 定义有参函数:函数的功能的执行依赖于外部传入的参数,有参函数通常都有返回值
- 空函数
- 函数的使用包含两个阶段:定义阶段和使用阶段
- 为什么要定义函数?:
- 先定义后使用,如果没有定义而直接使用,就相当于引用了一个不存在的变量名
- 按照有参和无参可以将函数调用分两种:有参函数 和 无餐函数。
=================第二天相关笔记=====================
- String 字符串
- name = “zhangZhiHUI”
- v = name.casefold() #将所有的字符都变成小写,包括德语等其他语言,
- v = name.lower() # 只将英文字符变成小写
- v = name.upper() # 将所有的字母都大写
- v = name.swapcase() # 将所有的字符进行大小写转换。
- v = name.center(20,’@‘) #参数1表示总长度。参数2: 表示空白处填充的字符(长度为1)
- v = name.count('Z’) #表示传入值在字符串中出现的次数。
- v = name.count(‘Z’,2) #第一个参数表示:起始位置(索引)。
- v = name.count(‘Z’,2,5) #第二个参数表示:结束位置(索引)。
- v = name.startswith(‘zh’) # 是否以xx开头
- v = name.endwith(‘UI’) #是否以xx结尾
- v = name.find(‘a’) # 找字母a,如果找到,返回字母a所在字符串中的位置,找不到返回 -1
- v = name.index(‘a’) #找字母a,如果找到,返回字母a所在字符串中的位置,找不到会报错~ 建议用find。
- v = name.isidentifier() #是否是标志符,eg:class
- v = name.isdecimal() #判断是否是数字,eg: ‘123'
- v = name.isdigit() #判断是否是数字:eg:’123’ 2⃣️ 都能判断
- v = name.isnumeric() #判断是否是数字:eg:’123’,’二’,2⃣️
- v = name.isalnum() #判断是否是字母加数字。
- v = name.isalpha() #判断是否是字母
- 字符串的格式化
- name = "我是:%s;年龄:%s;性别:%s"
- name = "我是:{0};年龄:{1};性别:{2}"
- v = name.format(“zhang",19,'都行')
- name = "我是:{name};年龄:{age};性别:{gender}"
- v = name.format(name='李杰',age=19,gender='随意')
- name = "我是:{name};年龄:{age};性别:{gender}"
- v = name.format_map({'name':"李杰",'age':19,'gender':'中'})
- 字符串的连接
- name = ‘alex’
- v = ‘_’.join(name) #输出为:a_l_e_x
- 字符串的替换
- name = ‘zhangsbzhihueisbgoushi’
- v = name.replace(’SB’,’love’) #将SB替换成love
- v = name.replace(’SB’,’love’,1) #将第一个SB替换成love
- List 列表 可变类型
- 扩展原列表
- user_list = ['zhang','zhihui','alex']
- user_list.extend(['zhao','yiwei','zhang’])
- user_list = ['zhang','zhihui',’alex’,'zhao','yiwei','zhang’]
- user_list.index(‘zhang’) 。查到的话,返回索引值。查不到的话,报错。
- user_list.reverse() #整个列表的反转
- user_list.sort() #整个列表按照ascii码排序eg:a~z 从小到大
- user_list.sort(reverse=True) 从大到小进行排序
- Tuple 元组,不可被修改的列表,不可变类型
- user_tuple = (‘alex’,’eric’,’zhang’,[‘a’,’b’,’c’],
- tuple的子元素不可以被变更,但孙子元素是可以被变更的。
- 元祖的最后,需要加一个逗号
- Dict 字典--可变类型,字典可以嵌套;字典的key必须是不可变类型
- 深浅copy
- dic.get(‘key’) #通过key来获取指定的value值。如果key不存在,则返回None
- v=dic.pop(‘key’) #删除key和key对应的value,并将value值返回给v
- v=dic.popitem() #随机删除键值对,并将键值对返回给v
- dic.setdefault(‘key’,’value) #如果字典中不存在key值,则将key,value增加到字典中。如果存在key值,则不进行任何操作。
- dic.update({‘k1’:’v1,’k5’:’v5}) #批量修改和更新,如果有对应的key,则update,如果没有对应的key,则新增入字典。
- dic = dict.fromkeys([‘k1’,’k2’,’k3’],123) #新建一个所有value都等于123的字典
- Set 集合 --不可重复的列表,可变类型
- s1 = {"alex",'eric','tony','李泉','李泉11’}
- s2 = {"alex",'eric','tony','刘一’}
- v = s1.difference(s2) # 表示s1中存在而s2中不存在的元素
- s1.difference_update(s2) #表示s1中存在而s2中不存在的值。先将s1清空,在将值重新付值到s1中 。v={'李泉','李泉11’}
- v = s1.symmetric_difference(s2) #去除s1和s2共有的值,返回给v
- v = s1.intersection(s2) #s1和s2的交集
- v = s1.union(s2) #s1和s2的并集
- s1.discard(‘alex’) #将alex元素移除
- s1.update({‘a’,’b’,’c’}) #重复的值不做操作,不一样的值添加进s1
- Enumerate枚举,会额外声称一列有序的数字
- user_list = ['zhang','zhi','hui','zhaoyiwei’]
- for i,ele in enumerate(user_list,1): #参数1表示从数字1开始输出有序的数字
- print(i,ele)
- 输出结果:
1 zhang
2 zhi
3 hui
- user_list = ['zhang','zhi','hui','zhaoyiwei’]
- 其他
- range()函数在2.7里面,会立即生成所有在范围内的数字,缺点,当数值范围较大时,会引起内存Crash。而在3.x里面,不会立即生成,只有循环迭代时,才会一个一个生成,
- 输出10~0
- for i in range(10,0,-1)
- 输出 1,3,5,7,9
- for i in range(1,10,2)
- range()函数在2.7里面,会立即生成所有在范围内的数字,缺点,当数值范围较大时,会引起内存Crash。而在3.x里面,不会立即生成,只有循环迭代时,才会一个一个生成,
=================第一天相关笔记=====================
- Python种类和其他语言的对比
- CPython:代码 -> C 字节码 -> 机器码 (一行一行进行编译执行)
- PyPy:代码 -> C 字节码 -> 机器码 全部转换完 再执行->执行
- 其他Python(Jython): 代码 -> 其他字节码 -> 机器码
- 字符编码:
- ascii :8位二进制数来表示 256种可能的字符,00000000 2**8=256
- unicode 万国码: 至少两个字节起,占用内存空间比较大。
- utf-8 :弹性存储,是对万国码的压缩。中文占三个字节。00000000 00000000 00000000
- gbk,gb2312:中文需要两个字节。00000000 00000000
- 变量
- 字母
- 数字(变量不能以数字开头)
- 下划线
- 不能使用关键字来命名变量
- 变量名需要设置一个有意义的,可以通过下划线方式。eg:usr_info
- Python数据类型
- 布尔值:
- 数字:只有数字0是 False,其他都是 True
- 字符串:只有""是 False,其他的都是 True,包括" "。有空格也表示 True
- 布尔值:
- 占位符
- 相关格式:
- name = '我叫: %s,性别: %s,年龄: %d' % ('张志辉', '男', 18)
- 相关格式:
- 运算符
- and or 运算符
- 1 == 1 and 1 > 2 or 1 == 4 False 如果遇到and,左侧正确再继续向后看,如果右侧也正确,则就表示正确。or后面的就不用看了
- 1 == 1 or 1 > 2 and 1 == 4 True 从左到右。如果遇到or,如果左侧是True,右侧就不用看了,直接忽略,打印出来是True。
- 原理:and 和 or 优先级相等,
- and or 运算符
- String相关操作
- 移除空格和换行符
- val = ' alex ' 。
- val.strip() #移除左右空格,包括回车换行。
- val.lstrip() #移除左侧空格,rstrip()表示移除右侧空格
- val = ' alex ' 。
- 分割
- val = 'zhang|zhihui|9|10'
- val.splict('|') #通过 | 来分隔,分隔出list:['zhang', 'zhihui', '9','10']
- val.splict('|',1) #表示只分隔左侧第一个|,分隔出list:['zhang', 'zhihui|9|10']。如是2,则表示分隔左侧两个 |
- val = 'zhang|zhihui|9|10'
- 长度&索引
- len(val) 长度
- val[0] 索引
- 切片
- name = 'zhangzhihui'
- name[0:5] #打印索引 0,1,2,3,4 五个字符。
- name[0:5:2] #打印索引 0,2,4 三个字符,步长为2.
- 移除空格和换行符
- List 列表
- 删除
- n = [ 'zhang', 'zhi', 'hui' ]
- v = n.remove('zhi') #根据value删除
- v = del(n[0]) #按照索引删除
- 更新
- n = [ 'zhang', 'zhi', 'hui' ]
- n[1] = 'zhao'
- 删除
- 字典
- 创建
-
1 user = { 2 'name': 'zhiHui', 3 'age': 18, 4 'gender': 'male' 5 }
-
- 增加&更新
- user['age'] = 34 #如果没有该key,则新增;如果有该key,则更新。
- 索引
- n = user['name'] #可以通过key获取值。获取值为:zhiHui
- 删除
- del user['name'] #通过key来删除
- 循环
-
# 打印字典里的key for item in val.keys(): print(item) # 打印字典里的values for item in val.values(): print(item) # 打印键值对 for key, value in val.items(): print(key, value)
-
- 相互嵌套
-
1 user_dict = { 2 'k1': 'value1', 3 'k2': {'kk1': 'vv1', 'kk2': 'vv2', 'kk3': 'vv3'}, 4 'k3': 123, 5 'k4': ['alex', 'eric', ['a', 'b', 'c'], '张志辉', {'k11': 'v11'}] 6 } 7 8 # K4下的list列表中append一个元素 9 user_dict['k4'][2].append('dog') 10 print(user_dict) 11 12 # 通过索引得到其中的一个元素的value 13 n = user_dict['k4'][4]['k11'] 14 print(n) 15 16 # 通过key更新 value 17 user_dict['k2']['kk1'] = 'zhang' 18 print(user_dict) 19 20 # 插入key and value 21 user_dict['k5'] = 7899 22 print(user_dict)
-
- 创建