• python *和**以及*_的用法


    最近接触了一些python有意思的操作,记录下来

    python *和**的解压缩

    在python函数传参中,单个*例如*args在函数传参中代表传入不确定个数的参数,而**例如**kwargs代表传入长度不确定的a=1

    以上两种用法在一些源码中非常常见,例如在某机器学习库中

    此时我们只需对应的传入相应的参数即可。

    而在实际的运用中,***可以分别作为列表和字典的解压缩符号使用,例如下面两种使用方式。

    >>> print(*[1], *[2], 3)
    1 2 3
    >>> dict(**{'x': 1}, y=2, **{'z': 3})
    {'x': 1, 'y': 2, 'z': 3}
    

    以上几种情况都比较常见,一般百度搜索都能搜到,也是基本常识,下面说一个今天遇到有意思的用法

    *_的省略用法

    在使用python自带函数os.walk()时,为了获取当前文件夹下的文件和文件夹名称,需要只让os.walk()运行一次。我在网络上查询到以下用法

    >>> a, *_ = os.walk(file_dir)
    # 此时a返回的结果为一次查询下的当前文件夹下所有文件和文件夹的名称(一层查询)
    # 如果改成下列两种形式,均会报错
    >>> a, _* = os.walk(file_dir)
    >>> a, _ = os.walk(file_dir)
    

    这种现象引起了我的好奇,下面对此做一个探究。

    先说结论:说到底*_就是对_的重复,代表多个_,类似于快速生成列表的用法:[1]*3

    我们都知道python在接受函数返回值时,若某个返回值今后不需要,可以用_代替,减少变量的使用。则*_就代表有多个返回值不需要,只需要第一个返回值a。

    这里我们可以去查阅os.walk()的源码,里面多次出现了python关键字yield,查阅得知,带有yield函数是一个生成器<generator>,简而言之就是你可以把yield当作一个特殊的return,第一次调用带有yield函数时,函数运行到yield会返回,再次调用此函数时,函数会从上次yield的地方继续运行。这里有一个讲的比较好的博客,就不再赘述。
    ps:range()也是生成器,所以可以用for...in的形式

    这里要讲的是生成器的返回值问题,已知os.walk()是生成器,生成器的一般用法是通过next()函数调用,例如这里一个简单的生成器:

    >>> gen = (x * x for x in range(4)) # 这是一个简单生成器的产生方式
    >>> print(next(gen))	# 调用返回0*0
    0
    >>> print(next(gen))	# 再次调用返回1*1
    1
    >>> print(next(gen))	# 再次调用返回2*2
    4
    

    如果我们不用next(),而是使用赋值语句,则应该根据生成器生成的所有返回值的个数进行赋值。

    # 例如(x * x for x in range(4))一共可以生成四个数0,1,4,9
    >>> a, b = (x * x for x in range(4))	# 两个值接受,报错,返回值不匹配
    >>> a, b, c, d = (x * x for x in range(4)) # 成功。a, b, c, d值分别为0, 1, 4, 9
    

    这里就回到我们一开始的问题了,*_的作用,就是省略之后的若干个_来接收返回值,如下面例子

    >>> a, *_ = (x * x for x in range(4))	# 结果a为0
    >>> *_, a = (x * x for x in range(4))	# 结果a为9
    

    所以,按照上面的说法

    a, *_ = (x * x for x in range(4))等价于a = next((x * x for x in range(4))

    也就是,回到最开始的os.walk()函数
    a, *_ = os.walk(file_dir)等价于a = next(os.walk(file_dir))

    以上。

  • 相关阅读:
    .NET自带控件 ································
    FCKeditor 2.2 + Asp.Net 设置
    . Net 2.0 实现动态切换首页图片···················
    按月统计的问题,即数据中没有该月的数据,该月的数据显示为0
    Active Directory如何用C#进行增加、删除、修改、查询用户与组织单位!
    GridView 的排序 !!
    利用GridView显示主细表并一次编辑明细表所有数据的例子 !!【转自孟子e章】
    [翻译]使用ASP.NET2.0的ReportViewer查看RDLC报表 !!!
    opengl 教程(20) 点光源
    每个程序员都应该了解的内存知识(1)
  • 原文地址:https://www.cnblogs.com/1623-1017/p/11773945.html
Copyright © 2020-2023  润新知