Day 4: 文件的修改,函数

今日内容

"""
文件的修改:了解
函数 ******
"""

复习

"""
1、可变与不可变类型
2、dict方法补充
3、set数据类型:去重,无序,for迭代取值,运算 & | ^ -
4、字符编码:编码演变 ascii -> utf-8
    字符 -> 字节 -> 2 ** 8(256)-> 8个二进制位 => 计算机最新的存储单位 字节
    编码:encode()  解码:decode()
5、文件处理:
    1.open()操作系统打开硬盘空间 
    2.f=open() python将数据加载到内存  
    3.f.read|write 操作文件  
    4.f.close()  自带 flush
    5.del f
    
    三步骤:打开文件 操作文件 关闭文件 =>  with open() as f: 操作文件的逻辑  => 自动close
    
    文件的复制:
    with open('1.txt', 'r', encoding='utf-8') as rf:
        with open('2.txt', 'w', encoding='utf-8') as wf:
            for line in rf:
                wf.write(line)
                wf.flush()
    
    操作模式:
        主:r | w | a
        从:b | t | +
"""

 

文件的修改

# 模式选取:rb+, ab+,不能出现w(清空文件内容)
# with open('test.txt', 'rb+') as f:
#     f.write(b'abc')  # 默认从头 一个一个字节 替换
#     f.write('呵呵'.encode('utf-8'))

# with open('test.txt', 'ab+') as f:
#     f.write(b'abc')  # 默认从尾 一个一个字节 添加
#     f.write('呵呵'.encode('utf-8'))

# with open('test.txt', 'rb+') as f:
#     print(f.read(3).decode('utf-8'))
#
#     # offset偏移字节,whence开始偏移的位置
#     # whence:0从头开始偏移 2从尾开始偏移 1从当前游标所在位置
#     f.seek(6, 1)
#     f.write('心情'.encode('utf-8'))

#     f.seek(-6, 1)
#     f.write('人'.encode('utf-8'))

# a默认不能改变游标位置
# with open('test.txt', 'ab+') as f:
#     f.seek(3, 1)
#     f.write('昨'.encode('utf-8'))
    
# 总结:文件修改的默认一定是 rb+

 

函数

导入

# 什么是函数
"""
解决问题的工具 - 解决问题需要多个步骤 - 一个整体 - 给该整体命名(工具名字) - 通过名字就能表明使用的工具 - 完成对应的事
函数:可以解决 "特定" 功能的代码块,要给代码块进行命名(函数名),通过函数名来调用(使用)函数
"""

# 为什么要有函数
'''
1. 避免代码的冗余
2. 让程序代码结构更加清晰
3. 让代码具有复用性,便于维护,极大降低开发成本
'''

# 在哪用函数
# 所有要复用的代码块都可以封装成函数,进行复用

# 怎么用函数
# 通过 函数名(参数们)  => 参数个数:0~n

# 求两个数中的大值:max 参数个数:2~n, 1个有值的容器
print(max(1, 10, 5, 30))
print(max([1]))

# 没有参数的:
l = list()
print(l)

# input()函数

函数的定义

# def就是声明有缩进函数的 关键字
# fn就是函数名,就是使用函数的 符号
# 使用函数功能:函数名() 来调用函数
# 注:函数的声明不会调用函数(函数体不能执行)
def fn():
    n1 = input('n1:')
    n2 = input('n2:')
    print(n1 + n2)

# 函数名 + ()是调用函数,加()目的是传参,即使不需要参数,也必须加()
fn()

函数的分类

# 空函数:函数体未设定,可以用pass填充
def fn1():
    pass
# fn1()

# 有参函数:内部逻辑(函数体)需要外接的数据
def fn2(a):
    print('外键的参数%s' % a)
# fn2(10)

# 无参函数:内部逻辑(函数体)不需要外接的数据
def fn3():
    num = input('num: ')
    print('内部自己的逻辑产生的数据%s' % num)
# fn3()

# 有返回值函数:通过return将内部数据反馈给外界
def fn4():
    num = 10  # 内部数据需要给外界用
    return num
result = fn4()
print(result)

# 无返回值函数:没有return或return后不跟数据,默认返回None
def fn5():
    num = 100  # 内部数据不需要给外界用
    print(num)
    return
result = fn5()
print(result)

# 总结:
# 1.内外数据交互:外界通过参数将外界数据传给内部,内部通过返回值将内部数据反馈给外界
# 2.函数都有返回值,可以自定义,系统默认返回None

函数的四大组成

# 1.没有return默认返回None:函数内部的值都不需要反馈给外界
def fn1():
    pass

# 先执行拿到结果,在输出(使用)结果
res = fn1()
print(res)

# 直接执行并输出(使用)结果
print(fn1())

# 2.空return默认返回None:用来主动结束函数
def fn2(n1, n2):  # 只做两个数字的加法
    if not (isinstance(n1, int) and isinstance(n1, int)):
        print('数据不合法')
        return
    print(n1 + n2)

fn2('10', 20)
fn2(10, 20)

# 3.一个值的return:将内部一个值反馈给外界,外界可以接收值,重复使用
def fn3(n1, n2):
    sum = n1 + n2
    return sum

result = fn3(100, 200)  # result: 300
print(result * 10)

# 4.多个值的return:将内部多个值反馈给外界,外界可以接收值,重复使用
def fn4(n1, n2):
    sum = n1 + n2
    low = n1 - n2
    jump = n1 * n2
    fall = n1 / n2
    return sum, low, jump, fall
    # return [sum, low], [jump, fall]  # ([88, 44], [1452, 3.0])
    # 注:返回多个值本质是将多个值加压成元组返回

# print(fn4(66, 22))
s, l, j, f = fn4(66, 22)
print(f)

函数的返回值

# 1.没有return默认返回None:函数内部的值都不需要反馈给外界
def fn1():
    pass

# 先执行拿到结果,在输出(使用)结果
res = fn1()
print(res)

# 直接执行并输出(使用)结果
print(fn1())

# 2.空return默认返回None:用来主动结束函数
def fn2(n1, n2):  # 只做两个数字的加法
    if not (isinstance(n1, int) and isinstance(n2, int)):
        print('数据不合法')
        return
    print(n1 + n2)

fn2('10', 20)
fn2(10, 20)

# 3.一个值的return:将内部一个值反馈给外界,外界可以接收值,重复使用
def fn3(n1, n2):
    sum = n1 + n2
    return sum

result = fn3(100, 200)  # result: 300
print(result * 10)

# 4.多个值的return:将内部多个值反馈给外界,外界可以接收值,重复使用
def fn4(n1, n2):
    sum = n1 + n2
    low = n1 - n2
    jump = n1 * n2
    fall = n1 / n2
    return sum, low, jump, fall
    # return [sum, low], [jump, fall]  # ([88, 44], [1452, 3.0])
    # 注:返回多个值本质是将多个值加压成元组返回

# print(fn4(66, 22))

s, l, j, f = fn4(66, 22)
print(f)

形参与实参

# 函数必须先定义后调用 - python是解释型语言
# fn()

# 外界数据要传递给内部 - 参数
def fn(num):  # 外界传递 100 就是100,传递 'abc' 就是 'abc',形式上的
    print(num)
    print(num)
    print(num)
    print(num)

# number = input("num: ")
# fn()

num = input("num: ")  # 外界的 num 才是数据的产生点,实际上的
fn(num)

# 形参:形参没有实际的值,值来源于实参,函数定义时 () 中出现的变量
# 实参:实参具有实际的值,值提供给形参,函数调用时 () 中出现的变量或值

实参分类

# 实参的分类:
# 1、位置实参(positional)
# 2、关键字实参(keyword-only)

def fn(a, b):
    print(a, b)

# 位置实参传参
fn(10, 20)  # 10 -> a  |  20 -> b
n1 = 100
n2 = 200
fn(n2, n1)  # n2 -> a  |  n1 -> b

# 关键字实参传值
fn(b=n1, a=n2)  # n2 -> a  |  n1 -> b

def func(a, b, c):
    print(a, b, c)

# func(100, b=200, 300)  # 100ok 200ok 300nook
# func(100, a=200, c=300)  # 按位置拿到值的形参就不能再被关键字进行传参
func(100, c=200, b=300)  # 正确的
func(100, b=200, c=300)  # 提倡

# 总结:
# 1、函数传递参数的实参形参个数要统一
# 2、位置实参传参:按位(安装顺序)传参
# 3、关键字实参传值:根据形参名,指名道姓传递值,传递顺序可以任意
# 4、如果位置与关键字实参同时存在,必须位置在前,关键字在后

形参分类

# 1、无值位置形参
# 2、有值位置形参(默认参数)
# 3、可变长位置形参
# 4、无值关键字形参
# 5、有值关键字形参
# 6、可变长关键字形参

# 位置与关键字的分水岭: * 前的是位置,后是关键字
def fn1(a, b, *, x, y):
    print(a, b, x, y)
fn1(a=10, b=20, x=100, y=200)

# 总结:
# 1、关键字形参必须有关键字实参传递
# 2、位置形参可以由位置或关键字实参传值

# i、位置实参只能给位置形参传值
# ii、关键字实参能给位置及关键字形参传值

# 无值的
def fn2(a, b, *, x, y):
    print(a, b, x, y)
fn2(a=10, b=20, x=100, y=200)

# 总结:
# 1、*前的a,b是无值的位置形参,必须要被传值,可以由位置或关键字实参传值
# 2、*后的x,y是无值的关键字形参,必须要被传值,只能由关键字实参传值

# 有值的
def fn3(a=10, *, x=100):
    print(a, x)
fn3()
fn3(x=888)
fn3(a=666)
fn3(x=888, a=666)
fn3(333, x=777)

# 总结:
# 1、有值的形参均可以不用被传值,没有被传值时采用默认值
# 2、可以给部分有默认值形参传值,被传值的形参采用所接受到的值,没有被传值的有默认值形参采用默认值


# 可变长
# *还是分水岭
def fn4(a, *args, x):
    pass
fn4(10, x=100)

# *和**是 指针符号,args、kwargs才是变量名
def fn5(*args, **kwargs):
    print(args)
    print(kwargs)
fn5()
fn5(1, 2, 3, x=10, y=20, z=30)

# 总结:
# 1、args用元组来接受值,kwargs用字典来接受值
# 2、args接收所有位置参数,kwargs接收所有关键字参数

形参运用

# 六种形参共存:必须按照以下顺序定义

# 无值位置、有值位置、可变长位置、有无值关键字、可变长关键字

def fn(a, b=10, *c, d, e=100, f, **g):
    print(a)
    print(b)
    print(c)
    print(d)
    print(e)
    print(f)
    print(g)

# fn(10, 20, 30, 40, d=50, f=70, x=100, y=200, z=300, e=60)
fn(a=10, b=20, c=30, d=50, f=70, x=100, y=200, z=300, e=60)

# 总结:
# 1、可变长位置形参:是接收 无值与有值位置形参 未接收完的所有 位置实参
# 2、可变长位置形参要接收到值,前方所有的位置形参必须被传值,所以前方出现有值位置形参没有多大意义
# 3、可变长关键字形参:是接收 前方所有 未接收完的 关键字实参

# 常见组合
def fn1(a, b=20):
    pass

def fn2(a, *, host, port):
    pass

def fn3(a, *, host='localhost', post):
    pass

def fn4(*, host='localhost', post):
    pass

def fn5(a, *args):
    pass

def fn6(*args, **kwargs):  # *****
    pass

def fn7(a, *args, x, **kwargs):
    pass

# 打散传值
def func(*args, **kwargs):
    print(args)
    print(kwargs)

# func(1, 2, 3, x=10, y=20, z=30)

ls = [1, 2, 3]
dic = {'x': 10, 'y': 20, 'z': 30}

# func(ls, dic)  # (ls, dic) {}

# *ls会把ls打散(解压) => 1, 2, 3
# **dic会把dic打散(解压) => x=10, y=20, z=30
func(*ls, **dic) # == func(1, 2, 3, x=10, y=20, z=30)

func(*[4, 5, 6], **{'name': 'owen', 'sex': 'male'})

函数的嵌套调用

# 求两个数值的大值
def max_two(n1, n2):
    # 从n1,n2中判断大者返回
    if n1 > n2:
        return n1
    return n2
print(max_two(100, 88))

# 求三个数值的大值
def max_three(n1, n2, n3):
    if n2 < n1 > n3:
        return n1
    if n1 < n2 > n3:
        return n2
    if n1 < n3 > n2:
        return n3
print(max_three(10, 30, 20))

# 函数的嵌套调用:在被调用的函数内部,调用其他函数
def max_three(n1, n2, n3):
    res = max_two(n1, n2)
    return max_two(res, n3)
print(max_three(10, 30, 20))

# 求四个数值的大值
def max_four(n1, n2, n3, n4):
    res = max_three(n1, n2, n3)
    return max_two(res, n4)
print(max_four(10, 30, 20, 40))

函数对象(函数名)

# 对象:对象就是存放地址的变量

# 函数名是存放函数地址的变量:函数对象
def fn():
    print('fn run')
print(fn)

a = 10  # a是 整型对象
ls = [1, 2]  # ls是 列表对象

# a和ls是对象,fn也是对象,使用本质没有多大区别
# 但是a与ls与fn之间又有本质区别:使用方式不一样
# a就是用来做算术运算的
# ls是用来存储多个值的 ls.append()  ls[0]  ls.pop(index)
# fn是用来加()调用拿到功能执行结果的  fn(参数列表)

# 函数对象的应用场景
"""
# 1 可以直接被引用
# 2 可以当作函数参数传递
# 3 可以作为函数的返回值
# 4 可以作为容器类型的元素
"""

函数对象运用

def fn():
    print('fn run')
fn()

a = 10

r1 = a
r1 += 1
print(r1)

# 1、可以直接被引用:将函数对象直接赋值给另一个变量(对象),该变量就可以加括号调用函数
r2 = fn
r2()

# 注:这个不是函数的引用,这是调用fn函数,拿到返回值给r3
r3 = fn()

############################这里不是很明白########################
# 2、可以作为函数的参数
def new_fn(arg):
    print(arg)

    # 如果能调用(是函数),就可以加()调用
    if callable(arg):
        arg()

new_fn(fn)
#################################################################

# 3、可以作为函数的返回值
def func():
    return fn

res = func()
res()

func()()

# 4、作为容器对象的成员
ls = [10, 'abc', fn()]
ls[2]()

dic = {
    'method': fn
}

dic['method']()

# 总结:
# 1、函数名可以被任意引用
# 2、函数名一旦加()就是执行函数拿到函数的结果

函数对象综合案例

# 需求:
# 从键盘录入运算指令,完成数据的运算 五则运算
# 指令正确:完成对应的运算,指令错误:重新输入指令,指令为Q或q退出系统

def add(n1, n2):
    print("选择了加法运算")
    return n1 + n2

def low(n1, n2):
    print("选择了减法运算")
    return n1 - n2

def jump(n1, n2):
    print("选择了乘法运算")
    return n1 * n2

# 指令与函数的对应关系 映射
method_map = {
    'add': add,
    'low': low,
    'jump': jump
}

# 运算,给我运算方法与运算数据,我来帮你完成运算
def computed(fn, num1, num2):
    return fn(num1, num2)

# 获取运算方法
def get_method(cmd):
    return method_map[cmd]

is_over = False
while not is_over:
    n1 = int(input('num1: '))
    n2 = int(input('num2: '))
    result = None

    while True:  # 指令可能不是一次性成功
        cmd = input('cmd:')  # add => 调用add函数 | low => 调用low函数

        if cmd.lower() == 'q':  # q的指令是要结束系统(双层循环)
            print('退出系统')
            is_over = True  # 内外循环可以通过变量建立起关联
            break

        if cmd not in method_map:
            print('指令错误')
            continue

        # result = method_map[cmd](n1, n2)  # 该句没有执行,result默认值为0

        # fn = method_map[cmd]

        fn = get_method(cmd)  # 有语义,根据指令得到对应的功能(函数)
        result = computed(fn, n1, n2)  # 有语义,该步是完成运算的,采用fn运算函数,提供n1,n2运算参数
        break  # 有执行结果,指令循环就可以结束了,代表本次运算有结果了

    # 0、空字符串、None、()、[]、{}都代表假,其他代表真
    if result is not None:
        print("运算结果:%s" % result)

名称空间与作用域

# 名称空间:存放名字与内存空间地址对应关系的容器

"""
# cpython解释器启动 => 加载名称空间

a = 10
a = 100
print(a)

def fn():
    x = 30
    print(x)
    print(locals())
    print(12345)

def fn1():
    x = 300
    print(x)

print(globals())

globals()['fn']()

fn()
fn1()

"""

# 三种名称空间
# Built-in:内置名称空间;系统级,一个;随解释器执行而产生,解释器停止而销毁
# Global:全局名称空间;文件级,多个;随所属文件加载而产生,文件运行完毕而销毁
# Local:局部名称空间;函数级,多个;随所属函数执行而产生,函数执行完毕而销毁

# 加载顺序: Built-in > Global > Local
print(max(1, 2))
# max = 100
# print(max)
# del max
#
# print(max(20, 30))

# 作用域:名字起作用的范围

# 内置加载了一个max:内置作用域
# max = 8  # 全局作用域
def fn():
    # max = 88  # 嵌套作用域(局部)
    def inner():
        # max = 888  # 局部作用域
        print(max)
    inner()  # 该函数变量在fn函数内部声明,所以在内部使用,同fn中定义的max,在fn中使用
fn()

# 变量的访问顺序(名字查找顺序)
# Local > Enclosing > Global > Built-in
"""
# Built-in:内置作用域 - 任何位置都起作用,但是最后被查找
# Global:全局作用域 - 在本文件中任何位置都起作用
# Enclosing:嵌套作用域 - 在自身函数与它嵌套的函数内部起作用
# Local:局部作用域 - 在自身函数内部起作用 - 最先被查找
"""

# 总结:
# 1、知道变量名字访问到变量值的完整路径:名称空间 => 栈区 => 堆区
# 2、明确名字的作用范围、查找顺序、生命周期

两个关键字

"""
# num = 10

# global: 在局部想修改全局变量(局部与全局变量统一) 或 在局部定义全局变量
def fn():
    global num
    num = 100
    print(num)  # 100

fn()

print(num)  # 10 => global num => 100
"""

# nonlocal: 在被嵌套的局部想修改嵌套它的局部变量(嵌套作用域的变量统一)
"""
def outer():
    num = 10

    def inner():
        nonlocal num
        num = 100
        print("inner:", num)  # 100
    inner()

    print("outer:", num)  # 10 => nonlocal num  => 100

outer()
"""

num = 1
def outer():
    global num
    num = 10
    def inner():
        global num
        num = 100
    inner()

    print(num)  # 100

outer()
print(num)  # 100

 

 

转载于:https://www.cnblogs.com/Black-Natasha/p/11475424.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值