文件读写

1.文件操作
文件其实就是操作系统给我们一个快捷操作硬盘的方式,我们双击打开一个文本文件就是相当于硬盘存储的数据,加载到内存中
2.文件读写模式
文件操作模式有两种
一种是文本模式
一种是二进制模式(bytes)
主要读写模式为: 文本模式 rt wt at
			   二进制模式 rb wb ab
3.文件操作方法:
文件操作方法有两种方式

变量名 + 赋值符号 + open('文件路径','读写模式',encoding = '编码')
但是由于我们只是打开文件进行操作文件不会关闭,所以还需要我们使用close关闭文件
变量名.close()
with open('文件路径','读写模式',encoding = '编码') as 变量名:
	子代码(注意缩进)
这两种方法第二种with open 它可以帮你节省掉.close的操作 
4.文件内光标移动
文件内光标移动主要有
seek()
tell()
两种方法
seek()方法括号内需要填写两个参数,一个是偏移量,一个是whence模式
偏移量填写参数只能是偏移字节,whence模式有 0 1 2 0是从头开始 1是从光变所在位置开始
2 是从文件内内容末尾处开始

tell() 可以用此方法获取光标所在位置距离文件开始处的字节距离
6.计算机硬盘修改数据的原理
计算机内修改数据一般是存储数据的区域它的状态发生改变,从占有态变为自由态
此时文件内容并不会消失,而是等待着新内容存储到这个区域并进行覆盖才会把上次删除的信息消除
这是机械硬盘,固态硬盘是算法
7.文件内容修改
文件内容的修改是通过覆盖,修改后的内容覆盖原有的内容
或者是在别的地方新建一个文件把修改后的信息复制进去,然后把文件名字改成被修改的文件的名字,
这个过程很快

函数

1.函数简介
函数就是相当于一个工具包,我们在工作的时候需要经常用到这个工具,函数可以方便我们编写代码,不需要那么多重复的代码
在代码中,我们总是会写一些重复性代码,所以我们在这个时候需要用函数来简化我们的操作
函数的语法结构
def 函数名():
    '''函数注释'''
    函数体代码
    return

# 函数的定义以及调用:
函数的定义就是:
def 函数名():pass
我们调用的话就可以
函数名()就可以调用这个函数了
这个函数就会执行它下面的函数体代码
注意:当我们运行到到函数体代码中的 return 时,函数体代码会马上终止运行就相当于循环中的break 一样

函数的分类:
空函数:
空函数主要是提醒我们有一个空函数需要书写内容 里面的函数体代码用 pass 或 ... 跳过
有参函数:
def func(a):
	print(a)
有参函数在定义时,需要在()中填写形参
这样我们在调用这个函数的时候需要在函数名后面的括号中填写是实参
无参函数:
def func():
    print(123)
无参函数就是正常定义,调用时使用函数名加()就可以直接调用这个函数了

函数参数:
函数的参数有形参与实参两种
形参:形参就相当于变量名,他是在函数定义阶段函数名()里面需要添加的内容,它的存在时为了在调用这个函数时,在括号内填写相应的实参,主要是起一个提示作用
实参:实参填写就相当于实际的数据值,它是在调用阶段函数名括号内填写的

当函数被调用的时候,实参中的内容会与形参中的变量名临时绑定,函数体代码执行结束后会解除这个绑定关系

函数的返回值:
函数的返回值是 return 后面填写的内容
def func():
    print(123)
    return 'a'
 res = func()
 print(res)
当我们调用这个func函数的时候,我们就可以通过赋值符号加变量名获取它的返回值
我们要注意,先看赋值符号的右边,这是调用func函数,先运行func函数然后看到了return 马上停止函数体代码,返回值为a,并赋值给 res

函数参数:
函数参数分为位置参数、默认参数/关键字参数、可变长参数
位置参数:
位置形参 函数定义时在函数名括号里面从左到右依次填写的变量名
位置实参 函数调用时在函数名括号里从右到左依次填写的数据值
默认参数:默认参数是在函数定义时写在括号内提前定义好的关键字参数
我们设置好了默认参数后,在调用函数时可以不用传输实参,函数内会用默认参数定义好的参数
可变长参数:
可变长形参:
*args 用来接收多余的位置参数,通过*接收多余的参数并组成元组赋值给*后面的变量名
**kwargs 用来接收多余的关键字参数,通过**接收多余的关键字参数并组成字典赋值给**后面的变量名
我们在实参传参时如果需要传容器类型数据,可以通过*来传

命名关键字传参就是(位置参数加关键字参数加可变长参数)
位置参数优先 默认参数在*args 与** kwargs之间

名称空间及作用域:
名称空间分为局部、全局、内置
局部为函数内部的名称空间,当我们调用函数的时候生成局部名称空间,函数体代码运行结束的时候销毁空间
全局名称空间是当我们运行py文件的时候生成的,py文件运行结束的时候销毁空间
内置名称空间是我们打开python解释器的时候就会生成内置名称空间 我们关闭解释器的时候销毁此空间
名称查找顺序:
首先要看你所在的空间是什么
全局名称空间》》内置名称空间
局部名称空间》》》全局名称空间》》》内置名称空间

global 与 nonlocal:
    global 用局部名称空间,global 后面添加变量名 就可以修改全局的变量名
    nonlocal 用于局部名称空间 nonlocal 后面添加变量名 就可以修改它上一层包裹的局部名称空间
函数名的多种用法:
函数名可以是参数
函数名可以作为返回值
函数名可以赋值给变量名
函数名可以作为容器类数据类型中的数据值


闭包函数:
闭包函数它的定义为
定义在函数中的函数,并且使用了外部函数的变量名
闭包函数的应用场景主要是方便我们在传参数的时候如果想多次传相同的参数我们写了一个闭包函数我们填写一次参数就可以做到以后直接调用函数名()就可以了 填写一次参数就可以
需要修改的话直接改参数


装饰器的介绍
装饰器是在不改变定义好的函数的代码以及它的调用方式的情况下,给此函数附加新的功能
装饰器其实就是 闭包函数 函数参数 函数名的多种用房 名称空间 返回值 等一些知识点总结起来的 ,不是新技术
装饰器的模板:
def outer(function)
	def inner(*args,**kwargs)
    	res = function(*args,**kwargs)
        return res
    return inner
装饰器语法糖
装饰器语法糖就是在被装饰的函数上一行写入 @装饰器名字
这样的作用是方便给我们优化装饰器
因为我们在调用代码时需要写一布
func = outer(func)
语法糖的作用就是帮我们节省了这一步


多层语法糖
def outer1(func1):
    print('我是func1')
    def inner1(*args, **kwargs):
        print('到这里了1')
        res1 = func1(*args, **kwargs)
        return res1
    return inner1

def outer2(func2):
    print('我是func2')
    def inner2(*args, **kwargs):
        print('到这里了2')
        res2 = func2(*args, **kwargs)
        return res2
    return inner2

def outer3(func3):
    print('我是func3')
    def inner3(*args, **kwargs):
        print('到这里了3')
        res3 = func3(*args, **kwargs)
        return res3
    return inner3

@outer1  # funcstart = outer1(inner2) = 返回值 inner1  func1 = inner2
@outer2  # outer2(inner3) = 返回值 inner2   fun2 = inner3
@outer3  # outer3(funcstart)  = 返回值 inner3       func3 = funcstart     
def funcstart():
    print('我是初始的function函数')

funcstart()

语法糖是先从定义的函数 def funcstart() 从它的上方寻找语法糖


多参装饰器
def outer_plus(data):
    def outer(func1):
        def inner(*args,**kwargs):
            username = input('username>>>>:').strip()
            password = input('password>>>>:').strip()
            if data == '1':
                print('使用模式1')
            elif data == '2':
                print('使用模式2')
            elif data == '3':
                print('使用模式3')
            res = func1(*args,**kwargs)
            return res
        return inner
    return outer

@outer_plus('1')
def func1():
    print('我是function1')

func1()
多参装饰器的使用主要是为了让装饰器内部需要的传递的参数传递进去
如果我们想在函数包函数的内部传递参数
我们就需要使用闭包函数传递参数进去



装饰器修复技术
help()
help 可以帮助我们查看内置函数的使用方式以及函数具体内部注释信息
我们知道被装饰器装饰的函数其实已经不是它字节本身了,如果我们想要让help() 内置函数方法显示它本身的内容
我们就需要再装饰器开头加上
from functools import wraps
def outer(func1):
    @warps(func1)
    def inner(*args,**kwargs)
    	res = func1(*args,**kwargs)
        return res
    return inner
@outer
def func1():
    print('你好')
写入此功能就可以让我们的装饰器更加的真实
func1()


递归函数:

递归函数调用的定义是,函数本身被自身调用或间接被调用

我们在写递归函数的时候
有几个注意事项
1.直接或间接调用自身
2.有明确的结束条件,并且每次调用都会更接近结束条件
	递推:一层层往下
    回溯:基于明确的结果一层层往上
 	 """
    get_age(5) = get_age(4) + 2
    get_age(4) = get_age(3) + 2
    get_age(3) = get_age(2) + 2
    get_age(2) = get_age(1) + 2
    get_age(1) = 18
    """
    def get_age(n):
        if n == 1:
            return 18
        return get_age(n-1) + 2
    res = get_age(5)
    print(res)
这个函数递归结束的时候就是当 return 18 时
把之前累计的结果 get_age(n-1) + 2 回溯
这样就得到了最后的结果

l1 = [1,[2,[3,[4,[5,[6,[7,[8,]]]]]]]]

def look(l1):  # 形参传递 l1列表
    for i in l1:  # 遍历 l1 列表
        if type(i) == list:  # 如果 i 的类型是列表 那么 再次调用 look函数 并且实参变为i
            look(i)
        else:
            print(i)

look(l1)  # 调用函数并传入实参 l1


算法:
二分法:
二分法的使用条件比较苛刻,必须是有序的序列
我们使用二分法主要是为了查找数据的
l1 = [1,2,3,4,5,6,7,8,23,554,776,88999,6766666]
# 我们先建立列表l1
# 使用二分法来找其中的一个数据,那么代码就如下:
data = 776  
def num_get(l1,data):  
    if len(l1) == 0:  # 定义一个结束条件,就是当这个序列长度为0的时候就结束
        print('没找到')
        return
    index = len(l1) // 2
    if data < l1[index]:   # 如果需要查找的数值小于 这个序列中间的数值
        left_list = l1[:index]     
        print(left_list)
        return num_get(left_list, data)  # 返回序列从中间索引数据值左侧的序列
    elif data > l1[index]:
        right_list = l1[index+1:]
        print(right_list)
        return num_get(right_list, data)  # 返回序列从中间索引数据值右侧的序列
    else:
        print(f'找到了!数值为{l1[index]}!')

num_get(l1,data)


匿名函数:
lambda a:a+a  也可以添加if 条件

def lam(x):  #  定义一个函数lam 需要传参数
    return x + x  # 返回传来的参数再加上参数
f = lam # 函数名赋值给变量名
print(f(55)) # 打印调用此函数的返回值  110

1. zip()
l1 = [1,2,3,4]
l2 = ['jason','kevin','oscar','jerry']
res = zip(l1,l2)
print(list(res))
# [(1, 'jason'), (2, 'kevin'), (3, 'oscar'), (4, 'jerry')]  两个列表拼接成元组
2.
	filter   # 过滤
    l1 = [11,22,33,44,55,66,77,88,99,100]
    res = filter(lambda x:x >40,l1)  # 两个参数一个是函数 ,另一个为可迭代对象
    print(list(res)  
3.
	sorted
    l2 = ['jason', 'kevin', 'oscar', 'jerry']
res = sorted(l2)
print(res)  # ['jason', 'jerry', 'kevin', 'oscar']
    # 排序,它跟sort的区别是在于sort是列表的独有方法 sorted的参数为可迭代对象
          
4.map()  # 映射
map 函数它的形参会接收两个参数,一个是函数,一个是可迭代对象
首先 map 方法会将函数依次作用再可迭代对象的每一个元素,并得到新的可迭代对象返回
我们举个例子:
res = map(lambda x:x + x,[1,2,3,4,5,6,7])  # 执行顺序就是再列表中的每一个元素都进入匿名函数lambda里面进行处理,最后汇总成一个新的列表作为返回值返回出来
print(res)  # 我们打印接收它的变量名res <map object at 0x0000017F17B56B20>
print(list(res))  # [2, 4, 6, 8, 10, 12, 14]

这就是我们匿名函数搭配使用的一种方法
5. reduce()  #
	# reduce 方法是需要接收两个参数 一个是函数一个是序列,跟map方法相似,但是它是将每次的处理结果做累积处理,最后返回一个处理后的结果
from functools import reduce
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
res = reduce(lambda a, b: a + b, l1)
print(res)  # 495
6.max()/min()
	# max函数和min函数一样 它们都可以接收多个参数,并从中返回数值最大的或最小的
l1 = [1,2,3,4,5,6,7]
print(max(l1))  # 7
print(min(l1))  # 1 

a = 'woshidalao'  # 字符串它判断它的大小就是判断它的字符编码,我们知道A-Z为65-90 a-z为97-122
print(max(a))
print(min(a))


1.
abs()  # 绝对值
print(abs(-20))  # 20
2.
all()  # 所有数据值对应的布尔值为True,结果才是True,如果不是则返回False
print(all([0,1,2,3]))
any()  # 只要有一个数据值对应的布尔值为True,结果就是True
print(any[0,None,'',1])  
3.
oct() hex() bin() int() #  进制转换
4.
bytes() # 转换成字节类型
5.
6.callable()  判断名字是否可以加括号调用
name = 'jason'
def index():
    print('from index')
print(callable(name))  # False
print(callable(index))  # True
7.chr() ord()  基于ASCII码表做数字与字母的转换
print(chr(65))  # A
print(ord('A'))  # 65
8.dir()  返回括号内对象能够调用的名字
print(dir('hello'))
9.divmod()  元组 第一个数据为整除数 第二个是余数
res = divmod(100, 2)
print(res)  # (50, 0)
res = divmod(100, 3)
print(res)


page_num, more = divmod(9999, 20)
print(divmod(99, 10))  # (9, 9)
if more:
    page_num += 1
print('总页码为:', page_num)  # 总页码为: 500
10.enumerate()  枚举
11.eval() exec()  能够识别字符串中的python并执行
s1 = 'print("哈哈哈")'
eval(s1)
exec(s1)
s2 = 'for i in range(100):print(i)'
eval(s2)  # 只能识别简单的python代码 具有逻辑性的都不行
exec(s2)  # 可以识别具有一定逻辑性的python代码
12.hash()  哈希加密
print(hash('jason'))
13.id() input() isinstance()
14.map() max() min()
15.open()
16.pow()  幂指数(次方)
print(pow(2, 2))
print(pow(2, 3))
print(pow(2, 4))
17.range()
18.round() 四舍五入
print(round(98.3))
print(round(98.6))
19.sum()
print(sum([11, 22, 33, 44, 55, 66]))
20.zip()

可迭代对象

1.
含有__iter__()方法的对象都是可迭代对象
2.
含有__iter__(),__next__() 方法的成为迭代器对象
3.
for 循环的底层原理就是
对被for 循环的对象使用 __iter__()方法
然后通过__next__()方法依次取值
当__next__()取不到值的时候会报错,但是for循环会把报错拦截下来