函数前戏

image

l = [11, 22, 33, 44, 55, 66, 77, 88]
print(len(l))  # 假设len无法使用

def my_len():
    n = 0
    for i in l:
        n += 1
    print(n)
print(my_len())
"""
1.我们现在所写的代码无法做到精简 需要用就必须重复写
    模仿len的内部源码
2.我们现在所写的代码兼容性极差(无法解决)
3.我们现在所写的代码没有返回值(无法解决 使用之后的返回结果)
函数简介
    函数就类似于是工具 提前定义好之后可以反复使用
"""

函数语法结构

image

# 函数语法结构
"""
def 函数名(参数1,参数2):
    '''函数注释'''
    函数体代码
    return 返回值
    
1.def(必须的)
    是定义函数的关键字
2.函数名(必须的)
    是函数的名字 相当于变量名
    函数名的命名规范与风格遵循变量名的
3.参数1,参数2(可选的)
    参数可以没有也可以有多个 
    表示在使用函数之前需要满足的一些条件
4.函数注释(可选的)
    类似于产品说明书
    主要用于介绍函数功能 参数使用 及其他情况
5.函数体代码(必须的)
    函数核心的代码逻辑(重要)
6.return返回值(可选的)
    使用函数之后反馈给使用者的结果 可以有也可以没有
"""

函数的定义与调用

image

###########################################################
1.函数必须先定义后调用(顺序不能乱)
2.函数在定义阶段只检测语法不执行代码
3.函数在调用阶段才会执行函数体代码
	如何调用函数
    	函数名加括号 如果函数在定义阶段有参数则在调用阶段也需要给参数
###########################################################
函数在定义与调用阶段底层原理
1.在内存空间中申请一块空间存储函数体代码
2.将函数体代码所在的空间地址绑定给函数名
3.函数名加括号则会执行函数体代码

函数的分类

image

1.内置函数
	python解释器自带的(提前给你定义好了 你直接使用即可)
2.自定义函数
	程序员自己写的函数
    2.1.无参函数
    2.2.有参函数
    2.3.空函数
 
# 无参函数:在函数定义阶段括号内没有写参数(变量名)
# def my_func():
#     print('这个函数很牛逼')

# 有参函数:在函数定义阶段括号内写了参数(变量名)
# def my_func(a,b):
#     print('这个函数更牛逼')
# my_func(1,2)

# 空函数:函数体代码为空(pass ...)
"""
虽然空函数本身没有含义 但是空函数可以提前规定好编写代码的思路
"""
def run():
    pass
def fight():
    pass
def talk():
    pass

函数参数的两大分类

image

形式参数
	在函数定义阶段,括号内所填写的参数,简称'形参'
    	def func(a,b):
            pass
        'a和b,就是函数func的形参'
实际参数
	在函数调用阶段,括号内传入的参数,简称'实参'
   			func(1,2)
        '数据1和2就是函数func的实参'
 """形参和实参的关系
 	我们可以将形参看成是变量名,实参看成变量值
 		两者在函数调用阶段临时绑定,函数运行结束断开
 	形参的表现形式只有一种就是变量名
 	实参的表现形式有很多种(但是把握核心就是,数据值"""

位置参数

image

位置参数
	按照从左往右的顺序依次填入的参数
位置形参
	在函数定义阶段括号内按照从左往右的顺序依次填入的变量名
位置实参
	在函数调用阶段括号内按照从做往右的顺序依次传入的数据值
    '定义一个可以比较大小的函数(传入两个值,返回较大的)'

关键字实参(可以打破位置顺序)
	在函数调用阶段通过形参名=数据值的形式指名道姓的传值
'''1.位置形参与位置实参在函数调用阶段,按照位置一一对应绑定
2.位置参数在绑定的时候多一个不行少一个也不行'''
"""格式越简单的越靠前,格式越复杂的越靠后"""

默认参数

默认形参
    函数在定义阶段就可以给形参赋值了
    	1.该形参在函数调用阶段如果不给值,则使用默认的	
        2.该形参在函数调用阶段也可以继续给值,则是使用你给的
     # 定义学员注册功能
	def register(name, age, gender='male'):
    	print('%s:%s:%s' % (name, age, gender))
    register('jason', 18)
    register('tony', 28)
    register('kevin', 38)
    register('lili', 18, 'female')
    register('lili', 18, gender='female')   
"""位置形参与默认值值形参在定义的时候,位置形参必须在默认值形参的前面"""
        """格式越简单的越靠前,格式越复杂的越靠后"""

可变长参数

image

1.函数无论传入多少位置参数都可以正常运行
 可变长形参
 def func(x,y,*a):
     print(x,y,a)
"""
*号在形参中的使用
    用于接收多余的位置参数 并组织成元组的形式赋值给*号后面的变量名
"""
2.函数无论传入多少关键字参数都可以正常运行
 def index(x, y, **b):
     print(x, y, b)
"""
**号在形参中的使用
    用于接收多余的关键字参数 并组织成字典的形式赋值给**号后面的变量名
"""
3.定义一个函数无论传入多少位置参数和关键字参数都可以正常运行
def index(*a,**b):
     print(a,b)
"""
墨守成规
    可变长形参 *与**后面的变量名其实是可以随便定义的
    但是python中推荐使用
        *args  
        **kwargs 
def index(*args, **kwargs):
    pass
"""
        

可变长参数实例

image

# def index(a, b, c):
#     print(a,b,c)
# new_list = [11,22,33]
# index(new_list)  # 肯定不行  列表是一个整体 相当于一个实参
# index(new_list[0],new_list[1],new_list[2])  # 可以
'''如果index形参是*args 列表里面有很多元素 如何实现按照位置一一传入'''
# def index1(*args):
#     print(args)
# new_list1 = [11,22,33,44,55,66,77,88,99]
# index1(*new_list1)  # index1(11,22,33,44,55,66,77,88,99)
"""
*号在实参中的使用
    会将列表、元组内的元素打散成位置参数的形式一一传值
"""

# def index2(**kwargs):
#     print(kwargs)
new_dict = {'username':'jason','pwd':123}
# index2(**new_dict)  # index2(username='jason',pwd=123)
# {'username': 'jason', 'pwd': 123}
"""
**号在实参中的使用
    会将字典内的键值对打散成关键字参数传入
"""

函数参数补充(了解)

image

1.命名关键字参数
	def register(name,age,*,sex,height):
        pass

     register('jason',18,'male',183)
    register('lili',18,sex='male',height='1.8m') 正确使用
    """
    sex height在传入实参的时候必须以关键字参数的形式

    ps:该类型的参数几乎不用 也几乎很少能碰到
    """

名称空间

image

 什么是名称空间(namespaces)
	用于存放变量名与变量值绑定关系的地方(类似于民政局)

 名称空间的分类(重要)
	1.内置名称空间
    	python解释器提前给你定义好的 
        	print()
            len()
            ...
    2.全局名称空间
    	在py文件中顶格编写的代码运行之后都会存入全局名称空间
        	name = 'jason'  # name全局
            def func():  # func全局
                pass
            if 1:
                a = 123  # a全局
            for i in range(10):
                print(i)  # i全局
            while True:
                a = 123  # a全局
    3.局部名称空间
    	函数体代码运行之后产生的都是局部名称空间
 存活周期
	1.内置名称空间
    	python解释器启动与关闭而创建和销毁
     2.全局名称空间
    	随着py文件的运行与结束而创建和销毁
     3.局部名称空间
    	随着函数体代码的执行与结束而创建和销毁

名字的查找顺序

image

# 在查找名字的时候 要先确定自己当前在哪
	1.如果你在局部
    	局部 >>> 全局 >>> 内置
    2.如果你在全局
    	全局 >>> 内置
     
 局部名称空间的嵌套 
'''函数在定义阶段名字的查找顺序就已经固定死了(特例)'''
x = 111
def f1():
    x = 222
    def f2():
        x = 333
        def f3():
            x = 444
            def f4():
                x = 555
                print(x)
                # x = 555  特例
            f4()
        f3()
    f2()
 通过调用f1 执行所有的函数
f1()

名称空间的作用域

image

作用域
	名称空间所能够作用的范围
  
内置名称空间
	程序任何阶段任何位置均可使用(全局有效)
全局名称空间
	程序任何阶段任何位置均可使用(全局有效)
局部名称空间	
	一般情况下只在各自的局部名称空间中有效

global与nonlocal关键字使用

image

# x = 111
# def index():
#     # 局部修改全局变量 需要使用关键字声明
#     global x
#     x = 222
# index()
# print(x)


# name_list = ['jason', 'kevin']
# def index():
#     name_list.append('heiheihei')
# index()
# print(name_list)
"""
如果想在局部修改全局数据
    如果数据为不可变类型则需要关键字global声明
    如果数据为可变类型则无需关键字global声明
"""
def index():
    # x = 111
    l1 = [11,22]
    def func():
        # 内部局部修改外部局部
        l1.append(333)
    func()
    print(l1)
index()
"""
如果想要在内部的局部修改外部局部的不可变类型数据
需要关键字nonlocal声明
"""

函数对象(函数名)

image

"""函数名遇到括号就会调用!!!"""
# 用法1:函数名可以当做变量名赋值
# def index():
#     print('from index')
# a = index
# a()  # 本质就是在调用index函数

# 用法2:函数名还可以当做函数的实参
# def index():
#     print('from index')
# def func(a):
#     print(a)
#     a()
#     print('from func')
# func(index)

# 用法3:函数名还可以当做函数返回值
# def index():
#     print('from index')
# def func():
#     print('from func')
#     return index
# res = func()  # 调用func并接受func的返回值
# res()

# 用法4:函数名可以当做容器类型(内部可以存放多个数据)的元素
# def index():
#     print('from index')
# l = [111, 222, 333, index()]
# print(l)

函数的嵌套调用

image

# 嵌套调用:函数内部调用其他函数
# def index():
#     print('from index')
# def func():
#     index()
#     print('from func')
# func()

def my_max(a, b):
    if a > b:
        return a
    return b

def many_max(x,y,z,m):
    res = my_max(x,y)
    res1 = my_max(res,z)
    res2 = my_max(res1,m)
    return res2
ret = many_max(1,2,3,4)
print(ret)7

函数的嵌套定义

image

# 函数体内部定义其他函数
# 将复杂的功能全部隐藏起来 暴露一个简单的接口
def all_func(type):
    def register():
        print('注册功能')
    def login():
        print('登录功能')
    def transfer():
        print('转账功能')
    def shopping():
        print('购物功能')
    # 这里仅仅是延时嵌套定义的现象 暂不考虑优化
    if type == '1':
        register()
    elif type == '2':
        login()
    elif type == '3':
        transfer()
    elif type == '4':
        shopping()
    else:
        print('不知道啥功能')

all_func('3')

闭包函数

image

闭:定义在函数内部的函数
包:内部函数使用了外部函数名称空间中的名字
# 只有符合上述两个特征的函数才可以称之为"闭包函数"

# def outer():
#     x = 222
#     def index():
#         print('from index', x)
#     return index

# 闭包函数其实是给函数传参的第二种方式
# 方式1:函数体代码需要用到数据 直接在括号内定义形参即可
# def index(username):
#     print(username)
# def my_max(a, b):
#     if a > b:
#         return a
#     return b
# 方式2:利用闭包函数
# def outer(x,y):
#     # x = 2
#     # y = 40
#     def my_max():
#         if x > y:
#             return x
#         return y
#     return my_max
# res = outer(2,40)
# print(res())
# print(res())
posted on 2021-11-12 17:20  狼行千里吃肉  阅读(71)  评论(0)    收藏  举报

import time with open('a.txt', 'rb') as f: f.seek(0, 2) while True: line = f.readline() if len(line) == 0: # 没有内容 time.sleep(0.5) else: print(line.decode('utf-8'), end='')