This is the first example we meet when we face with decorators. But I'm not able to realize what exactly I would like.
A simple decorator named LOG. It should work like this:
@LOG def f(a, b=2, *c, **d): pass
And the result should be something like:
f(1, pippo=4, paperino='luca') ===== Enter f ===== a = 1 b = 2 pippo = 4 paperino = luca ===== Exit f =====
Where every argument passed as a parameter to the function is showed with its value.
I discovered that the problem is harder than I thought, mainly because of the many different ways you can pass arguments to a function (think about tuples with *c or dictionaries with **d).
I tried a solution but I'm not sure it's correct. It' somethink like this:
def LOG(fn): import inspect varList, _, _, default = inspect.getargspec(fn) d = {} if default is not None: d = dict((varList[-len(default):][i], v) for i, v in enumerate(default)) def f(*argt, **argd): print ('Enter %s' % fn).center(100, '=') d.update(dict((varList[i], v) for i, v in enumerate(argt))) d.update(argd) for c in d.iteritems(): print '%s = %s' % c ret = fn(*argt, **argd) print 'return: %s' % ret print ('Exit %s' % fn).center(100, '=') return ret return f
I think it's not so easy as I expected, but it's strange I didn't found what I wanted on Google.
Can you tell me if my solution is ok? Or can you suggest a better solution to the problem I proposed?
Thank you to everybody.
A decorator in Python is a function that takes another function as its argument, and returns yet another function . Decorators can be extremely useful as they allow the extension of an existing function, without any modification to the original function source code.
log4j is a reliable, fast and flexible logging framework (APIs) written in Java, which is distributed under the Apache Software License. log4j is a popular logging package written in Java. log4j has been ported to the C, C++, C#, Perl, Python, Ruby, and Eiffel languages.
Use the logging Module to Print the Log Message to Console in Python. To use logging and set up the basic configuration, we use logging. basicConfig() . Then instead of print() , we call logging.
The only thing I noticed is that the dict((varList[i], v) for i, v in enumerate(argt))
construct you used twice is actually dict(zip(varList,argt))
.
Other than that i only have meta-criticism: None of the above belong in a logfile.
Instead of going trough the logs to
Everyhing is ok in your function. You seem to be lost with positional vs variable&keyword arguments.
Let me explain: positional arguments, a
and b
in your case, are obligatory (and may have default values). Other arguments are optional. If you want to make an argument obligatory or to have a default value, put it before *args and **kwargs. But remember that you can't supply an argument twice:
def x(a = 1, b = 2, *args, **kwargs): print a, b, args, kwargs >>> x(3, 4, 5, b=6) TypeError: x() got multiple values for keyword argument 'b'
There's another way, but not that readable, to have default values for arguments and have no positional args:
def x(*args, **kwargs): kwargs.updae({'a': 1, 'b': 2})
Your function that analyses the arguments is ok, though I don't understand why you write varargs
and keywords
into _
. It passes arguments transparently:
def x(a = 1, b = 2, *args, **kwargs): print a, b, args, kwargs def y(*args, **kwargs): x(*args, **kwargs) >>> y(3, 4, 5, 6) 3 4 (5, 6) {} >>> y(3, 4, 5, b=6) TypeError: x() got multiple values for keyword argument 'b'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With