如何通过Python args和kwargs?

时间:2014-05-19 17:45:45

标签: python

虽然我对Python的* args和** kwargs有一般性的了解(我认为),但我很难理解如何将它们从一个函数传递到另一个函数。这是我的模特:

from pdb import set_trace as debug
from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=30)

    def __unicode__(self):
        return u'%s' % self.name

    def save_name_for(self, *args, **kwargs):
        self.name = 'Alex'
        return self

    def save_name(self, *args, **kwargs):
        debug()
        self.save_name_for(self, args, kwargs)
        self.save()

我将名称拆分为上面的两个函数。这样,我可以通过对save_name_for方法进行单元测试来对我通常将所有逻辑进行单元测试。

当我在解释器中运行它并在save_name方法中停止时,正如我所料,我看到了这一点:

(Pdb) args
self =
args = (1, 2)
kwargs = {'last': 'Doe', 'first': 'John'}

如果我然后进入save_name_for方法,我会看到:

(Pdb) args
self =
args = (<Person: >, (1, 2), {'last': 'Doe', 'first': 'John'})
kwargs = 

有没有办法将save_name方法收到的kwargs直接传递给save_name_for方法,以便它们出现在后者的kwargs中?我想在save_name_for方法的名称空间中看到类似的内容:

(Pdb) args
self =
args = (1, 2)
kwargs = {'last': 'Doe', 'first': 'John'}   # <= I want this

我意识到我可以在save_name中解析它们,然后将它们显式传递给save_name_for,但这似乎相当不优雅。我也认为我可能会这样做,因为args是一个元组......

kwargs = args[2]

...但它似乎不起作用。 args [2]就是一切(我不明白这一点)。是否有Pythonic方法来做到这一点?

2 个答案:

答案 0 :(得分:8)

使用语法镜像参数语法传递它们:

self.save_name_for(*args, **kwargs)

请注意,您无需传入self; save_name_for已经绑定。

答案 1 :(得分:7)

***运算符用于两种不同的情况。

  1. 用作功能定义的一部分时,

    def save_name_for(self, *args, **kwargs):
    

    它用于表示任意数量的位置或关键字 论证,分别。需要记住的是内部 功能 args将是一个元组 kwargs将是一个 字典

  2. 用作函数调用的一部分时,

    args = (1, 2)
    kwargs = {'last': 'Doe', 'first': 'John'}
    self.save_name_for(*args, **kwargs)
    

    ***充当解包运营商 args必须是 可迭代 kwargs必须与dict类似args中的项目 将被解压缩并作为位置参数发送到函数, 并且kwargs中的键/值对将被发送到函数as 关键字参数。因此,

    self.save_name_for(*args, **kwargs)
    

    相当于

    self.save_name_for(1, 2, last='Doe', first='John')
    
  3. 另请参阅saltycrane blog以获取有关示例的说明。