简体   繁体   中英

How to pass through Python args and kwargs?

While I have a general understanding (I think) of Python's *args and **kwargs, I'm having trouble understanding how to pass them from one function through to another. Here's my model:

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()

I've split saving a name into two functions above. This way I can unit-test the logic I would normally put all in the save_name method by unit-testing the save_name_for method instead.

When I run this in the interpreter and stop in the save_name method, as I would expect, I see this:

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

If I then step into the save_name_for method, I see this:

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

Is there some way to pass the kwargs that are received by the save_name method directly into save_name_for method so that they appear in the latter's kwargs? I'd like to see something like this in save_name_for method's name space:

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

I realize I could parse them in save_name and then pass them explicitly to save_name_for but that seems rather inelegant. I also thought I might do this since args is a tuple...

kwargs = args[2]

... but it doesn't appear to work. args[2] is just everything (I don't understand this). Is there a Pythonic way to do this?

The * and ** operators are used in two different situations.

  1. When used as part of a function definition ,

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

    it is used to signify an arbitrary number of positional or keyword arguments, respectively. The point to remember is that inside the function args will be a tuple , and kwargs will be a dict .

  2. When used as part of a function call ,

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

    the * and ** act as unpacking operators . args must be an iterable , and kwargs must be dict-like . The items in args will be unpacked and sent to the function as positional arguments, and the key/value pairs in kwargs will be sent to the function as keyword arguments. Thus,

     self.save_name_for(*args, **kwargs)

    is equivalent to

    self.save_name_for(1, 2, last='Doe', first='John')

See also the saltycrane blog for an explanation with examples.

You pass them with syntax mirroring the argument syntax:

self.save_name_for(*args, **kwargs)

Note that you do not need to pass in self ; save_name_for is already bound.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM