语言基础篇11——函数、函数参数类型、装饰器、生成器

2023-11-05

函数

基本结构

def func_name(value):
    print(f"Hello {value}")
    return 0

func_name("World")

函数参数

参数默认值和五种参数类型

https://docs.python.org/3/glossary.html#term-parameter

参数默认值

带默认值的参数必须在参数列表右边

def func_name(a, b=0):
    return a + b

print(func_name(1))

位置或关键字参数,positional-or-keyword argument

默认参数类型,传参的时候可以以位置或者关键字形式传递,但位置参数一定在左,关键字参数一定在右

# a、b均为位置或关键字参数,a以位置参数的形式传递,b以关键字参数的形式传递
def func_name(a, b):
    return a + b

print(func_name(1, b=2))

仅位置参数,positional-only argument

使用/用于限定其之前的参数为仅位置参数类型

# a、b均为位置参数,c为位置或关键字参数但以位置参数形式传入
def func_name(a, b, /, c):
    return a + b + c

print(func_name(1, 2, 3))

仅关键字参数,keyword-only argument

使用*用于限定其之后的参数为仅关键字参数类型

# a、b为位置或关键字参数但以位置参数传入,c为仅关键字参数
def func_name(a, b, *, c):
    return a + b + c

print(func_name(1, 2, c=3))

可变位置参数,var-positional argument

a、b为仅位置参数,args为可变位置参数,*args将多余的位置参数装包为元组args,args命名任意,习惯上以args作为可变位置参数名

def func_name(a, b, *args):
    print(a, b, args, type(args))  # 1 2 (3, 4, 5) <class 'tuple'>

func_name(1, 2, 3, 4, 5)

可变关键字参数,var-keyword argument

a、b均为位置或关键字参数,但a、b传入形式不同,**kwargs将多余的关键字参数装包为字典kwargs,kwargs命名任意,习惯上以kwargs作为可变关键字参数名

def func_name(a, b, **kwargs):
    print(a, b, kwargs, type(kwargs))  # 1 2 {'c': 3, 'd': 4, 'f': 5} <class 'dict'>

func_name(1, b=2, c=3, d=4, f=5)

注:

  1. 整体上,参数传入时必然以位置参数或关键字参数的形式传入,通常联合使用*args**kwargs接受任意参数

    def func_name(*args, **kwargs):
        print(args, kwargs)
    
    func_name(1, b=2, c=3, d=4, f=5)
    
  2. a、b为位置参数,c、d为位置或关键字参数,e、f为关键字参数

    def func_name(a, b, /, c, d, *, e, f):
        print(a, b, c, d, e, f)
    
    func_name(1, 2, 3, d=4, e=5, f=6)
    

函数返回值

Python基于元组的自动装包和拆包在语法上实现了多个返回值形式,实际仍为一个返回值

def func_name(a, b):
    return a, b


a, b = func_name(1, 1)
print(a, b)  # 1 1

r = func_name(1, 1)
print(r, type(r))  # (1, 1) <class 'tuple'>

Python函数返回值默认为None,不存在没有返回值的情况

def func_name1():
    return
print(func_name1())  # None


def func_name2():
    pass
print(func_name2())  # None

匿名函数,lambda表达式

def pow2(n):
    return n ** 2
print(pow2(10))

calc = lambda n: n ** 2
print(calc(10))

add = lambda x, y: x + y

l = [-2, 4, -9, 4, 7, 8]
print(max(l, key=lambda n: n * n))

闭包函数

  • 闭包函数必须有内嵌函数
  • 内嵌函数需要引用该嵌套函数上一级中的变量
  • 闭包函数必须返回内嵌函数
# 闭包函数通过将函数名作为返回值使得不释放局部变量引用而保留局部变量
# 具有环境变量n的函数power
def nth_power(a):
    n = a or 1

    def power(base):
        return base ** n

    return power


_3power = nth_power(3)
print(_3power(2))  # 8

_closure_

def generate_func(start, end):
    def print_string(name):
        print(start, name, end)

    return print_string


hello = generate_func("Hello", "!")
hello('World')  # Hello World !
print(hello.__name__)  # print_string
print(
    hello.__closure__)  # (<cell at 0x00000215DB0E7E50: str object at 0x00007FF9311F9900>, <cell at 0x00000215DB0E7EE0: str object at 0x00000215DAD18AB0>)
print(hello.__closure__[0].cell_contents)  # !
print(hello.__closure__[1].cell_contents)  # Hello
print(id(hello))  # 2292892980448

bye = generate_func("Bye", ".")
bye('World')  # Bye World .
print(bye.__name__)  # print_string
print(
    bye.__closure__)  # (<cell at 0x00000215DB0E7DF0: str object at 0x00007FF9311F9BD8>, <cell at 0x00000215DB0E7E20: str object at 0x00000215DACBB4F0>)
print(bye.__closure__[0].cell_contents)  # .
print(bye.__closure__[1].cell_contents)  # Bye
print(id(bye))  # 2292892978368

global

a = 1


def f1():
    a = 2

    def f2():
        global a
        a = 3
        print(a)  # 全局变量a=3

    f2()
    print(a)  # 局部变量a=2


f1()
print(a)  # 全局变量a=3

nonlocal

a = 1


def f1():
    a = 2

    def f2():
        nonlocal a
        a = 3
        print(a)  # 全局变量a=3

    f2()
    print(a)  # 局部变量a=3


f1()
print(a)  # 全局变量a=1

装饰器

import time


def outer(func):
    def inner(*args, **kwargs):
        t1 = time.perf_counter()
        res = func(*args, **kwargs)
        print(time.perf_counter() - t1)
        return res

    return inner


def add(a, b):
    time.sleep(1)
    return a + b


add_plus = outer(add)
print(add_plus(1, 2))
# 1.0007887999818195
# 3


@outer
def sub(a, b):
    time.sleep(1)
    return a - b


print(sub(1, 2))
# 1.000871800002642
# -1
# 装饰器标准模板
# 装饰器函数\装饰器类,以函数作为装饰器\以类作为装饰器
def wrapper():
    def outer(func):
        def inner(*args, **kwargs):
            res = func(*args, **kwargs)
            return res

        return inner

    return outer


@wrapper()
def func_wrapped():
    pass


func_wrapped()

无参装饰器

# 无参装饰器
def debug(func):
    def wrapper(*args):
        print("[DEBUG]: function {}".format(func.__name__))
        return func(*args)

    return wrapper


@debug
def add(a, b):
    return a + b


add(1, 2)
# [DEBUG]: function add

有参装饰器

# 有参装饰器
def logging(level):
    def outer_wrapper(func):
        def inner_wrapper(*args, **kwargs):  # 参数在此
            print("[{}]: function {}".format(level, func.__name__))
            return func(*args, **kwargs)

        return inner_wrapper

    return outer_wrapper


# @logging(level="DEBUG")相当于先调用函数outer_wrapper=logging(level="DEBUG")得到@outer_wrapper
# @outer_wrapper相当于inner_wrapper=outer_wrapper(func)
# 最终执行inner_wrapper
@logging(level="DEBUG")
def add(a, b, *args):
    res = a + b
    for i in args:
        res += i
    return res


print(add(1, 2, 3, 4))
# [DEBUG]: function add
# 10

多重装饰器

自上而下,自下而上

def wrapper1(func):
    def inner1():
        print("inner1 before")
        func()
        print("inner1 after")

    return inner1


def wrapper2(func):
    def inner2():
        print("inner2 before")
        func()
        print("inner2 after")

    return inner2


def wrapper3(func):
    def inner3():
        print("inner3 before")
        func()
        print("inner3 after")

    return inner3


@wrapper1
@wrapper2
@wrapper3
def do():
    print("fun")


do()
# inner1 before
# inner2 before
# inner3 before
# fun
# inner3 after
# inner2 after
# inner1 after

生成器,generator

  • 生成器函数 生成器表达式

  • 含有yield关键字的函数为生成器函数,yield不可与return共用

def generator():
    a = '123456'
    for i in a:  # 一般写法
        yield i
    yield from a  # 简写


g = generator()
for i in g:
    print(i)
# 1
# 2
# 3
# 4
# 5
# 6
# 1
# 2
# 3
# 4
# 5
# 6

不给生成器传参

def generator():
    print("generator1")
    yield 'a'
    print("generator2")
    yield 'b'


result = generator()
print(result)
print(result.__next__())  # a
print(result.__next__())  # b
# print(result.__next__())  # StopIteration

# 生成器只能遍历一遍元素,获取完毕之后必须重新new
# 而对于列表来说,可以使用for i in l: print(i)遍历多次,但是生成器会报异常

给生成器传参

def generator():
    print(1)
    content = yield 'a'
    print(2, content)
    content = yield 'b'
    print(3, content)
    yield


g = generator()
print(g.__next__())
print(g.send("content1"))  # 需要给上一个yield位置传参,第一个需要用__next__,同理最后一个yield无法获取到值,不过可以yield空
print(g.send("content2"))
# 1
# a
# 2 content1
# b
# 3 content2
# None
def tractor():
    """
    拖拉机
    @return:
    """
    distance = 0
    second = 0
    avg_speed = 0
    while True:
        d, t = yield avg_speed
        distance += d
        second += t
        avg_speed = distance / second


avg = tractor()
print(avg.__next__())  # 0 摇车,人力启动柴油机
print(avg.send((10, 1)))  # 10.0
print(avg.send((12, 0.5)))  # 14.666666666666666
print(avg.send((10, 1)))  # 12.8

生成器嵌套

def generator():
    for i in range(4):
        yield i


g = generator()
g1 = (i for i in g)
print(g1, type(g1))
g2 = (i for i in g1)
print(g2, type(g2))
# print(list(g)) # 若此处注释打开你猜会如何
print(list(g1))  # [0, 1, 2, 3]
print(list(g2))  # [] 因为执行的时候g1只是一个能产生[0, 1, 2, 3]的迭代器,并不同于值本身
def add(a, b):
    return a + b


def nums():
    for i in range(4):
        yield i


g = nums()
for a in [1, 10]:
    g = (add(a, b) for b in g)  # 生成器表达式,不实际取元素的时候是不会列出元素的
print(list(g))  # [20, 21, 22, 23]

print(list((add(1, b) for b in nums())))  # [1, 2, 3, 4]
print(list((add(10, b) for b in nums())))  # [10, 11, 12, 13]
print(list((add(10, b) for b in (add(1, b) for b in nums()))))  # [11, 12, 13, 14]
print(list((add(10, b) for b in (add(10, b) for b in nums()))))  # [20, 21, 22, 23] 等价,a的值在list时才
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

语言基础篇11——函数、函数参数类型、装饰器、生成器 的相关文章

随机推荐

  • android studio修改module名称

    新建一个android studio项目 默认Module名称是app 右键app选择Rename 或者Shift F6也可以 重命名module名称 重命名为abc之后中 如图上面箭头所指的app会出错 点击Edit Configurat
  • 多益网络笔试题 随机地从大小为n的数组中选取m个整数。要求每个元素被选中的概率相等

    题目 随机地从大小为n的数组中选取m个整数 要求每个元素被选中的概率相等 时间复杂度是O m 参考链接 https my oschina net u 2822116 blog 795323 分析 这道题目和随机洗牌算法类似 只需要随机选取1
  • Java开发环境搭建03:idea中使用Maven

    一 Maven介绍 Maven项目对象模型 POM 可以通过一小段描述信息来管理项目的构建 报告和文档的项目管理工具软件 Maven是Apache 的开源项目 Maven使用Java开发的 运行需要Java环境的支持 Maven的作用有三点
  • leveldb之Compaction操作下之具体实现

    leveldb之Compaction操作下之具体实现 2015 05 17 19 40 438人阅读 评论 0 收藏 举报 分类 leveldb 13 版权声明 本文为博主原创文章 未经博主允许不得转载 目录 由上文可知 合并主要分为三种
  • Vue 3结合element plus(问题总结)之 table组件实现多选和清除选中

    问题描述和原因 一直出现toggleRowSelection和clearSelection不是方法 问题解决 后来发现getCurrentInstance支持访问内部组件实例 getCurrentInstance 只能在 setup 或生命
  • 人工神经网络matlab代码,matlab神经网络30例代码

    如何在matlab中建立多层bp神经网络 当你用newff的时候 里面有一个参数可以控制层数 比如说 P 0 1 2 3 4 5 6 7 8 9 10 T 0 1 2 3 4 3 2 1 2 3 4 net newff P T 5 这样表示
  • 通讯协议027——全网独有的OPC AE知识四之接口(十一)

    本文继续介绍OPC AE规范的IOPCEventSubscriptionMgt2接口的相关知识 更多通信资源请登录网信智汇 OPC AE规范描述了OPC事件服务器应该实现的对象和接口 实现在多个OPC客户端间共享事件和警报条件 可选的IOP
  • IT项目管理个人作业8

    练习题1 质量标准 要求 学历 全日制统招研究生及以上学历 专业 计算机科学 软件工程 工程管理或相关专业者优先 经验 三年 三年以上相关工作经验 年龄 30 45 论文发表 在顶级期刊上发表过三篇以上论文 技术需求 熟悉项目管理相关知识
  • 13、Efficient Geometry-aware 3D Generative Adversarial Networks

    简介 仅使用单视图 2D 照片集合无监督生成高质量的多视图一致图像和 3D 形状一直是一项长期存在的挑战 现有的3D GAN要么是计算密集型的 要么是进行不3D一致的近似 前者限制了生成图像的质量和分辨率 后者会对多视图一致性和形状质量产生
  • input框限制只能输入两位小数

    1 给数字输入框输入定义触发事件
  • 解决Mysql使用本地IP无法连接

    Mysql使用本地IP无法连接 使用localhost或127 0 0 1正常连接 问题原因 Mysql默认不会开启本地IP连接的权限 需要手动开启 解决方法 1 进入cmd 2 输入mysql u root p 密码 进入mysql 3
  • JS-----------Ajax

    目录 传统网站存在的问题 ajax概述 阿贾克斯 异步和同步的区别 Ajax运行原理 ajax的实现步骤 请求报文 Ajax的其他方法和Ajax配置信息 请求传参的几种格式 get post区别 同源政策 扩展 思维导图 传统网站存在的问题
  • Python列表操作指南:索引、切片、遍历与综合应用

    文章目录 列表 简介 创建列表 索引和切片 列表的长度 列表的拼接和重复 检查元素是否存在 列表的方法 index 方法 count 方法 列表的修改和删除 修改元素 删除元素 列表的排序和反转 添加元素 列表的拷贝 列表的遍历 列表的切片
  • Java基础练习题01基本控制流程

    1 输入一个字符 判断它是不是字母 是不是数字 是不是空格字符 public static void main String args System out print 请输入一个字符 Scanner input new Scanner S
  • 西门子S7-1200与V20变频器的USS通信

    USS通信基本原理 USS 协议 Universal Serial Interface Protocol 即通用串行接口协议 是西门子专为驱动装置开发的通用通信协议 它是一种基于串行总线进行数据通信的协议 USS 通信总是由主站发起 USS
  • NFT 项目的十大评估维度

    全文共 5383 字 阅读约需 7 分钟 目录 1 项目的艺术性 2 社区 3 团队 4 路线图 5 使用场景 6 故事性 7 成本度量 8 稀有度 9 流动性 10 趋势 如何判断某一NFT项目是否可冲 这是各大 NFT 社群里都很常见的
  • 软件测试——程序控制流图,McCabe环形复杂度

    软件测试 程序控制流图 McCabe环形复杂度 根据下边的程序流程图 完成 1 画出相应的程序控制流图 根据上述的程序流程图画出程序控制流图 由于一个条件判断语句中有复合条件表达式 故需拆开表示 2 给出控制流图的邻接矩阵 1 2 3 4
  • js中的dataset的使用

    总结 1 document querySelector 的使用 2 data 自定义属性的使用 3 dataset 获取自定义属性值的使用 转载于 https blog 51cto com 11871779 2333045
  • 社区划分的标准--模块度

    在社区发现算法中 几乎不可能先确定社区的数目 于是 必须有一种度量的方法 可以在计算的过程中衡量每一个结果是不是相对最佳的结果 模块度 Modularity 用来衡量一个社区的划分是不是相对比较好的结果 一个相对好的结果在社区内部的节点相似
  • 语言基础篇11——函数、函数参数类型、装饰器、生成器

    函数 基本结构 def func name value print f Hello value return 0 func name World 函数参数 参数默认值和五种参数类型 https docs python org 3 gloss