understanding generators and functions with arguments

Discussion in 'Python' started by caw@southernhealth.org.au, Oct 12, 2004.

  1. Guest

    this is the smallest bit of code I could get to demonstrate what I
    want to understand...

    def msg(text):
    def decorate(f):
    def new_f(*args):
    print text, f(*args)
    return new_f
    return decorate


    @msg("Hello, ")
    def f1(s):
    return s


    if __name__ == '__main__':
    f1("world!")


    ~/src/python caw$ python dec_play.py
    Hello, world!

    OK... so I can give a decorator and argument, and that will then
    return the function <decorate>. This expects one argument (and is a
    decorator (?)). When decorate is called with f1 as the argument, it
    returns new_f, which, when called will print <text> (passed to the
    original decorator), together with the result of calling f1 with its
    args.

    I don't understand the scope of *args, as seen in the argument list of
    new_f. It doesn't appear to be in the static scope of msg, or decorate
    or new_f...

    Could someone help me with this...

    Thanks

    chris wright
    , Oct 12, 2004
    #1
    1. Advertising

  2. wrote:
    > def msg(text):
    > def decorate(f):
    > def new_f(*args):
    > print text, f(*args)
    > return new_f
    > return decorate
    >
    > @msg("Hello, ")
    > def f1(s):
    > return s

    ....
    > I don't understand the scope of *args, as seen in the argument list of
    > new_f. It doesn't appear to be in the static scope of msg, or decorate
    > or new_f...

    OK, I would probably write this as:
    def msg(text):
    def decorate(f):
    def new_f(*args, **kwargs):
    print text, f(*args, **kwargs)
    return new_f
    return decorate

    That is, the *args in your example, and my "*args, **kwargs" are both
    meant to represent the parameters passed to the "wrapped" function f.
    My example would allow a line in the main section:

    f1(s=42)

    while your form would fail on that call.

    -Scott David Daniels
    Scott David Daniels, Oct 12, 2004
    #2
    1. Advertising

  3. <caw <at> southernhealth.org.au> writes:
    >
    > def msg(text):
    > def decorate(f):
    > def new_f(*args):
    > print text, f(*args)
    > return new_f
    > return decorate
    >
    >
    > @msg("Hello, ")
    > def f1(s):
    > return s
    >
    >
    > if __name__ == '__main__':
    > f1("world!")

    [snip]
    >
    > I don't understand the scope of *args, as seen in the argument list of
    > new_f.


    Not sure if Scott's answer was sufficient for you. In case it wasn't, maybe
    this will help illustrate a few more things:

    >>> def msg(text):

    .... def decorate(f):
    .... def new_f(*args, **kwds):
    .... print text, f(*args, **kwds)
    .... return new_f
    .... return decorate
    ....
    >>>
    >>> def f1(s):

    .... return s
    ....
    >>> f1.func_code.co_varnames

    ('s',)
    >>>
    >>> @msg("Hello, ")

    .... def f1(s):
    .... return s
    ....
    >>> f1.func_code.co_varnames

    ('args', 'kwds')

    So what's happening here is that f1 is being replaced by your function new_f.
    Note that though the definition of f1 has an 's' argument, the definition of
    f1 after the application of a decorator has the 'args' and 'kwds' arguments of
    new_f.

    When you call a function passed into a decorator (e.g. the 'f' passed
    into 'decorate' in your example above) you won't necessarily know what
    arguments it takes. Using *args and **kwds says that you don't know what
    these arguments are, which is probably true in most cases when you write a
    decorator function.

    Note that if you knew you were only ever going to use this decorator for
    function f1, you could write it as:

    def msg(text):
    def decorate(f):
    def new_f(s):
    print text, f(s)
    return new_f
    return decorate

    and when f1 was replaced with new_f, your argument name would still be 's'.
    Of course, then you could never use msg(...) as a decorator to any function
    that took more than a single argument.

    Steve
    Steven Bethard, Oct 12, 2004
    #3
  4. Terry Reedy Guest

    <> wrote in message
    news:...
    > this is the smallest bit of code I could get to demonstrate what I
    > want to understand...
    >
    > def msg(text):
    > def decorate(f):
    > def new_f(*args):
    > print text, f(*args)
    > return new_f
    > return decorate
    >
    >
    > @msg("Hello, ")
    > def f1(s):
    > return s
    >
    >
    > if __name__ == '__main__':
    > f1("world!")
    >
    >
    > ~/src/python caw$ python dec_play.py
    > Hello, world!
    >
    > OK... so I can give a decorator and argument, and that will then
    > return the function <decorate>. This expects one argument (and is a
    > decorator (?)). When decorate is called with f1 as the argument, it
    > returns new_f, which, when called will print <text> (passed to the
    > original decorator), together with the result of calling f1 with its
    > args.
    >
    > I don't understand the scope of *args, as seen in the argument list of
    > new_f. It doesn't appear to be in the static scope of msg, or decorate
    > or new_f...


    As with all parameters, 'args' is a local variable in the local namespace
    of the function it is a parameter for, in this case new_f. I presume you
    would call that 'local scope'. I do not know what you mean by 'static
    scope' since that is not a term usually used in describing Python.

    Terry J. Reedy
    Terry Reedy, Oct 13, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kevin Grigorenko

    Understanding unlimited arguments with ...

    Kevin Grigorenko, Jan 3, 2004, in forum: C++
    Replies:
    2
    Views:
    462
    Thierry Miceli
    Jan 4, 2004
  2. Xiangliang Meng
    Replies:
    1
    Views:
    1,592
    Victor Bazarov
    Jun 21, 2004
  3. Dominic
    Replies:
    1
    Views:
    343
    Scott David Daniels
    May 17, 2004
  4. Wolfgang Keller

    Generators vs. Functions?

    Wolfgang Keller, Feb 4, 2006, in forum: Python
    Replies:
    12
    Views:
    437
    Bengt Richter
    Feb 7, 2006
  5. oldyork90
    Replies:
    10
    Views:
    345
    Jorge
    Sep 27, 2008
Loading...

Share This Page