Py002-01-05递归

递归

原理就是自己调用自己

1
2
3
4
5
6
7
8
def xx(n):
print(n)
xx(n+1)

xx(1)

# 报错 maximum recursion depth exceeded while calling a Python object
# 大概打印不到1000次 就报错了

每次调用函数都会将其压入栈中,栈有一定的限制,超过就会溢出了

就像步枪的「弹匣」是由容量限制的

阶乘 1 2 3 4 … n

1
2
3
4
5
6
def xxx(n):
if n ==1:
return 1
return xxx(n-1)*n

print(xxx(4)) # 24

正确使用递归

  • 要有结束条件,否则就死循环了
  • 每次进入更深一层递归时,问题规模要比上一次有所减少
  • 递归效率不高

适用场景

  • 兔子数列—->斐波那契
  • 汉诺塔

递归的优化(尾递归)

  • 递归之所以效率低就是因为每执行一步就会压栈
  • 每次压栈的执行结果要保存 如 4的阶乘 需要知道 3阶乘的结果 。。。。
1
2
3
4
# 注意这个代码在python是不支持的会报错, 这样的代码实际就是尾递归。
def cal(n):
print(n)
return cal(n+1)

Py002-01-04函数

函数

  • 解决代码重复问题(给一坨代码起个名字法)
  • 方便程序扩展
  • 使程序变得易维护
1
2
3
4
5
6
7
8
9
10
11
12
13
def 发邮件(内容):
连接邮箱服务器
发送邮件
关闭连接

def sayHi(): # 定义函数
print('hello')

sayHi() # 执行代码

传参数------------------------
def sayHi(name): # 定义函数
print('hello',name)

形参实参的问题不写了。写的实在太多了

默认参数

就记住一个规则:默认参数必须在位置参数后面

1
2
3
4
5
6
7
8
9
10
11
12
def userInfo(name,age,gender,city='USA'):
print(name,age,gender,city)

如果默认参数提前了呢?---------------------------
ide会爆红,因为 那样就会影响后面的位置参数

def userInfo(name,age,city='USA',gender):

此时你就写三个参数
userInfo('a','2','man')
然后报错
non-default argument follows default argument

关键参数

铁律:位置参数不能放在关键字参数后面

1
2
3
4
5
6
7
8
9
10
def userInfo(name,age,gender='man',city='USA'):
print(name,age,gender,city)

调用可以这样
userInfo("山炮",gender="woman",age=22,city='china')

绝不可以这样
userInfo("山炮",gender="woman",22,city='china')
这样也不行
userInfo("山炮",22,age=22,city='china')

非固定参数

场景:以前小公司只有一个维护人员,功能出现问题就给维护人员报警提示

1
2
def send_msg(msg,user):
print(msg,user)

后来公司壮大了,10个运维人员,如何发给10个人呢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 多个人你肯定不能这样
# send_msg('别浪了','a1')
# send_msg('别浪了','a2')
# send_msg('别浪了','a3')
# send_msg('别浪了','a4')
# send_msg('别浪了','a5')
# ....

#----------------------------
# 报警:10个运维人员咋办? 修改如下 在users前加上「*」
def send_msg(msg,*users):
for u in users:
print(msg,u)

send_msg('别浪了','a1','a2','a3','a4') # 将第一个参数后面的参数打包给 users
此时 users就变为一个元组

# 如果参数中出现 *users参数的就可以不再固定个数,传过来的所有数据打包为一个元祖

# *users 实际有种专业写法就是 ---------> *args

传参的两种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def send_msg(msg,*users):
for u in users:
print(msg,u)
# 方式一
send_msg('别浪了','a1','a2','a3','a4')


# 如果向传一个列表呢?
send_msg('别狼了',['a1','a2','a3','a4']) # 这样实际上是 (['a1','a2','a3','a4'])
# 方式二

该咋办呢? 在传递的列表前加上一个 * 就可以了
send_msg('别狼了',*['a1','a2','a3','a4'])
这样就会这样
*['a1','a2','a3','a4'] ===> 'a1','a2','a3','a4'

如果有奇葩队友这样写参数咋办?

1
2
3
4
5
6
7
def send_msg(msg,*users,age):
pass

# send_msg('别狼了','alex',22) # 这样就会报错 因为 这种参数传递 都会把 alex 22 给 users 到 age的时候就没有参数了

# 有木有解决办法 使用关键字参数
send_msg('别狼了','alex','xxx',age=22)

非固定参数二

1
2
3
4
5
6
7
8
def func(name,*args,**kwargs):
print(name,args,kwargs)

func('alex',22,'qq','500w') # alex (22, 'qq', '500w') {}
# 最后一个字典代表关键字参数

func('alex',22,'qq','500w',phone='1323123123',addr='北京')
# alex (22, 'qq', '500w') {'phone': '1323123123', 'addr': '北京'}

你觉得写每个关键字参数太麻烦,于是改进了下

1
2
3
4
5
6
7
d = {"phone":"1323123123","add":"北京"}
func('alex',d) # 为啥参数跑 元组里去了,因为被当作非固定参数
# alex ({'phone': '1323123123', 'addr': '北京'},) {}

# 对于字典, 应该这样
func('alex',**d)
# alex () {'phone': '1323123123', 'addr': '北京'}

返回值

1
2
3
4
5
6
7
8
9
10
11
def fn():
return 1

print(fn()) # 1 返回1


def fn2():
pass

print(fn2()) # 返回 None
# 没写return 返回None
  • 能不能返回多个值? 不能 肯定是被包裹在一个容器里
1
2
3
4
5
6
7
def fn():
return 1,2
print(fn()) # [1,2]

def fn2():
return [1,2]
print(fn2()) # [1,2]

局部变量

  • 定义在函数外部的一级代码的变量叫全局变量
  • 在函数内定义的变量就是局部变量
  • 函数内部可以引用全局变量,如果函数内外都有一个name变量,函数查找是由内而外的
  • 局部可以引用全局变量,但不能修改 如name = ‘xx’实际是函数内部声明了一个局部变量name
1
2
3
4
5
6
7
8
9
10
# 全局
name = 'aaa'
def xxx():
# 局部
name = 'bbb'
print(name)


xxx() # 'bbb'
print(name) # 'aaa'

如果内部没有定义name 能直接打印吗? 可以

1
2
3
4
5
6
7
8
# 全局
name = 'aaa'
def xxx():
print(name) # 它会向父级作用域查找 有就打印,没有报错


xxx() # 'aaa'
print(name) # 'aaa'

我就是要修改全局变量

  • global声明一下你就可以改了
1
2
3
4
5
6
7
8
9
# 全局
name = 'aaa'
def xxx():
global name
name = 'bbb'
print(name)

xxx() # 'bbb'
print(name) # 'bbb'

让你诧异的问题

如果全局变量是个列表呢!而且也不进行global声明可以修改吗?

可以

1
2
3
4
5
6
7
8
9
10
11
12
13
names = ['a','b','c','d']

def xxx2():
del names[2]
names[1] = 'boss'
print(names)

xxx2() # ['a','boss','d']
print(names) # ['a','boss','d']

# 实际names整体是一个内存地址 它内部元素又是单独的地址可以修改

# 如果我就要整体换names里的东西呢? global声明呗

嵌套函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
age = 19
def wrapper():
age = 73
print(age)
def inner():
age = 84
print(age)
inner()

wrapper()
# 73
# 84

# 原理就是作用域从内到外,逐级向上查找

来看各种恶心的调用版本

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
age = 19
def wrapper():
age = 73
def inner():
print(age)
inner()

wrapper() # 73
再看-----------------------------
age = 19
def wrapper():
def inner():
print(age)
age = 73 # 声明在 函数后
inner()

wrapper() # 73
再看-----------------------------
age = 19
def wrapper():
def inner():
print(age)
inner()
age = 73 # 声明在 函数调用后

wrapper() # 报错
# 调用inner()的时候会找age 它会向全局找,但是函数调用的下面又声明了一个age所以就不知道找谁了,于是报错

# 如何解决
1. 要么声明在inner()之前
2. 要么在调用前声明global age
闭包
1
2
3
4
5
6
7
8
9
def wrapper():
aa = 1
def inner():
print(aa)
return inner

# 内部函数访问外部函数的变量就叫闭包
numAdd = wrapper()
numAdd()

匿名函数

声明一个匿名函数

1
2
3
4
5
6
7
8
# 传统方式
def fn(x,y):
return x**y

# 匿名函数
func = lambda x,y:x**y

func(2,5) # 32

注意:

lambda返回值不支持复杂的条件判断,只支持三元运算,不像js的箭头函数可以用{}包含起来

1
func = lambda x,y:x*y if x<y else x/y

匿名函数的用途

1
2
3
4
5
6
7
def fn(n):
return n*n

data = list(range(10))
map(fn,data)
--------------------------------
map(lambda x:x*x,data)

匿名函数总结:

  • 节省代码量
  • 看着高大上

高阶函数

只要满足以下任意条件就是高阶函数

  • 把函数当作参数
  • return 返回另一个函数
1
2
3
4
5
6
7
8
def xx(a):
return a + 1

def yy(fn,n):
return fn(n) # 返回 给参数函数fn 传递参数n并返回执行结果

res = yy(xx,2) # 传递 xx 函数
print(res) # 3

Py002_01_03文件操作

python文件处理

读取

1
2
3
f = open(file='xxx.txt',mode='r',encoding='utf-8')
data = f.read()
f.close()
  • file 是目标文件
  • mode 代表文件操作模式 r意思是只读
  • encoding 是以xx编码读取文件

注意:

  • 读取文件的编码方式和文件存储时的编码要一致
  • 如果不传递encoding,在python3里默认utf-8
1
如果文件是gbk的形式存储的,那么读取时如果encoding='utf-8'就会报错

二进制模式

如果我不知道文件的编码也想把内容读取进来,你可以使用二进制模式

把这段内容直接以二进制的形式读取进来,不进行按照它的编码方式编码

  • mode=rb

主要用来视频/图片/文件传输

1
2
3
f = open(file='xxx.txt',mode='rb',encoding='utf-8')
data = f.read()
f.close()

智能检测编码的工具

需要手动安装工具包

1
pip install chardet
1
2
3
4
5
6
f = open(file='xxx.txt',mode='rb')
data = f.read()
f.close()
print(chardet.detect(data))
# 输出一个字典显示 改二进制对应的编码
{'encoding': 'gb2312', 'confidence': 0,8321312312, 'language': 'chinese'}

read()的缺陷

一次性把文件读取到内存,如果文件3G呢?

循环文件(一次读一部分)

1
2
3
4
5
6
f = open(file='xxx.txt',mode='r',encoding='utf-8')

for line in f:
print(line)

f.close()

写文件

普通写入

1
2
3
f = open(file='xxx.txt',mode='w',encoding='gbk')
f.write("你好!!!")
f.close()

二进制模式写入

1
2
3
f = open(file='xxx.txt',mode='wb')
f.write("你好!!!".encode()) # encode默认utf-8
f.close()

mode=’w’每次都会创建一个新文件,如果已经存在就覆盖了

同一文件不想每次都覆盖==>追加模式

1
2
3
f = open(file='xxx.txt',mode='ab')
f.write("你好!!!".encode()) # encode默认utf-8
f.close()

混合操作文件

既能写又能读的模式

  • r+ 读写模式—>先读后写
  • w+ 写读模式—>先创建然后读取(先把文件覆盖,然后读取新写入的内容)(几乎用不到)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
假设文件里有内容
f = open('info.txt','r+',encoding='gbk')
print(f.read())
f.write('\n何大宝 哈哈 11111111111')
f.write('\n何大宝 哈哈 11111111111')
f.write('\n何大宝 哈哈 11111111111')
f.write('\n何大宝 哈哈 11111111111')
print('````````````````')
print(f.read()) # 为什么这次的内容是空的
f.close()

详解:
文件读取的时候会有一个光标
1. 第一次read()的时候全部读出来 光标移动到读取内容末尾
2. write的时候 光标移动到写入内容的后面
3. 第二次read()的时候 由于光标后面没有任何东西,所以为空
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
假设文件里有内容
f = open('info.txt','w+',encoding='gbk')
print(f.read()) # 为什么这次的内容是空的
f.write('\n何大宝 哈哈 11111111111')
f.write('\n何大宝 哈哈 11111111111')
f.write('\n何大宝 哈哈 11111111111')
f.write('\n何大宝 哈哈 11111111111')
print('````````````````')
print(f.read()) # 为什么这次的内容也是空的
f.close()

详解:
0. 写读模式打开--》创建这个文件如果已经存在就覆盖了
1. 第一次read() 文件是新建的本来就是空的
2. write的时候 光标移动到写入内容的后面
3. 第二次read()的时候 由于光标后面没有任何东西,所以为空

最没用模式---------几乎用不到

文件操作其他方法

  • fileno() 网络编程会用,返回一个数字
  • flush() 强制把文件buffer里(内存里)的内容写入到文件里
  • readable() 是否可读
  • readline() 每次读一行
  • seek() 设置光标的位置 (下次读的时候从这个位置开始)
  • tell() 返回光标的位置
  • seekable() 判断文件是否可以seek操作 比如终端命令行也是一个文件就不允许seek
  • writeable() 判断是否可写
  • truncate() 从指定位置(光标)截断文件

flush功能

1
2
3
4
5
6
7
8
9
10
f = open('info.txt','w')
f.write('aa')
f.write('aa')
f.write('aa')

# ....只要你不 f.close() 写入的内容就在 内存里也就是缓存里
# 因为频繁写入文件的话很耗性能
# flush是什么鬼呢?
# 如果你写的内容非常重要 必须确保每次都write的时候写入到文件里,就用flush
f.flush() # 此时就算你不f.close()也可以在存盘
tell和seek的坑
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
# 假设文件内容是 'hello world'

f = open('info.txt','r',encoding='gbk')
f.tell() # 0
f.seek(3)
f.readline() # lo world
------------------------------------------------
# 假设文件内容是 '路飞学城'
f = open('info.txt','r',encoding='gbk')
f.seek(3)
f.readline() # 报错 decode error
-----------------------------------------------
# 验证为什么报错
# 假设文件内容是 '路飞学城'
f = open('info.txt','r',encoding='gbk')
f.seek(0)
f.readline() # '路飞学城' 没问题啊???
-----------------------------------------------
# 验证为什么报错
# 假设文件内容是 '路飞学城'
f = open('info.txt','r',encoding='gbk')
f.seek(2)
f.readline() # 报错 decode error 为啥还报错!!!
-----------------------------------------------
# 验证为什么报错
# 假设文件内容是 '路飞学城'
f = open('info.txt','r',encoding='gbk')
f.read(1) # 路
f.tell() # 2 读了一个汉字 为什么走俩,我猜可能是因为gbk里汉字占俩字节
f.read() # 飞学城
-----------------------------------------------
# 验证utf-8汉字是否会 移动三个光标?
# 假设文件内容是 '路飞学城'
f = open('info.txt','r',encoding='utf-8')
f.read(1) # 路
f.tell() # 3 事实证明,结论是对的
f.read() # 飞学城

结论

  • 无论seek 还是 tell 它们找的都是字节
  • read(1) 是读一个字符

truncate

1
2
3
4
5
6
7
8
9
# 假设文件内容是 '路飞学城'
f = open('info.txt','r',encoding='utf-8')
f.truncate()
f.flush() # 此时文件是空的
----------------------------------
# 假设文件内容是 '路飞学城'
f = open('info.txt','r',encoding='utf-8')
f.truncate(6)
f.flush() # 此时文件是 '路飞' 代表从头开始截取6个字节

文件修改

实际是不能直接像word那样修改文件内容的,因为word是把所有内容读到内存里。

用光标也不靠谱:因为 比如seek的时候 张三 变成 哈尔滨 这样张三后面的内容不会让出位置,而是覆盖。

变通方式

  • 写道磁盘上
  • 写道内存里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import os

f_name = "info.txt"
f_new_name = "%s.new"%f_name

old_str = '张三'
new_str = '哈尔滨'

f = open(f_name,"r",encoding='utf-8')
f_new = open(f_new_name,"w",encoding='utf-8')

for line in f:
if old_str in line:
line = line.replace(old_str,new_str)

f_new.write(line)

f.close()
f_new.close()

os.rename(f_new_name,f_name)

Py002_01_01人丑就该多读书

据国家统计

一年中读书统计

  • 中国人均阅读量4.35本;
  • 日本40本
  • 韩国11本
  • 法国20本
  • 以色列60本

如果你迷茫了

想法太多,读书太少

如果你想升华

  • 多读书

推荐书籍

  • 追风筝的人
  • 白鹿原

金句:肾虚就该少看片,人丑就该多读书

Py001_02_06Python进制拾遗和编码问题

进制拾遗

  • oct 八进制
  • hex 十六进制
1
2
3
4
5
6
7
8
9
10
11
12
13
oct(1) # '0o1'
oct(7) # '0o7'
oct(8) # '0o10'


hex(9) # '0x9'
hex(10) # '0xa'
hex(11) # '0xb'
hex(12) # '0xc'
hex(13) # '0xd'
hex(14) # '0xe'
hex(15) # '0xf'
hex(16) # '0x10'

为何使用十六进制

  • 方便阅读
1
2
3
chr(97) # 'a'
bin(97) # '0b1100001'
hex(97) # '0x61'

编码

我们知道最早计算机使用的ascⅡ编码,因为是外国人发明的,没有考虑到中国的强大

后来随着祖国的强大陆续出现GB2312,GBK等编码

但是为了实现多个国家的统一ISO组织创建了Unicode字符集(万国码)

我们知道Unicode导致什么字符占用2-4个字节 这样很浪费空间

于是出现了UTF 编码(变长存储)

总结:UTF 是 unicode的编码设计的一种在存储和传输时节省空间的编码方案

可以参考我之前写的文章 计算机是如何存数据的

所有电脑现在都默认是unicode字符集,方便你以后的软件出口,或者10年前的项目不用改写

python3代码执行流程

参考链接

  • 在python3里内存里全是unicode编码
  • python3里默认是utf-8编码
  1. 解释器找到代码文件,把代码字符串按文件头定义的编码(#-- encoding:utf-8 --)加载到内存,转成unicode
  2. 把代码字符串按照语法规则进行解释,
  3. 所有的变量字符都会以unicode编码声明

结论就是:python3在内存里把你的编码转成unicode,即使你的输出环境是gbk也能正常显示

深坑 Python2并不会自动的把文件编码转为unicode存在内存里

如果你是utf-8编码,windows系统是gbk就会显示乱码

怎么办?人肉转

1
2
UTF-8 --> decode 解码 --> Unicode
Unicode --> encode 编码 --> GBK / UTF-8...

python只要出现各种编码问题,无非是哪里的编码设置出错了

常见编码错误的原因有:

  • Python解释器的默认编码
  • Python源文件文件编码(千万不要轻易改文件的编码不可逆,一旦失败就白玩了)
  • Terminal使用的编码
  • 操作系统的语言设置

结论:

py3

  • 文件默认编码是 utf-8
  • 字符串编码是 unicode

py2

  • 文件默认编码是 ascⅡ
  • 字符串编码是 ascⅡ
  • 如果文件头声明了gbk,那字符串的编码就是gbk

Py001_02_05Python哈希和字典

hash

hash值计算过程中依据这个值一些特征计算的,这就要求hash值必须固定,因此被hash的值必须是不可变的

不可变数据类型

  • 数字
  • 字符串
  • 元组

可变数据类型

  • 列表

hash函数

1
2
3
hash('aaa') 
hash(1)
hash((1,2,3))

字典

键值对 k/v

特性

  • k/v
  • key必须放可hash ,且必须为不可变数据类型,必须唯一
  • value可存放任意多个值,可修改,可以不唯一
  • 无序
  • 查找速度快
1
2
3
4
infos = {
"name":'alex',
"age":22
}

crud

增加

1
2
info = {}
info['a'] = 2

修改

1
2
info = {"a":2}
info['a'] = 3

查找

1
2
3
4
5
6
7
8
9
10
11
info = {
"a":1,
"b":2,
"c":3
}

"aa" in info # 判断key在不在info里
info.get('a') # 1
info.get('aaa') # None

如果直接 info['aaa'] 会报错

删除

  • pop(删除的key)
  • popitem() 随机删
  • del info[key]删除某个key
  • clear() 清空字典

其他方法

  • keys() 获取key的列表
  • values() 获取值的列表
  • items() 将key和value放入到元组里,返回一个列表
  • setdefault() 查看字典是否有这个key没有则设置默认值,有没有都返回这个key对应的值
  • fromkeys() 批量生成字典,并设置默认值

集合类型

如何找出既买了iphone7和8的人

1
2
i7 = ["a","b","c","d"]
i8 = ["a","b","d"]

什么是集合

无序的,不重复的数据集合

  • 去重,把一个列表变成集合就自动去重了
  • 关系测试
1
2
3
4
5
6
7
8
9
s = {}
type(s) # dict 集合是空的时候被认为是字典

s = {1}
type(s) # set

s = set([1,2,2,3,4]) # {1,2,3,4}

s = {1,2,3,4,5,6,2,3,4} # {1,2,3,4,5,6}

CRUD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
s = {1,2,3,4,5}
s.add(2) # {1,2,3,4,5}
s.add(6) # {1,2,3,4,5,6}


s.discard(6) # 删除指定元素 {1,2,3,4,5}

s.discard(6) # 如果元素不存在不报错 {1,2,3,4,5}


s.remove(5) # {1,2,3,4}
s.remove(5) # 不存在报错

s.pop() # 随机删


s2 = {1,2,3}
s2.update([3,4,5,6])
# {1,2,3,4,5,6}

集合的关系测试

1
2
i7 = {"a","b","c","d"}
i8 = {"a","b","e","f"}

交集

1
2
3
4
5
第一种
i7.intersection(i8) # {"a","b"}

第二种
i7 & i8 # {"a","b"}

差集

1
2
3
4
5
6
7
8
# 买了i7没买i8的人
i7.difference(i8) # {"c","d"}
i7-i8


# 买了i8没买i7的人
i8.difference(i7) # {"e","f"}
i8-i7

并集

1
2
3
i7.union(i8) # {'d', 'e', 'f', 'c', 'a', 'b'}

i7|i8

对称差集

并集取反

1
2
3
i7.symmetric_difference(i8) # {'f', 'e', 'c', 'd'}

i7 ^ i8
  • difference_update 将差集的结果赋值给集合

关系

  • isdisjoint 判断两个集合是不是不相交
  • issuperset 是否包含
  • issubset 是否被其他集合包含
1
2
3
4
5
6
7
a = {1,2,3,4}
b = {1,2,3}
print(b.issubset(a)) # False
print(b.issubset(a)) # True

print(b.issuperset(a)) # False
print(a.issuperset(b)) # True

Py001_02_04Python再看字符串

字符串

有序的字符集合

特性

  • 有序
  • 不可变(一旦声明不可修改)
1
2
3
4
5
6
7
8
9
a = 'alex'
id(a) # 1435111012

a = 'bbb'
id(a) 3 3254554354
内存地址变了

a修改后并不是在原地址上修改,而是新开辟一片内存空间。
那之前的alex去哪里了? 答案是python解释器会定时的帮你把无用的地址清空掉
  • swapcase()大小写翻转
  • capitalize() 返回首字母大写其他全部小写的字符串
  • casefold() 去掉大小写 全变成小写
  • center() 返回字符填充
  • count() 统计字符个数
  • endswith() 是否以什么结尾
  • expandtabs() 设置制表符\t 的空格长度
  • find() 查找字符串 从左往右返回索引,未找到返回-1
  • format()
  • index() 返回查找字符串的索引,没有报错
  • isalnum() 是否是阿拉伯的数字和字符(同时包含字母和数字)
  • isdecimal() 是否是整数
  • isidentifier() 是否是合法的变量(包含字母数字下划线,但不能是数字开头)
  • islower() 是否是小写
  • isnumeric() 是否有数字在里面
  • isprintable() 这个值是否可以打印
  • istitle() 是否是标题,每个单词首字母大写
  • isupper()
  • join() 列表拼接
  • ljust() 字符串填充 s.ljust(50,’-‘)
  • strip() 去除左右两边空格和换行
  • lstrip()
  • rstrip()
  • maketrans()/translate() 通过字符生成某种映射关系,类似加密解密
  • partition() 以输入字符将字符分成两段
  • rpartition()
  • replace()
  • rfind()
  • rindex()
  • split() 按指定字符来分
  • splitlines() 按行来分
  • startstwith()
  • endswith()
  • zfill()

format()

1
2
3
4
5
s = 'my name is {0}, i am {1} years old'
s.format('alex',22)

s2 = 'my name is {name}, i am {age} years old'
s.format(name='alex',age=22)

index()

1
2
3
4
s = 'hello world'
s.index('o') # 4

s.index('o',5,6) # 报错

如果你是pycharm在这些函数上按住ctrl可以查看源码(但是只有解释没有实际的代码因为是c语言实现的)