views:

136

answers:

1

Hello, I am in progress to learn Python. Hopefully someone points me to correct way.
This is what I'd like to do below:

def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'  # This is what I want
        return function(*args, **kwargs)
    return wrap_function

@decorate
def print_message():
    # I'd like to pass 'str' as mentioned above
    # to any functions' argument like below:
    print(str)  # 'str' is same as above

Any idea? Thanks in advance.

+5  A: 

You can't pass it as its own name, but you can add it to the keywords.

def decorate(function):
    def wrap_function(*args, **kwargs):
        kwargs['str'] = 'Hello!'
        return function(*args, **kwargs)
    return wrap_function

@decorate
def print_message(*args, **kwargs):
    print(kwargs['str'])

Alternatively you can name its own argument:

def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'
        return function(str, *args, **kwargs)
    return wrap_function

@decorate
def print_message(str, *args, **kwargs):
    print(str)

Class method:

def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'
        args.insert(1, str)
        return function(*args, **kwargs)
    return wrap_function

class Printer:
    @decorate
    def print_message(self, str, *args, **kwargs):
        print(str)
Tor Valamo
Note that the first solution is also achieved by using `functools.partial()` (but from version 2.6 only). The same module also offers the `wraps()` function which can be used with decorators to maintain the name and the doc of the original function.
RedGlyph
@RedGlyph: why using `functools.partial()` from version 2.6 only? the documentation say nothing about it except that functools module is new in pyhton 2.5.
mg
Thanks to Tor Valamo. Alternative solution is clear for me. But how about if the decorated function is an instance method? The instance method's argument should be something like: `def print_message(str, self, *args, **kwargs):` Is this correct? Thanks again.
Japboy
switch self and str. def print_message(self, str, *args, **kwargs)
Tor Valamo
in this case `def print_message(self, str, *args, **kwargs)`, `self` gives me `Hello!` from `wrap_function`, and `str` gives me something like class object.
Japboy
yes, that's because the args list contains 'self' as the first item. you can fix it with args.insert(1, str) and then return function(*args, **kwargs)
Tor Valamo
See the edited answer for a better view.
Tor Valamo
now everything seems clear for me. thanks again Tor Valamo :D happy holidays!
Japboy
@Japboy: i don't know if you noticed but `print_message` don't need extra `*args` and `**kwargs` arguments so don't declare so you function if you don't need it. imho a decorator is more powerful the more the decorated function is unaware of it
mg
@mg: you're right, 2.6 was for the function above in a table. It should read "2.5".
RedGlyph