Python 3.x 在python中,哪个对象确切地支持位置参数(或键区参数)的星号(或双星号)?有什么标准吗?

Python 3.x 在python中,哪个对象确切地支持位置参数(或键区参数)的星号(或双星号)?有什么标准吗?,python-3.x,asterisk,Python 3.x,Asterisk,我使用了*或**向Python2中的函数传递参数,这是毫无疑问的,通常与list、set和dictionary一起使用 def func(a, b, c): pass l = ['a', 'b', 'c'] func(*l) d = {'a': 'a', 'b': 'b', 'c': 'c'} func(**d) 但是,在Python3中,出现了新的对象,用或其他东西替换list,例如,dict\u键,dict\u值,范围,映射等等 虽然我已经将我的Python2代码迁移到Pytho

我使用了
*
**
Python2
中的函数传递参数,这是毫无疑问的,通常与
list
set
dictionary
一起使用

def func(a, b, c):
   pass

l = ['a', 'b', 'c']
func(*l)

d = {'a': 'a', 'b': 'b', 'c': 'c'}
func(**d)
但是,在
Python3
中,出现了新的对象,用或其他东西替换
list
,例如,
dict\u键
dict\u值
范围
映射
等等

虽然我已经将我的
Python2
代码迁移到
Python3
,但我需要确定新对象是否能够支持
Python2
中以前的对象所支持的操作,如果不能,我应该使用like类型转换将代码更改为origin类型,例如
list(dict_key)
,或者其他什么

d = {'a': 'a', 'b': 'b'}
print(list(d.keys())[0])    # type-case to use list-index
对于迭代,我可以通过下面的方式进行计算

import collections
isinstance(dict_keys, collections.Iterable)
isinstance(dict_values, collections.Iterable)
isinstance(map, collections.Iterable)
isinstance(range, collections.Iterable)
可以清楚地区分新对象是否可编辑,但与问题的标题相似,那么
位置/关键字参数的
操作如何

到目前为止,所有对象都替换为支持星号操作的
列表
,作为我的测试,但我需要明确的标准,而不是手动测试

我试过几种方法,但没有共同的标准

  • 它们都是
    Iterable
    class?
    • 否,
      Iterable
      生成器不支持
  • 它们都是迭代器类?
    • 否,
      迭代器
      生成器
      不支持
  • 它们都是
    容器
    类?
    • 映射
      类不是
      容器
  • 它们都有一个共同的
    超类
    类?
    • 不,没有公共超类(使用
      Class.mro()测试)
  • 我怎么知道对象是否支持
    位置/关键字参数的
    操作

    单星号格式(*args)用于传递非关键字, 可变长度参数列表,并使用双星号形式 传递关键字可变长度参数列表的步骤

    每个可数“支持”带星号的表达式;就连发电机和地图也有。然而,“一个对象支持
    *
    ”是一个误导性的术语,因为星号的意思是“解包我的interable并将每个元素传递给接口的参数”。因此,
    *
    操作符支持可伸缩性

    这可能就是你的问题所在:与
    *
    一起使用的iterables必须具有与接口具有参数一样多的元素。例如,请参见以下代码段:

    # a function that takes three args
    def fun(a, b, c):
        return a, b, c
    
    # a dict of some arbitrary vals:
    d  = {'x':10, 'y':20, 'z':30}            # 3 elements
    d2 = {'x':10, 'y':20, 'z':30, 't':0}     # 4 elements 
    
    您可以通过多种方式将
    d
    传递给乐趣:

    fun(*d)             # valid
    fun(*d.keys())      # valid
    fun(*d.values())    # valid
    
    但是,您不能将
    d2
    传递给
    fun
    ,因为它有更多的元素
    fun
    接受参数:

    fun(*d2)    # invalid 
    
    def genx():
        for i in range(3):
            yield i
    
    fun(*genx())    # Result: (0, 1, 2)
    
    您还可以使用表达式将贴图传递到
    fun
    。但是请记住,
    map
    的结果必须具有与
    fun
    获取参数一样多的参数

    def sq(x):
        return x**2
    
    sq_vals = map(sq, *d.values())
    
    fun(*sq_vals)    # Result (100, 400, 900)
    
    如果生成器生成的元素数量与函数接受的参数数量相同,则同样适用:

    fun(*d2)    # invalid 
    
    def genx():
        for i in range(3):
            yield i
    
    fun(*genx())    # Result: (0, 1, 2)
    
    为了检查是否可以使用星号表达式将iterable解压到函数的接口中,需要检查iterable的元素数是否与函数的参数数相同

    def sq(x):
        return x**2
    
    sq_vals = map(sq, *d.values())
    
    fun(*sq_vals)    # Result (100, 400, 900)
    
    例如,如果您希望针对不同长度的参数使函数安全,可以尝试以下方式重新定义函数:

    # this version of fun takes min. 3 arguments:
    fun2(a, b, c, *args):
        return a, b, c
    
    fun2(*range(10))    # valid
    fun(*range(10))     # TypeError
    

    我知道它们是什么,我只想知道哪些对象支持该操作,以及对象是否支持的标准是什么。感谢您的回答,我似乎对generator进行了漏检。