编码
assic(只有英文及特殊字符) gb2312(6700) gbk(1995-21000) gb18030(27000) 万国码:unicode
python2.x默认为assic编码
python3.x默认为utf-8编码
改变编码:#-*- coding:utf-8 -*- (告诉py解释器,后面的代码用utf8来解释)
msg = "中国“
msg.decode(encoding="utf-8").encode(encoding="gbk") 先解码为unicode,然后在编码为gbk
python2
- py2里默认编码是ascii
- 文件开头那个编码声明是告诉解释这个代码的程序 以什么编码格式 把这段代码读入到内存,因为到了内存里,这段代码其实是以bytes二进制格式存的,不过即使是2进制流,也可以按不同的编码格式转成2进制流
- 如果在文件头声明了#_*_coding:utf-8*_,就可以写中文了, 不声明的话,python在处理这段代码时按ascii,显然会出错, 加了这个声明后,里面的代码就全是utf-8格式了
- 在有#_*_coding:utf-8*_的情况下,你在声明变量如果写成name=u"大保健",那这个字符就是unicode格式,不加这个u,那你声明的字符串就是utf-8格式
- utf-8 to gbk怎么转,utf8先decode成un
python3
- py3里默认文件编码就是utf-8,所以可以直接写中文,也不需要文件头声明编码了
- 你声明的变量默认是unicode编码,不是utf-8, 因为默认即是unicode了(不像在py2里,你想直接声明成unicode还得在变量前加个u), 此时你想转成gbk的话,直接your_str.encode("gbk")即可以
- 但py3里,你在your_str.encode("gbk")时,感觉好像还加了一个动作,就是就是encode的数据变成了bytes里,我擦,这是怎么个情况,因为在py3里,str and bytes做了明确的区分,你可以理解为bytes就是2进制流,你会说,我看到的不是010101这样的2进制呀, 那是因为python为了让你能对数据进行操作而在内存级别又帮你做了一层封装,否则让你直接看到一堆2进制,你能看出哪个字符对应哪段2进制么?
- 那你说,在py2里好像也有bytes呀,是的,不过py2里的bytes只是对str做了个别名(python2里的str就是bytes, py3里的str是unicode),没有像py3一样给你显示的多出来一层封装,但其实其内部还是封装了的。 这么讲吧, 无论是2还是三, 从硬盘到内存,数据格式都是 010101二进制到-->b'xe4xbdxa0xe5xa5xbd' bytes类型-->按照指定编码转成你能看懂的文字
编码应用比较多的场景应该是爬虫了,互联网上很多网站用的编码格式很杂,虽然整体趋向都变成utf-8,但现在还是很杂,所以爬网页时就需要你进行各种编码的转换,不过生活正在变美好,期待一个不需要转码的世界。
最后,编码is a piece of fucking shit, noboby likes it.
文件
r:只读模式(默认)
w:只写模式(不可读,文件不存在则创建,存在则覆盖原内容)
a:追加模式(可读,文件不存在则创建,存在则只在文件末尾追加内容)
+表示可以同时读写某个文件
r+:可读写文件(可读、可写、可追加)
w+:写读(清空原文件,再写入新内容**尽量少用**)
a+:同a
U表示在读取时,可以将 自动转换成 (与r或r+模式同时使用)
rU
r+U
b表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需注明)
rb
wb
ab
-----------------------------------------------------------------------------------
f = open("test","r+",encoding="utf-8")
print("cursor:",f.tell())
print(f.read())
f.write("test")
f.close()
open()#如果encoding不声明,默认使用操作系统的编码来解释文件
f.tell()#光标所在位置
f.seek(10)#将光标移动10个字节
f.read(10)#读取10个字符
f.flush()#将内存中的数据刷新至硬盘,一般用于打印实时日志
集合
name = {}
天生去重
关系运算
a = {1,2,3,4,5,6,7,}
b = {8,5,6,98,644,2,3}
#差集
print(a - b)
print(a.difference(b))
print(b - a)
print(b.difference(a))
##交集
print(b & a)
print(a.intersection(b))
print(b.intersection(a))
#并集
print(a | b)
print(a.union(b))
print(b.union(a))
#对称差集
print(a ^ b)
print(a.symmetric_difference(b))
print(b.symmetric_difference(a))
a = {1,2,3}
b = {1,2,3,4,5,6}
print(a.issubset(b)) #a是不是b的子集
print(a.issuperset(b)) #a是不是b的父集
函数
定义函数的三种形式:
1、无参函数:def foo(): print("in the foo") 调用时不用传参数:foo()
2、有参函数:def bar(x,y):print("in the bar") 调用时必须穿参数:bar(1,2)
3、空函数:def func():pass 用途:利用空函数制定好程序架构,然后再一个功能一个功能实现
调用函数的三种形式:
1 def foo(): 2 print("in the foo") 3 4 foo()
1 def my_max(x,y): 2 if x>y: 3 return x 4 else: 5 return y 6 7 my_max(1,2) 8 res = my_max(1,2) 9 res = 10*my_max(1,2)
1 def my_max(x,y): 2 if x > y: 3 return x 4 else: 5 return y 6 7 my_max(1,my_max(2,3))
函数返回值的三种形式,返回值可以是任意的数据类型:
1 def foo(): 2 pass 3 4 res = foo() 5 print(res)
1 def foo(): 2 return 1,'s',[1,2,3] 3 4 res = foo() 5 print(res) 6 7 结果:(1,'s',[1,2,3])
函数的参数:形参,实参
def name(x,y): #name函数名字,(x,y)形参
res = x**y
return res #return:1、返回函数结果;2、代表函数的结束
c = name(a,b) #(a,b)实参
print(c)
def foo(x,y):------>形参,只有在函数调用时才会接收到值,等函数运行完毕后马上释放内存
print(x)
print(y)
foo(1,2)---------->实参,真正占用内存空间
实参:有确定值的参数,所有数据类型都可以当作参数传递给函数
形参:只有在被调用的时候才分配内存,调用后,立刻释放内存,值仅在函数内部有效(形参的作用域只在当前函数内部生效)
从实参的角度可分为:按位置的方式和按关键字的方式
按位置的方式:
def foo(x,y):
print(x,y)
foo(1,2)
按关键字的形式:
def foo(x,y):
print(x,y)
foo(y=2,x=1)
对同一个形参,我们要么按照位置要么按照关键字为形参传值,对同一个形参不能重复赋值
关键字的形式的参数只能放在位置参数的后面
从形参角度可分为:位置参数,默认参数,可变长参数,**kwargs
位置参数:def foo(x,y,z) 也是必传参数,不能多也不能少
默认参数:def foo(x,y,z=1) z就是默认参数,调用时不是必须赋值
--------------------------------------------
def change(a):
print(a) #引用全局变量
a = "syan" #局部变量
print(a)
b = "bob" #全局变量
print(b)
change(b)
print(b)
全局变量默认不能被函数内部(局部变量)修改,只能引用
如果想在函数内部修改全局变量,需要在函数内部声明:global,但是强烈建议不这么使用
----------------------------------
def change():
print(names)
names[0] = "Mack"
names.append("lili")
info["age"] = 22
names = ["bob","tom"]
info = {"syan":"rain"}
change()
print(names,info)
结果:
['bob','tom']
['Mack','tom','lili']{'syan':'rain','age':22}
函数内部可以修改列表、字典、集合、实例(类)
位置参数:必须按顺序传入
默认参数:
关键参数:
默认参数和关键参数必须放在位置参数后面
非固定参数:*args = ()以位置参数的形式传人,**kwargs = {}以关键参数的形式传人
匿名函数:(labmda)
def calc(x,y):
return x**y
print(calc(10,12))
calc2 = lambda x,y:x**y
print(calc2(10,12))
匿名函数最复杂的运算就是三元运算:
def calc(x):
if x > 5:
return x*2
else:
return x-1
for i in map(calc,[1,2,3,4,5,6,7,8,9]):
print(i)
for i in map(lambda x:x*2 if x>5 else x-1,[1,2,3,4,5,6,7,8,9]):
print(i)
高阶函数:
def add(x,y,f):
return f(x) + f(y)
print(add(3,-5,abs))
abs为内置函数
函数在调用时不加(),则会调其内存地址
1、把一个函数的内存地址传给另一个函数当做参数
2、一个函数把另一个函数当做返回值返回
递归
def calc(n):
print(n)
if int(n/2)>0:
n = calc(int(n/2)) #将每层的结果赋值给n
print(n)
return n
print(calc(10))
可以得到最里层的值
特性:
必须有一个明确的结束条件
每次进入更深一层递归时,问题规模相对上一次递归都应有所减少
递归效率不高,递归层次过多会导致栈溢出