首页 文章

星级算子是什么意思? [重复]

提问于
浏览
486

这个问题在这里已有答案:

* 运算符在Python中的含义是什么,例如 zip(*x)f(**k) 等代码?

  • 如何在解释器内部处理?

  • 它会影响性能吗?是快还是慢?

  • 什么时候有用,什么时候不用?

  • 它应该用在函数声明还是调用中?

5 回答

  • 39

    单星 * 将序列/集合解压缩为位置参数,因此您可以这样做:

    def sum(a, b):
        return a + b
    
    values = (1, 2)
    
    s = sum(*values)
    

    这将解压缩元组,使其实际执行如下:

    s = sum(1, 2)
    

    双星 ** 做同样的事情,只使用字典并因此命名参数:

    values = { 'a': 1, 'b': 2 }
    s = sum(**values)
    

    你也可以结合:

    def sum(a, b, c, d):
        return a + b + c + d
    
    values1 = (1, 2)
    values2 = { 'c': 10, 'd': 15 }
    s = sum(*values1, **values2)
    

    将执行为:

    s = sum(1, 2, c=10, d=15)
    

    另请参阅Python文档的4.7.4 - Unpacking Argument Lists部分 .


    此外,您可以定义函数以获取 *x**y 参数,这允许函数接受在声明中未明确命名的任意数量的位置和/或命名参数 .

    例:

    def sum(*values):
        s = 0
        for v in values:
            s = s + v
        return s
    
    s = sum(1, 2, 3, 4, 5)
    

    或者 **

    def get_a(**values):
        return values['a']
    
    s = get_a(a=1, b=2)      # returns 1
    

    这可以允许您指定大量可选参数而无需声明它们 .

    再次,你可以结合:

    def sum(*values, **options):
        s = 0
        for i in values:
            s = s + i
        if "neg" in options:
            if options["neg"]:
                s = -s
        return s
    
    s = sum(1, 2, 3, 4, 5)            # returns 15
    s = sum(1, 2, 3, 4, 5, neg=True)  # returns -15
    s = sum(1, 2, 3, 4, 5, neg=False) # returns 15
    
  • 7

    一点是:这些不是运营商 . 运算符在表达式中用于从现有值创建新值(例如,1 2变为3 . *和**这里是函数声明和调用语法的一部分 .

  • 15

    它被称为扩展调用语法 . 来自documentation

    如果语法*表达式出现在函数调用中,则表达式必须求值为序列 . 来自这个序列的元素被视为它们是额外的位置参数;如果存在位置参数x1,...,xN,并且表达式求值为序列y1,...,yM,则这相当于使用MN位置参数x1,...,xN,y1,...的调用 . ,是的 .

    和:

    如果语法**表达式出现在函数调用中,则表达式必须求值为映射,其内容被视为附加关键字参数 . 如果关键字出现在表达式和显式关键字参数中,则会引发TypeError异常 .

  • 753

    我发现这对于你想要“存储”一个函数调用特别有用 .

    例如,假设我对函数'add'进行了一些单元测试:

    def add(a, b): return a + b
    tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
    for test, result in tests.items():
       print 'test: adding', test, '==', result, '---', add(*test) == result
    

    没有其他方法可以调用add,除了手动执行add(test [0],test [1])之类的操作,这很丑陋 . 此外,如果存在可变数量的变量,那么代码可能会变得非常丑陋,您需要使用所有if语句 .

    另一个有用的地方是定义Factory对象(为您创建对象的对象) . 假设您有一些类Factory,它会生成Car对象并返回它们 . 你可以这样做,myFactory.make_car('red','bmw','335ix')创建Car('red','bmw','335ix'),然后返回它 .

    def make_car(*args):
       return Car(*args)
    

    当您想要调用超类的构造函数时,这也很有用 .

  • 15

    在函数调用中,单个星形将列表转换为单独的参数(例如,如果 x=[x1,x2,x3] ,则 zip(*x)zip(x1,x2,x3) 相同)并且双星将字典转换为单独的关键字参数(例如 f(**k)f(x=my_x, y=my_y) 相同,如果 k = {'x':my_x, 'y':my_y} .

    在函数定义中,它是另一种方式:单个星形将任意数量的参数转换为列表,双启动将任意数量的关键字参数转换为字典 . 例如 . def foo(*x) 表示“foo接受任意数量的参数,它们将通过列表x访问(即,如果用户调用 foo(1,2,3)x 将是 [1,2,3] )”, def bar(**k) 表示“bar接受任意数量的关键字参数,它们将可访问通过字典k(即如果用户调用 bar(x=42, y=23)k{'x': 42, 'y': 23} )“ .

相关问题