python之基础
第一章 列表
1.1 定义
列表 --list --容器
有序,可变,支持索引
列表: 存储数据,支持的数据类型很多 字符串,数字,布尔值,列表,集合,元祖,字典,
#定义一个列表
lst = ["zz",123,True,"中国"] # 用逗号分隔的是一个元素
print(lst[0])
print(id(lst[0]))
# id获取对象的内存地址
1.2 增加
lst.append("111") #追加(在列表的最后位置添加一个内容)
lst.insert(2,"sd") #插入 以后尽量不要使用(当数据量比较大的时候会影响效率)
lst.extend("可迭代的内容") # 迭代追加 只在最后追加
1.3 删除
lst.pop() # 默认删除最后一个
lst.pop(-1) #可以根据索引删除
lst.remove("dsb") # 移除 通过元素名字进行删除
print(lst) #只能删除1个
#remove 删除全部,使用while循环
l=[9,6,5,6,6,7,8,9,6,0]
length=len(l)
x=0
while x < length:
if l[x] == 6:
l.remove(l[x])
# del l[x]
x -= 1
length -= 1
x += 1
print(l)
lst[-1][1][1][0]
del lst[0] # 通过索引删除
del lst[0:3] # 通过切片删除
del lst[0:3:2] # 通过步长删除
lst.clear() #清空
1.4 改
lst = ["zz",123,True,"中国"]
lst[1] = "123" #通过索引改
lst[1:2] = "12345" #通过切片改
print(lst)
# ['zz', '1', '2', '3', '4', '5', True, '中国']
lst[1:4] = 12,13,14,15
print(lst)
['zz', 12, 13, 14, 15]
lst[1:4:2] = "12"
print(lst) # 步长不为1的必须用一一对应,多一个也不行,少一个也不行
['zz', '1', True, '2']
1.5 查
for i in lst:
print(i)
1.6 列表嵌套
取出88
l=[1,2,3,[3,5,[77,88]]]
print(l[-1][-1][1])
# 不管什么类型进行切片的时候获取都到都是源数据类型
第二章 元组
1. 定义
-- tuple
tu=(1,"12",[12,11])
有序,不可变,支持索引
元组用于存储一些比较重要的信息
元组在配置文件中会使用元组就是不可变的列表
2. 读取
#for 循环
for i in tu:
print(i)
第三章 range
1. 定义
# range -- 范围
print(list(range(0,10))) # 顾头不顾尾
常用于与for循环
python3 中的range是一个可迭代对象 写得是怎样的打印的时候就是怎样
获取成列表:list(range(0,10)) 顾头不顾尾
python2 中的range返回的是一个列表
xrange和python3中的range是相似的
2. 用法
print(list(range(0,10,1))) #步长不写的时候默认为1 [0:10:1]
print(list(range(10,0,-1))) # [10:0:-1]
print(list(range(10))) #1 [:10]
3. 例题
使用for循环和range 打印 100 ~ 1
for i in range(100,0,-1):
print(i
输入三次姓名退出
lst = []
flage = True
while flage:
name = input("请输姓名:")
lst.append(name)
if len(lst) == 3:
flage = False
print(lst)
#------------------------------------------
lst = []
for i in range(3):
lst.append(input("请输入姓名:"))
print(lst)
4. 小题
lst = [1,2]
for i in lst:
lst.append("alex")
print(lst) # 循环打印lst中的内容 -- 此循环是死循环
lst = [1,2]
for i in lst:
lst.append("alex")
print(lst) # 死循环 -- 不会打印内容
lst = []
for i in range(5):
lst.append([])
print(lst) # [[],[],[],[],[]]
lst = [1,2]
lst[0] = lst
print(lst) # [[...],2]
第四章 字典
1. 定义
字典 -- dist
字典:无序的,可变的数据类型
字典:用于存储数据,存储大量数据 字典要比列表快 将数据和数据之间进行关联
dic = {1:"zbb",2:True,3:"追梦NAN",4:"人生苦短",5:"我用python"}
print(dict(key=1,a="alex"))
字典的键(key):
可哈希的(不可变得数据类型) -- 避免哈希冲突使用了 开放寻址法
要求唯一 -- 如果有重复的后边值的将前面的值覆盖
字典的值(value):
可以任意
2. 增加
dic["zz"] = 89 # 暴力添加
dic.setdefault("www",100) #去字典查询key,如果不存在执行添加,如果存在就不添加了
3. 删除
del dic["www"] # 通过字典的键删除键值对
dic.pop("zz") #通过字典的键进行删除键值对 返回值:返回的是被删除的值
dic.clear() #清空
4. 改
dic["aaa"] = "djj" #有则改,无则加
dic.update(dic1) # update括号中的字典级别高于update前面的字典
5.查
for i in dic1: # 循环获取的是字典中每个键值对的键
print(i)
print(dic.get("cx")) # 通过键获取值,如果将不存在字典中返回None
print(dic["cx"]) # 通过键获取值,如果将不存在字典中报错
6.其他操作
print(dic1.keys()) # 高仿列表 -- dict_keys(['1', '5', '2']) 支持for循环 不支持索引
for i in dic1.keys(): # 获取字典中所有的键
print(i)
print(list(dic1.values())) # 获取字典中所有的值
#获取字典中所有的键和值 存放在一个高仿列表里的元组(元组第一个元素:键,第二元素:值)
print(dic.items())
for i in dic.items():
print(i[0],i[1])
#dict_items([(1, 'zbb'), (2, True), (3, '追梦NAN'), (4, '人生苦短'), (5, '我用python')])
# 1 zbb
# 2 True
# 3 追梦NAN
# 4 人生苦短
7.解构
a,b=10,12
print(a) #10
print(b) #12
a,b = [1,2] #a=1,b=2
a,b = (3,4) #a=3,b=4
a,_,b = (3,4,5)
print(a,b) # 等号后边的值和前面的变量名要一一对应 3,5
a = 10,12 #本质就是一个元组
a,b = "23"
print(a,b) # 2 3
a,b = {"1":"a","2":"b"}
print(a,b) #1, 2 显示的是key
for i in dic.items():
print(i) #每个字边变成了元组
#(123, '123')
#(1, '122')
for k,v in dic.items():
print(k,v) # 获取每个元素的键和值
8.嵌套
dic = {1001:["伦","杰"],
1002:{"峰":{"妻":["饼"],"前":["熊大","熊二"],"章":"肉丝"}},
1003:{"陈":["娇","萨","芝"]}}
print(dic[1002]["峰"]["妻"][0])
第五章 小数据池
缓存机制(驻留机制)
节省资源
== 判断两边内容是否相等
is判断基于内存地址进行判断
a = 0
b = 0
print(a==b)
print(a is b)
print(id(a))
print(id(b))
1.代码块
能够提高一些字符串,整数处理人物在时间和空间上的性能;需要值相同的字符串,整数的时候,直接从‘字典’中取出复用,避免频繁的创建和销毁,提升效率,节约内存。
一个文件,一个函数,一个类,一个模块,终端中每一个行是一个代码块
满足代码块缓存机制
适用对象: int (float) ,str , bool
数字:
在同一代码块下 只要内容相同就采用相同的内存地址(-5以后就不是)
数字在做乘法的时候范围 -5 ~ 256 ****
数字在做乘法的时候不能使用浮点数
字符串:
在同一代码块下 只要内容相同就采用相同的内存地址
乘法的时候总长度不能超过python3.7 4096 ****
乘法的时候中文,特殊符号乘以1或0
布尔值:
在同一代码块下 只要内容相同就采用相同的内存地址
2.小数据池
能够提高一些字符串,整数处理人物在时间和空间上的性能;需要值相同的字符串,整数的时候,直接从‘池’里拿来用,避免频繁的创建和销毁,提升效率,节约内存
数字: -5 ~ 256 ****
字符串:
在同一代码块下 只要内容相同就采用相同的内存地址
乘法的时候总长度不能超过3.7 4096 ****
乘法的时候中文,特殊符号乘以0
布尔值:
在同一代码块下 只要内容相同就采用相同的内存地址
小数据池的验证方法,必须脱离代码块才能进行验证
先执行代码块的规则,在执行小数据的规则 --(驻留机制)
第六章 深浅拷贝
1.浅拷贝
浅拷贝的时候只拷贝第一层元素
浅拷贝在修改第一层元素(不可变数据类型)的时候,拷贝出来的新列表不进行改变
浅拷贝在替换第一层元素(可变数据类型)的时候,拷贝出来的新列表不进行改变
浅拷贝在修改第一层元素中的元素(第二层)的时候,拷贝出来的新列表进行改变
lst = [1,2,3,[5,6,7]]
lst1 = lst.copy() # 新开辟一个空间给lst1
lst[-1].append(7)
print(lst1)
print(lst)
# 浅拷贝的时候,只会开辟一个新的容器列表,其他元素使用的都是源列表中的元素
lst = [1,2,3,4,[5,6,7,[8,9]]]
lst1 = lst.copy() # [1,2,3,4,[5,6,7,[8,9]],10]
lst.append(10)
print(lst)
print(lst1)
lst = [1,2,3,4,[5,6,7,[8,9]]]
lst1 = lst.copy()
lst1[-1][-1] = "56"
print(lst)
print(lst1)
[1, 2, 3, 4, [5, 6, 7, '56']]
[1, 2, 3, 4, [5, 6, 7, '56']]
dic = {"alex":[1,2,3,[5,6]]}
dic1 = dic.copy()
dic["alex"][0] = "56"
print(dic)
print(dic1)
#####直接就是第二层
2.深拷贝
用法
import copy #导入
空间里的值是不可变的数据进行共用的,可变的数据类型再次开辟空间
lst = [1,2,3,[5,6,7]]
lst1 = copy.deepcopy(lst) # 深拷贝
lst[-1][-2]=1
print(lst)
print(lst1)
怎么改都不变
第七章 集合
集合 --set
相当于没有值得字典 无序 --不支持索引
-- set() 空集合
作用:
天然去重
lst = [1,2,1,2,4,2,45,3,2,45,2345,]
print(list(set(lst)))
定义:
s = {1,2,3,4,5}
1. 增
s.add("67") #只能添加一个
s.update("今天") # 迭代添加
2. 删除
print(s.pop()) # pop有返回值
s.remove(3) # 指定元素删除
s.clear() # 清空
3. 查
for i in {1,2,3}:
print(i)
4. 其他操作
# s1 = {1,2,3,4,5,6,7}
# s2 = {5,6,7,1}
# print(s1 & s2) # 交集
# print(s1 | s2) # 并集
# print(s1 - s2) # 差集
# print(s1 ^ s2) # 反交集
# print(s1 > s2) # 父集(超集)
# print(s1 < s2) # 子集
# print(frozenset(s1)) # 冻结集合 更不常用
# dic = {frozenset(s1):1}
# print(dic)
第八章 数据补充
1.Str 字符串
1.首字母大写
name = "aaa"
name1 = name.capitalize()
1.2每个单词首字母大写
name = "aaa bbb"
print(name.title())
1.3大小写反转
name = "aaa"
print(name.swapcase())
1.4居中 -- 填充
name = "aaa"
print(name.center(20,"-")) #一个参数居中,两个参数填充
1.5查找
name = "aaa" #从左向右 只查找一个
print(name.find("b")) #find查找不存在的返回-1
print(name.index("b")) #index查找不存在的就报错
1.6拼接
name = "al3x"
print("_".join(name)) ***
1.7格式化
1.%s
2.f
3.name.format()
name = "alex{},{},{}"
print(name.format(1,2,3)) # 按照顺序位置进行填充
name = "alex{2},{0},{1}"
print(name.format("a","b","c")) # 按照索引值进行填充
name = "alex{a},{b},{c}"
print(name.format(a=1,c=11,b=67)) # 按照关键字进行填充
2.list 列表
定义方式: # list("123")
1.排序
lst = [1,2,23,234,435,36,23,213421,421,4231,534,65]
lst.sort() # 排序 (升序)
print(lst)
lst.sort(reverse=True) # 降序
print(lst)
2.反转
lst = [1,2,3,4453,5,6,7]
print(lst[::-1])
lst.reverse() # 反转
print(lst)
3.面试小题
lst = [[]]
new_lst = lst * 5
new_lst[0].append(10)
print(new_lst)
###[[10], [10], [10], [10], [10]]
3.tuple 元组
元组 支持 +
tu = (1,2)
tu1 = (3,4)
tu2 = tu + tu1
print(id(tu))
print(id(tu1))
print(id(tu2))
tu = ([],)
tu1 = tu * 5
tu1[0].append(9)
print(tu1)
列表在进行乘法的时候元素都是共用
tu = (1,2)
tu1 = tu * 5
print(tu1)
print(id(tu1[0]),id(tu1[-2]))
3.dict 字典
字典定义方式:
dict(key=1,key1=2,key2=3)
1.随机删除: popitem
dic = {"key":1,"key2":2,"key3":56}
print(dic.popitem()) # 返回的是被删除的键值对(键,值)
print(dic)
2.批量创建字典
dic = {}
a=dic.fromkeys("123",[23]) # 批量添加键值对{"1":[23],"2":[23],"3":[23]}
print(a)
formkeys这个是个坑,坑点就在于值是可变数据类型的时候,当第一个键对应的值进行修改了以后,其余的键对应的值也都跟着进行改变了. 如何避免坑,就是批量创建字典的时候值不能使用可变的数据类型.
4.set 集合
set() -- 空集合
{} -- 空字典
定义集合:
set("alex") # 迭代添加的xxxxxxxxxx
set() -- 空集合
{} -- 空字典
5.数据类型之间转换
元组 => 列表 list(tuple)
列表 => 元组 tuple(list)
列表 => 字符串 str.join(list)
字符串 => 列表 str.split()
转换成False的数据:
0,'',None,[],(),{},set() 都是False
6.python数据类型:
可变:
list ,dict ,set
不可变:
int bool str tuple
有序:
list,tuple,str,int,bool
无序:
dict,set
取值方式:
索引: str list tuple
直接: set ,int ,bool
键: dictxxxxxxxxxx python数据类型:python数据类型:可变:list ,dict ,set不可变:int bool str tuple有序:list,tuple,str,int,bool无序:dict,set取值方式:索引: str list tuple直接: set ,int ,bool 键: dictpython
第九章 以后会遇到的坑
1.for的死循环
lst = [1,2]
for i in lst:
lst.append(3)
print(lst) # 死循环
2.删除列表的坑
li = [11, 22, 33, 44]
for e in li:
li.remove(e)
print(li)
结果:
[22, 44]
lst = [1,2,3,4]
for i in lst:
lst.remove(i)
print(lst)
分析原因: for的运⾏过程. 会有⼀个指针来记录当前循环的元素是哪⼀个, ⼀开始这个指针指向第0 个.
然后获取到第0个元素. 紧接着删除第0个. 这个时候. 原来是第⼀个的元素会⾃动的变成 第0个.
然后指针向后移动⼀次, 指向1元素. 这时原来的1已经变成了0, 也就不会被删除了
3.正确的删除列表
lst = [1,2,3,4,6]
for i in range(len(lst)):
lst.pop() #倒着删除
print(lst)
lst = [1,2,3,4,6]
for i in range(len(lst)):
del lst[-1]
print(lst)
lst = [1,2,3,4,5,6]
lst1 = lst.copy()
for i in lst1:
lst.remove(i)
print(lst)
4.删除字典的坑
1.错误案例
dic = {'k1': 'alex', 'k2': 'wusir', 'k3': '大宝哥'}
# 删除key中带有'k'的元素
for k in dic:
if 'k' in k:
del dic[k] # dictionary changed size during iteration, 在循环迭代的时候不允许进⾏删除操作
print(dic)
2.正确
dic = {'k1': 'alex', 'k2': 'wusir', 'k3': '大宝哥'}
dic_del_list = []
# 删除key中带有'k'的元素
for k in dic:
if 'k' in k:
dic_del_list.append(k)
for el in dic_del_list:
del dic[el]
print(dic)
# 使用两个字典进行删除
dic = {'k1': 'alex', 'k2': 'wusir', 'k3': '大宝哥'}
dic1 = dic.copy()
for i in dic1:
dic.pop(i)
print(dic)
dic = dict.fromkeys("12345",1) # 字典的迭代的时候改变了原来的大小(不能加不能删)
for i in dic:
dic[i] = "123"
print(dic)
dic = dict.fromkeys("12345",1)
dic1 = dic.copy()
for i in dic1:
dic.pop(i)
print(dic)
集合和字典都是迭代的时候不能改变原来的大小
第十章 编码 --进阶
密码本:
ascii -- 没有中文
gbk -- 英文 8b(位) 1B(字节) 中文 16b 2B
unicode -- 英文16b 2B 中文32b 4B
utf-8 -- 英文8b 1B 欧洲16b 2B 亚洲24b 3B
1.编码
s = "alex"
print(s.encode("utf-8")) # 将字符串编码成UTF-8
print(s.encode("GBK")) # 将字符串编码成GBK
结果:
b'alex'
b'alex'
s = "中"
print(s.encode("UTF-8")) # 中⽂编码成UTF-8
print(s.encode("GBK")) # 中⽂编码成GBK
结果:
b'\xe4\xb8\xad'
b'\xd6\xd0'
记住: 英⽂编码之后的结果和源字符串⼀致. 中⽂编码之后的结果根据编码的不同. 编码结果也不同. 我们能看到. ⼀个中⽂的UTF-8编码是3个字节. ⼀个GBK的中⽂编码是2个字节. 编码之后的类型就是bytes类型. 在⽹络传输和存储的时候我们python是发送和存储的bytes 类型. 那么在对⽅接收的时候. 也是接收的bytes类型的数据. 我们可以使⽤decode()来进⾏解码操作. 把bytes类型的数据还原回我们熟悉的字符串:
s = "我叫李嘉诚"
print(s.encode("utf-8")) #
b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'
print(b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'.decode("utf-8")) # 解码
2.解码
编码和解码的时候都需要制定编码格式.
s = "我是⽂字"
bs = s.encode("GBK")
# 我们这样可以获取到GBK的⽂字
# 把GBK转换成UTF-8
# ⾸先要把GBK转换成unicode. 也就是需要解码
s = bs.decode("GBK") # 解码
# 然后需要进⾏重新编码成UTF-8
bss = s.encode("UTF-8") # 重新编码
print(bss)
unicode就是一个桥梁,可以实现他们之前相互编码,但是我们在编码和解码的时候必须使用同一个密码本.
第十一章 文件操作
打开文件的方式:
r,w,a
r+,w+,a+
rb,wb,ab
1. r模式
f = open('22.txt',mode='r',encoding='utf-8') #f是文件句柄
content = f.read()
print(content)
f.close()
默认 mode(操作文件的模式)可以不写
r 可以不写
2. rb模式
f = open('22.txt','rb')
content = f.read()
#content = f.read(3) #按照字节读取
print(content)
f.close()
#b'\xe4\xb8\xad\xe8\xbf\x87'
rb 读出来的数据是bytes类型,在rb模式下,不能encoding字符集
作用:
在读取非文本文件的时候,比如要读取mp3,图像,视频等信息的时候就需要用到rb,因为这种数据是没办法直接显示出来的
这个字节的模式是用于传输和存储
3. 绝对路径
绝对路径:从根目录下开始一直到文件名。
相对路径:同一个文件夹下面的文件,直接写文件名就可以。
我们在使用绝对路径的时候因为有\这样程序是不能识别的,解决方法:
open('C:\Users\neet') #这样程序是不识别的
解决方法一:
open('C:\Users\\neet') #这样就成功的将\进行转义 两个\\代表一个\
解决方法二:
open(r'C:\Users\neet') #这样相比上边的还要省事,在字符串的前面加个小r也是转义的意思
4. 读操作
1.read()
read()是将文件中所有的内容都读取
f = open('22.txt',encoding="utf-8")
content = f.read()
print(content)
f.close() ###
read()可以指定我们想要读取的内容数量
f = open('22.txt',encoding="utf-8")
content = f.read(3) #读取三个字符
msg = f.read() #接着第三个字符之后读取
print(content)
print(msg)
f.close()
结果:
高圆圆
刘亦菲
张柏芝
杨紫
王菲
使用r模式读取的就是文字
使用rb模式读取出来的就是字节
f = open('22.txt',"rb")
content = f.read(3)
msg = f.read()
print(msg)
f.close()
#b'\xe5\x9c\x86xe8\x8f\xb2\r\n\x\xe6\x9d\xa8\b\xe8\x8f\xb2'
2.readline()
每次只读取一行,注意点:readline()读取出来的数据在后面都有一个 \n **
f = open('22.txt',encoding="utf-8")
msg1 = f.readline()
msg2 = f.readline()
msg3 = f.readline()
print(msg1)
print(msg2)
print(msg3)
# 高圆圆
#
# 刘亦菲
#
# 张柏芝
结果这里每个一内容中间都有一个空行是因为咱们读取的内容后边都带有一个\n
print()的时候会将这个\n执行
f = open('22.txt',encoding="utf-8")
msg1 = f.readline().strip()
msg2 = f.readline().strip()
msg3 = f.readline().strip()
print(msg1)
print(msg2)
print(msg3)
解决这个问题只需要在我们读取出来的文件后边加一个strip()就OK了
3.readlines()
一行一行的读取,并放到列表中
缺点:
当文件很大的时候,将文件中的内容全部读取,存放在内存中这样会导致内存奔溃
解决方法:
for i in f:
print(i)
5.w操作
分为两步:
1.先清空(open的时候清空)
2.后写入(可以追加写入多次)
f = open('22.txt',"w",encoding="utf-8")
f.write("213\n")
f.write("213\n")
f.write("213\n")
#213
#213
#213
1. wb模式
f = open("3.jpg","wb") #清空
f.write(f1.read()) #添加b
6. a操作
追加写入
f = open('22.txt',"a",encoding="utf-8")
f.write("213222221\n")
1.ab
f = open("2.jpg","ab")
f.write("你好啊".encode("utf-8")) #写入utf-8编码的"你好啊"
7. + 操作
1.r+ 读写
先读后写
f = open("萝莉小姐姐","r+",encoding="utf-8")
print(f.read())
f.write("鸡你太美")
2.w+ 清空写读
f = open("萝莉小姐姐","w+",encoding="utf-8")
f.write("鸡你太美")
f.seek(0) #
print(f.tell())
print(f.read())
3. a+ 追加写读
f = open("小姐姐电话号","a+",encoding="utf-8")
f.write("鸡你太美")
print(f.tell()) # 字节数
# print(f.seek(0,0)) # 0将光标移动到文件的头部
print(f.read())
4 .其他操作
tell 查看光标 --- 返回的是字节数
seek 移动光标
1.seek(0,0) -- 移动到文件的头部
2.seek(0,1) -- 当前位置
3.seek(0,2) -- 移动到文件的末尾
4.seek(3) -- 按照字节进行移动(按照编码集,自己进行计算)
5. 文件的修改
f = open("小姐姐电话号","r",encoding="utf-8")
s = f.read()
s1 = s.replace("你太美","吃煎饼")
###########
f1 = open("小姐姐电话号","w",encoding="utf-8")
f1.write(s1)
6. with 自关闭
with 关键字 open("萝莉小姐姐","r",encoding="gbk") as f:
pass
with open("萝莉小姐姐电话号","r",encoding="utf-8")as f,\
open("萝莉小姐姐电话号.txt","w",encoding="utf-8")as f1:
for i in f:
s1 = i.replace("你太美","井盖")
f1.write(s1)
7.文件重命名
import os
os.rename("萝莉小姐姐电话号","萝莉小姐姐电话号.bak")
os.rename("萝莉小姐姐电话号.txt","萝莉小姐姐电话号")
###############vim
7.取出文件中的第几行
import linecache
aa = linecache.getline('zz.txt', 4)
print(aa)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?