Last active
August 29, 2015 13:57
-
-
Save pydanny/9856041 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import functools | |
# Broken implementation | |
class ClassDecoratorOptionalArguments(object): #rename | |
def __init__(self, value=None): | |
# set the 'value' argument as an attribute | |
self.value = value | |
def __call__(self, func, value=None): | |
@functools.wraps(func) | |
def wrapped(*args, **kwargs): | |
print(self.value) # the 'value' variable is in self | |
# Before function call logic goes here | |
result = func(*args, **kwargs) | |
# After function call logic goes here | |
return result | |
return wrapped | |
# Failing test | |
def test_ClassDecoratorOptionalArguments(capsys): | |
@ClassDecoratorOptionalArguments(value="PEP 0318") | |
def return_6(): | |
return 6 | |
# does function return correct value? | |
assert return_6() == 6 | |
# Did the value get printed? | |
out, err = capsys.readouterr() | |
assert out == "PEP 0318\n" | |
# Try it again but without the decorator argument. | |
@ClassDecoratorOptionalArguments | |
def return_7(): | |
return 7 | |
# does function return correct value? | |
assert return_7() == 7 | |
# Did the value get printed? | |
out, err = capsys.readouterr() | |
assert out == "None\n" | |
So for class decorator with optional arguments you should use your normal class decorator in combination with a function.
# -*- coding: utf-8 -*-
import functools
class ClassDecorator(object): # rename as needed
def __init__(self, func, value=None):
self.wrapped = func
functools.update_wrapper(self, func)
self.value = value
def __call__(self, *args, **kwargs):
print(self.value) # the 'value' variable is in self
# Before function call logic goes here
result = self.wrapped(*args, **kwargs)
# After function call logic goes here
return result
def ClassDecoratorOptionalArguments(func=None, value=None):
if func is not None:
return ClassDecorator(func, value)
else:
return functools.partial(ClassDecoratorOptionalArguments, value=value)
# Failing test
def test_ClassDecoratorOptionalArguments(capsys):
@ClassDecoratorOptionalArguments(value="PEP 0318")
def return_6():
return 6
# does function return correct value?
assert return_6() == 6
# Did the value get printed?
out, err = capsys.readouterr()
assert out == "PEP 0318\n"
# Try it again but without the decorator argument.
@ClassDecoratorOptionalArguments
def return_7():
return 7
# does function return correct value?
assert return_7() == 7
# Did the value get printed?
out, err = capsys.readouterr()
assert out == "None\n"
I am not sure you decorator function with optional arguments is correct in the post. Should be something like:
# -*- coding: utf-8 -*-
import functools
def decorator_optional_args_function(func=None, value=None): #rename
def _wrapped(func):
@functools.wraps(func)
def _returned_wrapper(*args, **kwargs):
print(value) # the 'value' variable is in scope
# Before function call logic goes here
result = func(*args, **kwargs)
# After function call logic goes here
return result
return _returned_wrapper
if func is not None:
return _wrapped(func)
else:
return functools.partial(decorator_optional_args_function, value=value)
def test_ClassDecoratorOptionalArguments(capsys):
@decorator_optional_args_function(value="PEP 0318")
def return_6():
return 6
# does function return correct value?
assert return_6() == 6
# Did the value get printed?
out, err = capsys.readouterr()
assert out == "PEP 0318\n"
# Try it again but without the decorator argument.
@decorator_optional_args_function
def return_7():
return 7
# does function return correct value?
assert return_7() == 7
# Did the value get printed?
out, err = capsys.readouterr()
assert out == "None\n"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You really don't want to do this combination. It is a bit silly.
And one case you loose introspection ability.
In short, don't suggest this as an alternative as is not useful.