一、文件操作:
打开文件:
f = open("db", "r") #只读
f = open("db", "w") #只写,注意,是先清空原文件
f = open("db", "x") #文件存在报错,不存在,创建并写内容
f = open("db", "a") #追加
f = open("db", "rb") #加b以二进制模式打开,(rb,wb,ab,xb),应用场景网络传输中用二进制传输
f = open("db", "r")
data = f.read()
print(data, type(data))
f = open("db", "rb") #二进制没有编码,读时不加编码encoding="utf8"
data = f.read()
print(data, type(data))
f = open("yesterday","wb")
f.write("hello binary".encode('utf-8')) #encode转为二进制再写
f.close()
f = open("db", "a",encoding="utf8")
f.write("郭")
f.close()
f = open("db", "ab")
f.write(bytes("铁", encoding="utf8"))
f.close()
"+" 表示可以同时读写某个文件:
r+, 读写【可读,可写】
w+,写读【可读,可写】,需先清空
x+ ,写读【可读,可写】
a+, 写读【可读,可写】,无法设置指针位置
f = open("db", "r+", encoding="utf8")
data = f.read(8) #如果打开模式无b,则read,按照字符读取
print(f.tell()) #tell显示当前指针所在的位置,按字节
f.seek(f.tell()) #seek调整当前指针的位置,按字节
f.write("888") #当前指针位置开始然后向后覆盖
f.close()
f.flush() #刷新文件内部缓冲区
f.readable() #查看是否可读
f.readline() #仅读取一行
f = open("db" ,"r" ,encoding='utf-8') #读取10行
for i in range(10):
print(f.readline())
f.readlines() #把每行当作列表元素
不打印文件的第10行代码:
for index,line in enumerate(f.readlines()):
if index == 9:
print("分割线".center(50, "*"))
continue
print(line.strip()) # 脱去换行
不打印文件第10行代码(高效率):
count = 0
for line in f: #读一行删一行不占用内存空间
if count == 9:
count += 1
print("分割线".center(30, "+"))
continue
print(line.strip())
count += 1
f.truncate() #截断,清空指针后的内容
f.encoding #打印字符编码
f.flush() #从内存刷到硬盘
f.truncate() #不传参数清空文件,f.truncate(20)截取前20字符其它清空
"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)
rU
r+U
with打开文件:
with open("db", "r", encoding="utf8") as f:
pass
把db1中的每行,写到db2中,并且把guo替换为gang,代码:
with open("db1", "r", encoding="utf8") as f1, open("db2","w",encoding="utf8") as f2: #使用with最后不用close文件
for line in f1:
new_str = line.replace("guo","gang")
f2.write(new_str)
flush实现进度条代码:
import sys,time
for i in range(30):
sys.stdout.write("#")
sys.stdout.flush() # 每打印一次#,就从内存flush到硬盘中
time.sleep(0.5)
把yesterday写到yesterday.new,并修改一行,代码:
f = open("yesterday", "r", encoding="utf-8")
f_new = open("yesterday.new", "w", encoding="utf-8")
for line in f:
if "年少轻狂" in line:
line = line.replace("年少轻狂", "年轻真好")
f_new.write(line)
f.close()
f_new.close()
二、字符编码与转码:
需知:
1.在python2默认编码是ASCII, python3里默认是utf-8
2.unicode 分为 utf-32(占4个字节),utf-16(占两个字节),utf-8(占1-4个字节), so utf-8就是unicode
3.在py3中encode,在转码的同时还会把string 变成bytes类型,decode在解码的同时还会把bytes变回string
GBK需要转换为UTF-8格式流程:
1、首先通过编码【decode】转为Unicode编码
2、然后通过解码【encode】转为UTF-8编码
UTF-8需要转换为GBK格式流程:
1、首先通过编码【decode】转换为Unicode编码
2、然后通过解码【encode】转换为GBK编码
python2中:
#-*-coding:utf-8-*-
__author__ = 'Alex Li'
import sys
print(sys.getdefaultencoding()) # 打印默认编码
msg = "我爱北京*"
msg_gb2312 = msg.decode("utf-8").encode("gb2312")
gb2312_to_gbk = msg_gb2312.decode("gbk").encode("gbk")
print(msg)
print(msg_gb2312)
print(gb2312_to_gbk)
python3中:
#-*-coding:gb2312 -*- #这个也可以去掉
__author__ = 'Alex Li'
import sys
print(sys.getdefaultencoding())
msg = "我爱北京*"
#msg_gb2312 = msg.decode("utf-8").encode("gb2312")
msg_gb2312 = msg.encode("gb2312") #默认就是unicode,不用再decode
gb2312_to_unicode = msg_gb2312.decode("gb2312")
gb2312_to_utf8 = msg_gb2312.decode("gb2312").encode("utf-8")
print(msg)
print(msg_gb2312)
print(gb2312_to_unicode)
print(gb2312_to_utf8)
三、函数
定义函数,函数体不执行。
在函数中,一旦执行return,函数执行过程立即终止。
1、编程语言中函数定义:函数是逻辑结构化和过程化的一种编程方法。
python中函数定义方法:
def test(x):
"""The function definitions"""
x+=1
return x
def:定义函数的关键字
test:函数名
():内可定义形参
""" """:文档描述(非必要,但是强烈建议为你的函数添加描述信息)
x+=1:泛指代码块或程序处理逻辑
return:定义返回值
2、为何使用函数:
例一:
假设我们编写好了一个逻辑(功能),用来以追加的方式写日志:
with open('a.txt','ab') as f:
f.write('end action')
现在有三个函数,每个函数在处理完自己的逻辑后,都需要使用上面这个逻辑,那么唯一的方法
就是,拷贝三次这段逻辑
def test1():
print 'test1 starting action...'
with open('a.txt','ab') as f:
f.write('end action')
def test2():
print 'test2 starting action...'
with open('a.txt','ab') as f:
f.write('end action')
def test3():
print 'test3 starting action...'
with open('a.txt','ab') as f:
f.write('end action')
那么假设有>N个函数都需要使用这段逻辑,你可以拷贝N次吗?
例二:
优化后的代码
def logger_test():
with open('a.txt','ab') as f:
f.write('end action')
def test1():
print 'test1 starting action...'
logger_test()
def test2():
print 'test2 starting action...'
logger_test()
def test3():
print 'test3 starting action...'
logger_test()
例三:
需求变了(让我们来为日志加上时间吧)
import time
def logger_test():
time_format='%Y-%m-%d %X'
time_current=time.strftime(time_format)
with open('a.txt','ab') as f:
f.write('time %s end action' %time_current)
def test1():
print 'test1 starting action...'
logger_test()
def test2():
print 'test2 starting action...'
logger_test()
def test3():
print 'test3 starting action...'
logger_test()
总结例二和例三可概括使用函数的三大优点
1.代码重用
2.保持一致性
3.可扩展性
3、函数返回值:
def test01():
pass
def test02():
return 0
def test03():
return 0,10,'hello',['alex','lb'],{'WuDaLang':'lb'}
t1=test01()
t2=test02()
t3=test03()
print 'from test01 return is [%s]: ' %type(t1),t1
print 'from test02 return is [%s]: ' %type(t2),t2
print 'from test03 return is [%s]: ' %type(t3),t3
总结:
返回值数=0:返回None
返回值数=1:返回object
返回值数>1:返回tuple
4、参数:
形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)
实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参
def sendmail (user,content): #括号内为形式参数
print("发送成功",user,content)
return True
while True:
em = input("请输入邮箱:")
result = sendmail(em,"hello") #括号内为要传的实际参数
if result == True:
print("发送成功")
else:
print("发送失败")
普通参数(严格按照顺序,将实际参数赋值给形式参数)
def sendmail (user,content):
默认参数(默认参数必须放在普通参数列表的末尾)
def sendmail (user,content,moren="OK",moren2="OKOK"):
指定参数(将实际参数赋值给指定的形式参数)
def sendmail (user,content):
sendmail(content="hello",user="gtg")
动态参数(*默认将传入的参数,全部放置到元组中)
def f1(*args):
print(args,type(args))
f1(11,22,33,"vn")
def f1(*args):
print(args,type(args))
list1 = [11,22,33,"vn"]
f1(*list1) #把列表中的元素,赋值为元组中的元素
动态参数(**默认将传入的参数,全部放置到字典中)
def f1(**kwargs):
print(kwargs,type(kwargs))
f1(n1="vn",n2=55)
def f1(**kwargs):
print(kwargs,type(kwargs))
dict1 = {"n1":"vn","n2":55}
f1(**dict1) #把字典中的元素,赋值为**字典中的元素
万能参数:(*在前面**在后面,一般习惯写为*args,**kwargs)
def f1(*args,**kwargs):
print(args)
print(kwargs)
f1(11,22,33, k1="v1",k2="v2")
def fun1(a1):
a1.append(999)
list1 = [11,22,33]
fun1(list1) #函数传参数,传递的是引用
print(list1
print(list1)
四、局部与全局变量
在子程序(函数)中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
全局变量:(所有作用域,都可读。定义全局变量习惯都大写)
函数内对全局变量重新赋值,需要global
列表字典,可修改,不可重新赋值
NAME = "guo"
def fun1():
age = 27
global NAME 表示,NAME是全局变量
NAME = "gtg"
print(NAME,age)
fun1()
五、递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
递归1*2*3*4*5*6阶乘代码:
def cheng(n):
if n == 1 or n == 0 : #计算1和0的阶乘时,直接返回1
return 1
return n*cheng(n-1)
r = cheng(6)
print(r)
递归除以2代码:
def calc(n):
print(n)
if int(n/2) ==0:
return n
return calc(int(n/2))
calc(10)
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3.递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)