第三周

本周内容(第三周)

文件操作

1.文件的概念:
操作系统显示给用户可以直接操作硬盘的快捷方式,
打开文件的两种方式:
f = open(r'a.txt', 'r', encoding='utf8')
f.close() 关闭打开的文件
-------------------------------------------------------------------------------------
with open(r'a.txt', 'a', encoding = 'utf8') as f:
我们写路径的时候可能会遇到带有特殊含义的特殊符号,所以在文件路径前+r
------------------------------------------------------------------------------------
2. 文件的读写模式
文件读写模式有三种:
r 只读不写,文件不存在报错  # read
w 只写不读,文件不存在自动创建文件  清空文件在写入数据 # write
a 只追加模式 文件不存在自动创建文件,在文件的末尾添加数据
------------------------------------------------------------------------------------
3.文件的操作模式
t模式: 文本模式  全称  rt  wt  at  必须指定encoding参数,以字符为最小单位
b模式: 二进制模式 全称  rb  wb  ab  不需要指定encoding参数,以字节为最小单位
------------------------------------------------------------------------------------
4.文件的诸多方法
read() 一次性读取文件内容
readline() 一次只读一行内容
readlines() 一次性读取文件内容,结果是个列表对应每行内容
readable() 判断文件是否是可读的
write() 写入文件
writelines() 一次性将列表数据写入文件
writeable()判断文件是否是可读的
flush() 保存 相当于Ctrl + s
------------------------------------------------------------------------------------
5.文件的光标移动
seek(offset, whence)
offset 是位移量(以字节为单位),  whence是模式,默认是0
模式分为三种:
0 让光标移到文件开头处  支持 文本模式和二进制模式
1 让光标停留在当前位置  只支持二进制模式
2 让光标移到文件末尾  只支持二进制模式
with open(r'userinfo.txt','r',encoding='utf8')as f:
    print(f.read(1))  
    f.seek(3,0)  # 光标移动3个字节   
    print(f.read(1))

文件的修改

1.计算机修改硬盘数据的原理
硬盘有两个形态, 占有态 和自由态
当我们在删除数据的时候,是将删除的数据改为自由态,在新数据放到自由态位置时,就会把他给覆盖。变成占有态。    
文件数据在硬盘上是写死的,我们没有办法在中间添加新的内容,只能将老数据删除之后重新写新数据。
------------------------------------------------------------------------------------
2.修改文件的两种方式
	先将文件内容一次性读写的内存中,使用只写不读模式进行修改,在文件修改过程中同一数据只有一份。 缺点:文件数据过大会导致内存溢出。
a.txt 今天头有点晕
with open(r'a.txt', 'r', encoding=‘utf8’) as f: 
    data = f.read()  打开文件并用一个变量名绑定文件地址
with open(r'txt', 'w', encoding = 'utf8') as f2:
    f2.write(data.replace('今天', '哎呦')) 替换文件中今天为哎呦。
------------------------------------------------------------------------------------
	用写的模式打开源文件,再用写的模式打开一个临时文件,一行行读取原文件内容。修改完成后写入临时文件,删除源文件将临时文件重命名为原文件
import os
with open(r'a.txt', 'r', encoding = 'utf8') as read_f,\open(r'a.txt', 'w', encoding = 'utf8') as write_f:
for i in read_f:
    write_f.write(i)  # 把 i 获取到的内容写入write_f
os.remove('a.txt')  # 删除a.txt
os.rename('a.txt.swap', 'a.txt')  # 把.a.txt.swap 改名为 a.txt   

函数

什么是函数

函数其实就是工具,提前定义好,可以反复拿出来使用

语法结构

1.函数的语法结构:
def 函数名+(参数):
    # 函数注释
    函数体代码
    return 返回值
调用  # 参数和返回值可有可无,根据调用时是否传参来确定要不要填参数
2.函数与循环的区别:
在相同的地方,反复执行相同的代码>>>循环
在不同的地方,反复执行相同的代码>>>函数

函数的定义与调用

定义函数需要使用def关键字.定义时不会执行函数,只会检测语法。
函数在调用阶段才会执行函数体代码。
函数必须先定义后调用。

函数的分类

1.空函数
在我们搭建功能的时候,提醒我们这里是什么功能
def f1():
    # 功能
2.无参函数
def f2():
    print('111')
 定义函数时阔号内没有输入参数。
3.有参函数
def f3(a):
	print(a)
定义函数时括号内填写了参数,调用时传参数
    

函数的返回值

return 
在我们调用函数时得到的结果就是返回值
如何获取返回值:
变量名 = 函数调用
def test():
	print('今天头疼')
没有 return 关键字,返回值是None
------------------------------------------------------------------------------------
def test():
    print('今天头疼')
    return
a = test()
print(a)
有return关键词,没返回值
------------------------------------------------------------------------------------
def test():
    print('今天头疼')
    return '头疼啊'
a = test()
print(a)  # 头疼啊
有return关键字后面有返回值
"""
在函数里遇到return 会终止函数体代码,类似于循环里的break
return 后面跟着什么就会返回什么
return 后面有多个数据会组成元组返回
return 后面没有 返回None
没有return 返回 None
"""

形参与实参

定义时小括号内的参数,用来接收参数 --形参
调用时小括号内参数,用来传递参数 -- 实参
关系:
在调用函数的时候 传入实参会与形参临时绑定,函数结束运行自动解绑
形参类似于变量名, 实参类似于 变量的值

函数参数

位置参数

要诀
"""越短的越简单的越靠前
   越长的越复杂的越靠后"""


位置参数
位置形参与位置实参必须保证个数相同,位置相同。 依照从左往右的顺序
-------------------------------------------------------------------------------------
位置形参
定义函数阶段小括号内填写
def fo(a,b):
   函数体代码
------------------------------------------------------------------------------------
位置实参
def fo(a,b):
    函数体代码
fo(1,2)
调用阶段括号内填写,也可以打断顺序,使用a = 1,b = 2的形式,一个形参同时不能多次赋值

默认参数

默认参数也称为 关键字参数
填写好默认参数 实参处可以不传,默认是形参填写的参数。
def foo(a, name = 'tank'):
    print(a,name) # 1, tank
foo(1,) # name 默认参数时tank
------------------------------------------------------------------------------------
修改默认参数需要在实参处填写
foo(1, 'jack')  # 此时默认参数tank 修改成 jack
------------------------------------------------------------------------------------
关键字参数说白了就是指名道姓的传参。
foo(a = 2 , name = 345)
------------------------------------------------------------------------------------
可以打乱顺序
foo(name=1, a = 2) # 必须使用关键字 不能 (name = 1 ,1)

可变长参数`重要

  在参数中带有一个* 或者两个**的(*后面跟着变量名 **也是如此) 我们称为可变参数。
*后面变量名可以随意写,但是一般是由*args  **kwargs 因为常用所以一般人都能看懂。
------------------------------------------------------------------------------------
*args
用来接收多余的位置参数  # 结果是元组
------------------------------------------------------------------------------------
**kwargs 
用来接收多余的关键字参数,组成字典的方式传给**后面的变量名
def foo(*args, **kwargs):
    print(args, kwargs)  
foo(1, 2, 3, 4, name=1, a=2)  # (1, 2, 3, 4) {'name': 1, 'a': 2}

可变长实参(重要)

* 和 **也可以在实参中使用
*在实参中可以把列表里的数据类似与for循环 取出,一次传递给函数
l1 = [2,3,5,6]
def foo(a,b,c,d):
    print(a,b,c,d) 
foo(*l1)  #2 3 5 6
字典只能取出键,集合取出来是无序的。
------------------------------------------------------------------------------------
** 在实参中可以把字典内的数据以k:v的形式打散成关键字参数,传给函数
d1 = {'name': 'jack', 'age': 18, 'salary': 20000}
def foo(name,age,salary):
    print(name,age,salary)
foo(**d1)  # jack 18 20000
也可以打乱关键字形参的顺序

名称空间

名称空间的含义

其实就是用来存放 变量名和数据值绑定关系的空间

名称空间的分类,存活周期,作用范围

1.内置名称空间
解释器已经定义好了。里面包含很多文字可以直接拿来用
存活周期:
运行paython解释器时产生
关闭python解释器销毁
作用范围:解释器全局有效
------------------------------------------------------------------------------------
2.全局名称空间
py文件运行时产生,存放文件级别的名字。
存活周期:
运行py文件时产生
关闭py文件时销毁
作用范围:
py文件内全局有效
------------------------------------------------------------------------------------
3.局部内存空间
函数体代码运行时产生的空间
存货周期:
函数体代码运行时产生
函数体代码结束时销毁
作用范围:
函数体代码内有效

名字的查找顺序

当我们在查找名字时要先确定自己的位置在哪里
在函数体代码内
局部名称空间-全局名称空间-内置名称空间
在全局名称空间内
全局名称空间- 内置名称空间

golbal与nonlocal

global
可以在局部名称空间修改全局名称空间内的数据
x = 11
def foo():
    global x
    x = 22
foo()
print(x) 22
------------------------------------------------------------------------------------
nonlocal
可以在内层局部空间修改外层局部空间的数据
def foo():
    x = 11
    def foo1():
        nonlocal x
        x = 22
    foo1()
	 print(x) 22	
foo()

函数名的多种用法

什么是函数名

函数名其实就是绑定的一块内存空间,只不过该空间内是一串代码,调用时执行该内存空间内的代码

多种用法

1.可以当做变量名赋值
def f1():
    print('变量名赋值')
res = f1
print(res)
res()
调用res = 调用f1 执行函数f1代码
------------------------------------------------------------------------------------
2.可以当做函数的参数
def func():
    print('参数用法')
def func1(a):
   	 print(a)
   	 a()
func1(func)
调用函数func1 此时传参func 给a  调用a =调用func
------------------------------------------------------------------------------------
3.可以当做函数的返回值
def func():
    print('返回值用法')
def func1():
    print('111')
    return func
res = func1()
print(res)
res()
调用func1 返回func 与res绑定 调用res=调用func
------------------------------------------------------------------------------------
4.可以当做容器使用
def register():  # 定义函数
    print('注册功能')
def login():	# 定义函数	
    print('登录功能')
def check_all():  # 定义函数
    print('查找功能')
def revamp():  # 定义函数
    print('修改功能')
def remove():  # 定义函数
    print('删除功能')
# 创建一个字典,用编号对应函数功能
func_dict = {
    '1': register,
    '2': login,
    '3': check_all,
    '4': revamp,
    '5': remove
}  
#  循环功能
while True:
    # 打印功能供用户选择
    print("""
        1.注册功能
        2.登录功能
        3.查找功能
        4.修改功能
        5,删除功能
        """)  
    choice = input('请输入想要的功能').strip()
    if choice in func_dict:
        num = func_dict.get(choice)
        num()

闭包函数

什么是闭包函数

定义在函数内部的函数,并用到了外部函数名称空间中的名字

闭包函数用法

def f1(name ,age):
	def f2():
        pringt(name,age)
    return(f2)
res = f1('tank',1997)
res()

装饰器

装饰器概念与本质

概念:
在不改变被装饰对象的代码与调用方式的情况下,给被装饰对象添加新的功能。
本质:
其实就是结合了函数参数,名称空间,函数多种用法,闭包函数结合到一起

装饰器模板与语法糖

def outer(func_name):
    def inner(*args,**kwargs):
        res = func_name(*args,**kwargs)
        return res
    return inner
语法糖
@outer
def func():
    pass
多层语法糖,需要提前定义多个装饰器
@outer1
@outer2
@outer3
def func():
    pass

有参装饰器模板

def outer_plus(a):
    def outer(func_name):
        def inner(*args,**kwargs):
            res = func_name(*args,**kwargs)
            return res
        return inner
    return outer

装饰器修复技术

from functools import wraps
ef outer(func):
    @wraps(func)
    def inner(*args, **kwargs):
		print('啥米是装饰器')
       res = func(*args, **kwargs)
    	return res
    return inner

@outer
def foo():
	print('我才是真正的foo')
修复技术只是用来忽悠你把函数foo改回成真的foo"""不是真的改,其实戴了个面具""" 啥都没变。 没啥用。

递归函数

在函数里直接或间接调用自制==递归函数
递归函数每一次必须比上一次更简单,距离答案更加近。不给返回值会一直循环递归,最大递归深度1000,超过1000报错。
用法:
计算1-100之和。
def func(a):
    in a < 1:
        return 1
    else:
        return func(n - 1) + n
 res = func(100)
print(res)

二分法

根据我们需要查找的数据在目标数据集里中分查找,没找到的情况下对比大小切分,重复至找到目标数据
l1 =[11,22,33,44,55,66,77,88,99]
def get(l1, target_num):
    # 结束条件
    if len[l1] == 0:
        return
    # 中分列表
    midder = len[l1] // 2
    if target_num > l1[midder]:
        #切割操作,保留右边
        right_l1 = l1[midder+1:] 
        # 因为顾头不顾尾的特性,该索引位已做过对比 
        return get(right_l1, target_num)
    elif target_num < l1[midder]:
        # 保留左边
        left_l1 = l1[:midder]
        return get(left_l1, target_num)
   	else:
        print('找到啦')
get(l1, 55)

三元表达式

我们判断条件只需要二选一时可以使用。简化代码
name = 'jack'
res = '真厉害' if name == 'jack' else '不行啊'
print(res) # 真厉害
数据值1 判断条件 数据值2
如果判断条件成立 执行 数据值1 ,判断条件不成立执行 数据值2

生成式

列表生成式

res = [添加的数据,for循环]
l1 = ['jason', 'tank', 'tony']
res = [f'{i}厉害' for i in l1]

字典生成式

res ={k:v形式, for循环k,v enenumerate(目标数据集)}
res = {k:v for k,v in enumerate(l1)}
enumerate 当你在循环一个数据集的时候给你产生从0开始的数字,也可以修改起始号码 在后面+ start= 20

集合生成式

res = {i for i in 'wokao'}
prit(res)

匿名函数

  没有函数名的函数,需要使用关键字
lambda
语法结构
lambda 形参:返回值
"""
        def func(a, b) 是def的声明部分,return a+b 是实现部分
        lambda x,y是声明部分,x * y是实现部分
    """

重要内置函数

1.map()映射
l1 = [12,21,26,31,40]
res = map(laambda x.y:x+y, l1)
-------------------------------------------------------------------------------------
2. max()\min()最大值最小值
res = max(l1) # 40
-------------------------------------------------------------------------------------
3.reduce 传多个值返回一个值
from functools import reduce
res = reduce(lambda a,b:a+b, l1)
-------------------------------------------------------------------------------------
4.zip 拉链
可以把两个列表的数据按照索引位的顺序合在一起,可以有多个,如果有短的,按照短的索引位 后面的不用
l1 = [11, 22, 33, 44, 55]
l2 = ['是我','是你','是他','是狗']
res = zip(l1,l2)
print(list(res))
-------------------------------------------------------------------------------------
filter 过滤
根据我们给的数据值固定条件
l1 = [11, 22, 33, 44, 55]
res = filter(lambda x:x > 22, l1)
-------------------------------------------------------------------------------------
sorted 排序
res = sorted(目标数据集)

常见内置函数

abs()绝对值
有符号的情况下只取数据值 。只限 + -
-------------------------------------------------------------------------------------
all() 
所有数据值为True 返回True 只要有一个Flase 返回Flase
-------------------------------------------------------------------------------------
any()
只要有一个数据为True返回True
-------------------------------------------------------------------------------------
bytes() 二进制模式
bin()其他进制转二进制
oct()其他进制转八进制
hex()其他进制转十六进制
int()其他进制转十进制
-------------------------------------------------------------------------------------
callable() 
判断变量名是否可以+括号调用。
-------------------------------------------------------------------------------------
chr() 把数字转换成ASCII码对应的字母
ord() 把字母转换成ASCII码对应的数字
A - Z = 65-90   a-z = 97- 122
-------------------------------------------------------------------------------------
dir() 可以查看该数据能用的内置方法
-------------------------------------------------------------------------------------
divmod()
主要用在网站的分页制作上
eg:
def foo(a1,a2):
	b1,b2 = divmod(a1,a2)  # (计算后的整数,余数)
   if b2:
    b1 += 1
    print(f'需要{b1}页')
foo(要计算的数据数,整除)
-------------------------------------------------------------------------------------
enumerate()枚举
eval() 识别字符串中的python并执行,只能识别简单的
exec() 识别字符串中的python并执行,可以识别复杂的
a1 = 'for i in name:print(i)'
exec(a1)
-------------------------------------------------------------------------------------
hash() 哈希加密 可以把字符串转成遗传你看不懂的数字
id() 查看内存地址 input() 获取用户输入 
-------------------------------------------------------------------------------------
isinstance(目标数据,数据类型) 判断数据类型
-------------------------------------------------------------------------------------
map() 映射
max()\min() 最大值最小值
open 打开文件
-------------------------------------------------------------------------------------
pow() 幂指数 次方
print(pow(4,2)) 16
-------------------------------------------------------------------------------------
sum() 求和
print(sum([1,2,3])  6

迭代对象

可以使用双下__iter__方法的都可以称为迭代对象。
迭代对象范围:
不可迭代对象:
int float 函数对象
可迭代对象:
str list dict set tuple 文件对象
迭代,更新换代的意思

迭代器对象

迭代对象调用双下__iter__方法后就变成了迭代器对象。
含有__iter__, __next__都是迭代器对象
理解:
对于一些有序文件如 列表,字符串,元组,我们可以使用索引取值的方式取出,而字典,集合这写没有索引位的我们没办法用索引取值,有了迭代器以后就可以给字典和集合取值了。注意是取键。
__next__调取数据一次只能调取一个,想要多个数据就要多次执行。获取完会报错

for循环本质

for循环的本质其实就是先调用了__iter__方法,后再用__next__获取数据,获取完会报错,for循环会自动捕捉报错然后处理。
for 变量名 in 迭代对象:

异常处理

在我们编写一段代码时往往在运行时会发生错误,如何处理这些错误呢。
报错位置分为三个区域。
报错代码位置。
报错类型,
报错详情。
我们可以根据报错详情得到报错的原因,然后根据代码的位置快速处理,如果出现多行报错那么只用看最近的一行,可能别的报错都是这行引起的。
报错分为两种:
语法错误  不允许出现
逻辑错误 因为藏得比较少,不容易看到,允许出现

周考核

1.编写⽤用户识别程序

要求:
可循环根据⽤用户输⼊入的姓名不不同输出不不同的身份信息
添加程序结束功能(如⽤用户输⼊入字⺟母q直接结束识别程序)
jason:扫地僧 tony:洗碗⼯ kevin:服务员 jack:配菜员 其他:未识别

# 1 先定义一个循环
while True:
    # 2获取用户输入
    # 8 增加结束循环条件
    username = input('请输入姓名>>>(q)').strip()
    if username == 'q':
        break
    # 3用户等于jason时 打印 扫地僧
    if username == 'jason':
        print('扫地僧')
    # 4用户等于tony时 打印 洗碗工
    elif username == 'tony':
        print('洗碗工')
    # 5 用户等于kevin时 打印 服务员
    elif username == 'kevin':
        print('服务员')
    # 6 用户等于jack时 打印 配菜员
    elif username == 'jack':
        print('配菜员')
    # 7 都不是 打印 未识别
    else:
        print('未识别')

2.利利⽤用for循环及range⽅方法自动生成链家⼆二手房多⻚页数据网址(十条以上即可)

http = 'https://sh.lianjia.com/ershoufang/pg%s/'
for i in range(0, 200, 1)
	print(http % i)

3.编写⽤用户登录程序

温馨提示:
用户名与密码来源于字符串串source_data = 'jason|123'
想办法从中拆分出⽤用户名和密码⽤用于后续账户信息⽐比对
普通要求:
1.验证失败情况下可⼀一直循环验证 成功则直接退出
拔⾼高练习:
1.只允许三次失败机会
2.登录成功后进⼊入内层循环,⽤用户输⼊入任何指令利利⽤用格式化输出
打印正在执⾏行行该⽤用户指令即可,直到⽤用户输⼊入字⺟母q退出内层循环

# 编写用户登录程序
# 5 定义一个计数器
count = 0
# 4 定义循环
while True:
    # 6 加入结束条件 3次
    if count == 3:
        print('你只有三次机会')
        break
    # 1获取用户输入
    usernmae = input('请输入用户名(q)').strip()
    passwold = input('请输入密码(q)').strip()
    # 2 拆分用户名密码
    real_name, real_pwd = source_data.split('|')
    # 3 校验用户名密码是否正确
    if usernmae == real_name and passwold == real_pwd:
        print('用户登陆成功')
        # 7添加内层循环
        while True:
            # 8 获取用户指令
            user_input = input('请输入指令(q)').strip()
            # 9 加入结束条件
            if user_input == 'q':
                print('下次在见')
                break
            print(f'正在执行{usernmae}该用户指令{user_input}')
    else:
        print('用户名密码错误')
        count += 1
        continue
posted @ 2022-10-16 19:42  李阿鸡  阅读(67)  评论(0编辑  收藏  举报
Title