哪个 object 完全支持 python 中位置参数(或键控参数)的星号(或双星号)?任何标准?
Which object exactly support asterisk(or double asterick) for positional argument(or keyward argument) in python? Any criterion?
我已经使用 *
或 **
将参数传递给 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
中,出现了新的objects,将list
替换为或某物,例如,dict_keys
、dict_values
、range
、map
等等。
虽然我已将我的 Python2
代码迁移到 Python3
,但我需要确定新的 object 是否可以支持 [=] 中以前的 object 的操作17=] 这样做如果没有,我应该使用 type-cast 将代码更改为原始类型,例如 list(dict_keys)
或其他内容。
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)
新的object是否可迭代看起来很清楚,但是就像问题的标题一样,position/keyword argument
的asterisk
操作如何?
到目前为止,所有 object 都用支持 asterisk
操作替换了 list
作为我的测试,但我需要明确的标准而不是手动测试。
我尝试了几种方法,但没有共同的标准。
- 都是
Iterable
class?
- 不支持,
Iterable
generator
不支持。
- 都是
Iterator
class?
- 不支持,
Iterator
generator
不支持。
- 都是
Container
class?
- 不是
map
class不是Container
- 他们都有一个共同点
superclass
class?
- 没有普通的superclass(用
Class.mro()
测试过)
我怎么知道 object 是否支持 asterisk
(*
, **
) 操作 position/keyword argument
?
The single asterisk form ( *args ) is used to pass a non-keyworded,
variable- length argument list, and the double asterisk form is used
to pass a keyworded, variable-length argument list
每个可迭代的 "supports" 星号表达式;甚至发电机和地图也可以。但是,"an object supports *
" 是一个误导性术语,因为星号表示 "unpack my interable and pass each element in order to the parameteres of an interface"。因此,*
运算符支持迭代。
这可能就是您的问题所在:您使用 *
的可迭代对象必须具有与接口具有的参数一样多的元素。例如,请参见以下片段:
# 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
您还可以使用 stared 表达式将地图传递给 fun
。但请记住,map
的结果必须有与 fun
接受的参数一样多的参数。
def sq(x):
return x**2
sq_vals = map(sq, *d.values())
fun(*sq_vals) # Result (100, 400, 900)
如果生成器生成的元素与您的函数接受的参数一样多,那么生成器也是如此:
def genx():
for i in range(3):
yield i
fun(*genx()) # Result: (0, 1, 2)
为了检查是否可以使用带星号的表达式将可迭代对象解压到函数的接口中,您需要检查可迭代对象的元素数量是否与函数接受参数的元素数量相同。
如果你想让你的函数对不同长度的参数安全,你可以,例如,尝试按以下方式重新定义你的函数:
# 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
我已经使用 *
或 **
将参数传递给 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
中,出现了新的objects,将list
替换为或某物,例如,dict_keys
、dict_values
、range
、map
等等。
虽然我已将我的 Python2
代码迁移到 Python3
,但我需要确定新的 object 是否可以支持 [=] 中以前的 object 的操作17=] 这样做如果没有,我应该使用 type-cast 将代码更改为原始类型,例如 list(dict_keys)
或其他内容。
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)
新的object是否可迭代看起来很清楚,但是就像问题的标题一样,position/keyword argument
的asterisk
操作如何?
到目前为止,所有 object 都用支持 asterisk
操作替换了 list
作为我的测试,但我需要明确的标准而不是手动测试。
我尝试了几种方法,但没有共同的标准。
- 都是
Iterable
class?- 不支持,
Iterable
generator
不支持。
- 不支持,
- 都是
Iterator
class?- 不支持,
Iterator
generator
不支持。
- 不支持,
- 都是
Container
class?- 不是
map
class不是Container
- 不是
- 他们都有一个共同点
superclass
class?- 没有普通的superclass(用
Class.mro()
测试过)
- 没有普通的superclass(用
我怎么知道 object 是否支持 asterisk
(*
, **
) 操作 position/keyword argument
?
The single asterisk form ( *args ) is used to pass a non-keyworded, variable- length argument list, and the double asterisk form is used to pass a keyworded, variable-length argument list
每个可迭代的 "supports" 星号表达式;甚至发电机和地图也可以。但是,"an object supports *
" 是一个误导性术语,因为星号表示 "unpack my interable and pass each element in order to the parameteres of an interface"。因此,*
运算符支持迭代。
这可能就是您的问题所在:您使用 *
的可迭代对象必须具有与接口具有的参数一样多的元素。例如,请参见以下片段:
# 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
您还可以使用 stared 表达式将地图传递给 fun
。但请记住,map
的结果必须有与 fun
接受的参数一样多的参数。
def sq(x):
return x**2
sq_vals = map(sq, *d.values())
fun(*sq_vals) # Result (100, 400, 900)
如果生成器生成的元素与您的函数接受的参数一样多,那么生成器也是如此:
def genx():
for i in range(3):
yield i
fun(*genx()) # Result: (0, 1, 2)
为了检查是否可以使用带星号的表达式将可迭代对象解压到函数的接口中,您需要检查可迭代对象的元素数量是否与函数接受参数的元素数量相同。
如果你想让你的函数对不同长度的参数安全,你可以,例如,尝试按以下方式重新定义你的函数:
# 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