失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 第三章 三元运算 文件处理 函数

第三章 三元运算 文件处理 函数

时间:2022-05-27 23:31:36

相关推荐

第三章 三元运算 文件处理 函数

第三章、三元运算、文件处理、函数

三元运算

三元运算又称三目运算,是对简单的条件语句的简写,如:

简单条件语句:

if 条件成立:val = 1else:val = 2# 可以写成如下:val = 1 if 条件成立 else 2

文件处理

读,写,修改

f = open(file='d:/*.txt', mode='r', encoding='utf-8')date = f.read()f.close()

r是只读模式,rb是以二进制读文件

第三方模块 chardet检测二进制内容可能是什么编码

使用pip安装第三方库,py3就用pip3 install chardet

import chardet

chardet.detect(data)

{'encoding':'GB2312','confidence':0.823045,'language':'Chinese'}

循环文件

f = open("*.txt", "r", encoding="gbk")for line in f:print(line)f.close()

print每次执行之后会自动换行

写文件

模式 w 写模式,wb二进制写模式

f.write("路飞".encoding("gbk"))

以wb模式写的时候需要指定以什么编码写

w写模式会先清空文件,然后去写,相当于直接覆盖文件原有的内容

w就是一个创建模式

追加

a 追加模式,,ab二进制追加模式

读写混合模式

r+ 读写模式,先读后写,读完可以追加.

f.read()读完之后会将指针指向文件内容末尾,再次执行f.read()就读到是空

w+写读模式,先写后读,先往里覆盖写,再去读你写的内容.(相当于先创建了一个空文件替换掉原来的,然后可以读这次新写的内容,几乎用不到)

文件操作的其他功能方法

def fileno(self, *args, **kwargs): 返回文件句柄在内核中的索引值,以后做IO多路复用时可以用到def flush(self, *args, **kwargs): 把文件从内存buffer里强制刷新到硬盘def readable(self, *args, **kwargs): 判断是否可读def readline(self, *args, **kwargs): 只读一行,遇到\r or \n为止,指针会指向下一行开头.def seek(self, *args, **kwargs): 把操作文件的光标移到指定位置*注意seek的长度是按字节算的, 字符编码存每个字符所占的字节长度不一样。如“路飞学城” 用gbk存是2个字节一个字,用utf-8就是3个字节,因此以gbk打开时,seek(4) 就把光标切换到了“飞”和“学”两个字中间。但如果是utf8,seek(4)会导致,拿到了飞这个字的一部分字节,打印的话会报错,因为处理剩下的文本时发现用utf8处理不了了,因为编码对不上了。少了一个字节def seekable(self, *args, **kwargs): 判断文件是否可进行seek操作def tell(self, *args, **kwargs): 返回当前文件操作光标位置,按字节单位def truncate(self, *args, **kwargs): 按指定长度截断文件*指定长度的话,就从文件开头开始截断指定长度,不指定长度的话,就从当前位置到文件尾部的内容全去掉。模式必须可写def writable(self, *args, **kwargs): 判断文件是否可写

f.tell() 返回当前光标位

f.seek(0) 将光标移到文件开头

f.tell()和f.seek(0)都是以字节为单位

f.read(1)是以字符为单位,gbk中一个中文字符2个字节,utf-8中一个中文字符3个字节

修改文件

f = open("兼职白领学生空姐模特护士联系方式utf8.txt",'r+',encoding="utf-8")f.seek(6)f.write("[路飞学城]")f.close()

王心[路飞学城]9 46 1381234424马纤羽深圳 173 50 1374423423乔亦菲广州 172 52 1582342525罗梦竹北京 175 49 1862343421刘诺涵北京 170 48 1862343765岳妮妮深圳 177 54 1883524553贺婉萱深圳 174 52 1893344452叶梓萱 上海 171 49 1804242324杜姗姗 北京 167 49 13324523342black girl 河北 167 50 13542342233

确实从第3个字开始改的,但是[路飞学城] 把后面的内容覆盖了

练习题

练习题1 —— 全局替换程序:

写一个脚本,允许用户按以下方式执行时,即可以对指定文件内容进行全局替换

`python your_script.py old_str new_str filename`

替换完毕后打印替换了多少处内容

# -*- coding:utf-8 -*-# !/usr/bin/env python# Author:dc0012import sysold_str = sys.argv[1] # 接受被替换文本参数new_str = sys.argv[2] # 接收新文本file_name = sys.argv[3] # 接收需要处理的文件名字f = open(file_name, "r+", encoding="utf-8")content = f.read().replace(old_str, new_str) # 替换后的文件全部内容给contenf.seek(0) #将指针移到文件开头f.write(content) # 将替换后的文件内容写入文件f.truncate(f.tell()) # 防止新内容比旧内容少,将多出来的截取出去f.close()

例: python your_script.py 北京 陕西 f_test

将f_test文件中的北京替换为陕西.

练习题2 —— 模拟登陆:

用户输入帐号密码进行登陆用户信息保存在文件内用户密码输入错误三次后锁定用户,下次再登录,检测到是这个用户也登录不了

# -*- coding:utf-8 -*-# !/usr/bin/env python# Author:dc0012import syswith open("lock_account", "r+") as f_lock:with open("account", "r") as f_account:count = 0_username = input("username:").strip()for i in f_lock:if _username == i.strip():print("This account was locked....")sys.exit()for i in f_account:username, password = i.strip().split(",")if _username == username:while count < 3:_password = input("password:")if _password == password:print("Welcome %s login..." % _username)sys.exit()else:print("Wrong password...")count += 1continueelse:print("You have tried too many times.This username will be locked")f_lock.write(_username + "\n")sys.exit()print("No such this username....")sys.exit()

account存放用户名密码一行为一个用户,用","隔开用户名密码,例:dc,123

lock_account存放被锁定的用户名,一行一个用户名.

函数

定义:

函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

特性:

减少重复代码使程序变的可扩展使程序变得易维护

语法定义

def sayhi():#函数名print("Hello, I'm nobody!")sayhi() #调用函数

带参数

#下面这段代码a,b = 5,8c = a**bprint(c)

#改成用函数写def calc(x,y):res = x**yreturn res #返回函数执行结果c = calc(a,b) #结果赋值给c变量print(c)

函数参数

参数可以让你的函数更灵活,不知能做死的动作,还可以根据调用时传参的不同来决定函数内部的执行流程

形参变量:

只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元.因此形参只在函数内部有效.函数调用结束返回主调用函数后则不能再使用该形参变量.

实参:

可以是常量,变量,表达式,函数等.无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传给形参.因此应预先赋值,输入等办法使参数获得确定值.

默认参数:

在定义函数的时候赋予参数一个默认的值,如果调用的时候不给这个参数赋值,它就会调用默认的参数进行处理

默认参数必须放在位置参数后面

定义默认参数要牢记一点:默认参数必须指向不变对象!比如:如果默认参数是个空列表,而一旦更改了这个默认空列表的值,在下次调用时就会以更改后的列表作为参数来调用.

关键参数:

正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),*但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后*

赋值的时候指定对象赋值的参数叫关键参数

def stu_register(name, age, course='PY' ,country='CN'):print("----注册学生信息------")print("姓名:", name)print("age:", age)print("国籍:", country)print("课程:", course)

调用可以这样

stu_register("王山炮",course='PY', age=22,country='JP' )

但绝不可以这样

stu_register("王山炮",course='PY',22,country='JP' )

当然这样也不行

stu_register("王山炮",22,age=25,country='JP' )

这样相当于给age赋值2次,会报错!

非固定参数:

若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数

def stu_register(name,age,*args): # *args 会把多传入的参数变成一个元组形式print(name,age,args)stu_register("Alex",22)#输出#Alex 22 () #后面这个()就是args,只是因为没传值,所以为空stu_register("Jack",32,"CN","Python")#输出# Jack 32 ('CN', 'Python')

还可以有一个**kwargs

def stu_register(name,age,*args,**kwargs): # *kwargs 会把多传入的参数变成一个dict形式print(name,age,args,kwargs)stu_register("Alex",22)#输出#Alex 22 () {}#后面这个{}就是kwargs,只是因为没传值,所以为空stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong")#输出# Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}

**kwargs 接收关键字参数,自动转换为字典.

如果定义函数的参数前出现了*,那么这个函数传递的参数就可以不再是固定个数,传过来的所有参数打包成一个元组

>>> nums = [1, 2, 3]>>> calc(*nums)14

*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。

函数返回值

函数外部的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回

注意

函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束如果未在函数中指定return,那这个函数的返回值为None

函数永远只能返回一个值,这个值可以是一个元组,一个列表,一个字典

局部变量

在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。全局变量作用域是整个程序,局部变量作用域是定义该变量的函数。当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。

在函数里修改全局变量

在函数内部使用global 变量名 ,来声明此变量为全局变量,进行修改

一般不建议在函数内部更改全局变量

字典,列表,集合,对象,类里面的对象是可以在函数内部直接修改的全局变量如果是字符串,整型的话,是不能在函数内部直接更改的.

函数小结:

定义函数时,需要确定函数名和参数个数;如果有必要,可以先对参数的数据类型做检查;函数体内部可以用return随时返回函数结果;函数执行完毕也没有return语句时,自动return None。函数可以同时返回多个值,但其实就是一个tuple。

嵌套函数

函数内部可以再次定义函数执行需要被调用

age = 19def func1():# global age 定义全局变量后就不会出错def func2():print(age)func2()age = 73 func1()# 这种调用会导致出错

作用域

python中一个函数就是一个作用域局部变量放置在其作用域中定义完成后,作用域已经生成,作用域链向上查找

匿名函数

声明一个匿名函数

lamdba x, y: x*y # 声明一个匿名函数

lambda只支持简单的逻辑,最多支持三元运算语法

def func1(x, y):if x < y:return x * yelse:return x / y# 上面的函数换成lambda就是下面的格式func2 = lambda x, y: x * y if x < y else x / y

和其他方法搭配使用,用完就丢弃了

作用:

节省代码量看着高级

高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数.

只需要满足以下任意一个条件,即是高阶函数:

接收一个或多个函数作为输入return返回另外一个函数

递归函数

递归特性:

必须有一个明确的结束条件每次进入更深一层递归时,问题规模相比上次递归都应有所减少递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧,由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

先举个简单的例子:计算1到100之间相加之和;通过循环和递归两种方式实现

#!/usr/bin/env python3# 1-100 sumimport sysdef sum_cycle(n):'''1 to n,The sum function'''sum = 0for i in range(1,n + 1):sum += ireturn sumdef sum_recu(n):'''1 to n,The sum function'''if n > 0:return n + sum_recu(n - 1)#调用函数自身else:return 0print("循环求和:",sum_cycle(100))print("递归求和:",sum_recu(100))执行结果:[root@localhost tmp]# ./sum.py循环求和: 5050递归求和: 5050

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

***使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

把上面的递归求和函数的参数改成10000就导致栈溢出!

[root@localhost tmp]# ./sum.py循环求和: 5050Traceback (most recent call last):File "./sum.py", line 23, in <module>print("递归求和:",sum_recu(1000))File "./sum.py", line 19, in sum_recureturn n + sum_recu(n - 1)File "./sum.py", line 19, in sum_recureturn n + sum_recu(n - 1)File "./sum.py", line 19, in sum_recureturn n + sum_recu(n - 1)[Previous line repeated 994 more times]File "./sum.py", line 18, in sum_recuif n > 0:RecursionError: maximum recursion depth exceeded in comparison

***解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

尾递归优化:http://www.open-/lib/view/open1480494663229.html

二分法查找大家应该听说过;就是一种快速查找的方法,时间复杂度低,逻辑简单易懂,总的来说就是不断的找出中间值,用中间值对比你需要找的实际值;若中间值大,则继续找左边;若中间值小,则继续找右边;可以看出二分法就是不断重复此上过程,所以就可以通过递归方式来实现二分法查找了!

小结

使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

#!/usr/bin/env python3#The binary search functiondef Binary_Search(data_source,find_n):if len(data_source) >= 1: #判断列表长度是否大于1,小于1就是一个值mid = int(len(data_source)/2)#获取列表中间索引;奇数长度列表长度除以2会得到小数,通过int将转换整型if find_n > data_source[-1]:#判断查找值是否超出最大值print('{}查找值不存在!'.format(find_n))exit()elif find_n < data_source[0]:#判断查找值是否超出最小值print('{}查找值不存在!'.format(find_n))exit()if data_source[mid] > find_n: #判断列表中间值是否大于查找值#print('查找值在 {} 左边'.format(data_source[mid]))Binary_Search(data_source[:mid],find_n) #调用自己,并将中间值左边所有元素做参数elif data_source[mid] < find_n: #判断列表中间值是否小于查找值#print('查找值在 {} 右边'.format(data_source[mid])) #调用自己,并将中间值右边所有元素做参数Binary_Search(data_source[mid:],find_n)else:print('找到查找值',data_source[mid])#找到查找值else:print('{}查找值不存在!'.format(find_n))#特殊情况,返回查找不到Data = [22,12,41,99,101,323,1009,232,887,97]Data.sort() #列表从小到大排序Binary_Search(Data,323) #查找323执行结果:[root@localhost tmp]# ./binary_search.py 找到查找值 323

内置方法

如果觉得《第三章 三元运算 文件处理 函数》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。