Decorator / wrapper around python class attribute - python

I am trying to enhance the default #property behavior in Python:
from functools import wraps
def MyProperty(func):
def getter(self):
"""Enhance the property"""
return func(self) + 1
return property(getter)
class MyClass(object):
def __init__(self, foo):
self._foo = foo
#MyProperty
def foo(self):
return self._foo
This all works very fine, I get the desired effect
A = MyClass(5)
A.foo
>>> 6
Since I have learned it that way, I want to apply the wraps decorator to the wrapper for good-practice reasons. But if I do write the wrapper as
def MyProperty(func):
#wraps
def getter(self):
"""Enhance the property"""
return func(self) + 1
return property(getter)
I now get
A = MyClass(5)
A.foo
>>> <__main__.MyClass object at 0x7f209f4aa0d0>
Which is not what I expect. Any suggestions?

Use this:
def MyProperty(func):
#wraps(func)
def getter(self):
"""Enhance the property"""
return func(self) + 1
return property(getter)

Related

Python: How can i decorate function to change it into class method

I have code like this and i want to write decorator which will add decoradted function as class method of class A.
class A:
pass
#add_class_method(A)
def foo():
return "Hello!"
#add_instance_method(A)
def bar():
return "Hello again!"
assert A.foo() == "Hello!"
assert A().bar() == "Hello again!"
What about this approach?
P.S. The code is not structurally optimized for the sake of clarity
from functools import wraps
class A:
pass
def add_class_method(cls):
def decorator(f):
#wraps(f)
def inner(_, *args, **kwargs):
return f(*args, **kwargs)
setattr(cls, inner.__name__, classmethod(inner))
return f
return decorator
def add_instance_method(cls):
def decorator(f):
#wraps(f)
def inner(_, *args, **kwargs):
return f(*args, **kwargs)
setattr(cls, inner.__name__, inner)
return f
return decorator
#add_class_method(A)
def foo():
return "Hello!"
#add_instance_method(A)
def bar():
return "Hello again!"
assert A.foo() == "Hello!"
assert A().bar() == "Hello again!"
Is this what You were going for:
class A:
def __init__(self):
pass
#classmethod
def foo(cls):
return "Hello!"
def bar(self):
return "Hello again!"
print(A.foo())
print(A().bar())
read docs here
class MyClass:
def method(self):
# instance Method
return 'instance method called', self
#classmethod
def cls_method(cls):
#Classmethod
return 'class method called', cls
#staticmethod
def static_method():
# static method
return 'static method called'
You need to instantiate MyClass To reach(Call) Instance Method
test = MyClass()
test.method()
You Can directly access class Method without instantiate
MyClass.cls_method()
MyClass.static_method()

pythonic way of decorating classmethods

Given the following example:
class A:
def f(self, x):
return 2*x
I would like to write another method which uses f above but adds a constant, i.e.
class A:
def f(self, x):
return 2*x
def g(self, x):
return self.f(x) + 10
This would be one way. However, this smells very much like decorating! What would be the proper pythonic way to do this?
Extending answer of #Ajax1234, you may try to:
- parametrize your decorator,
- call your decorator explicitly (without #).
def add_val(_value):
def decorator(f):
def wrapper(cls, _x):
return f(cls, _x) + _value
return wrapper
return decorator
class A:
def f(self, x):
return 2*x
g = add_val(10)(f)
[EDIT]
You may also improve the decorator with functools.wraps() (which is a decorator itself). All you need to do is to change your wrapper declaration:
#functools.wraps(f)
def wrapper(cls, _x):
return f(cls, _x) + _value
You can write a simple function outside the class:
def add_val(f):
def wrapper(cls, _x):
return f(cls, _x) + 10
return wrapper
class A:
#add_val
def f(self, x):
return 2*x
print(A().f(20))
Output:
50
Edit: you can utilize functools.wraps with a classmethod in Python3. The wrapped function f will return x*2 and the decorator g will add 10 to the returned result of the function passed to it. However, to be able to save the original functionality of f, you can utilize the __wrapped__ attribute:
import functools
def g(f):
#functools.wraps(f)
def wrapper(cls, _x):
return f(cls, _x)+10
return wrapper
class A:
#classmethod
#g
def f(cls, x):
return x*2
f_1 = functools.partial(A.f.__wrapped__, A)
print(A.f(4))
print(f_1(4))
Output:
18
8

Decorate a class in Python by defining the decorator as a class

What is a simple example of decorating a class by defining the decorator as a class?
I'm trying to achieve what has been implemented in Python 2.6 using PEP 3129 except using classes not functions as Bruce Eckel explains here.
The following works:
class Decorator(object):
def __init__(self, arg):
self.arg = arg
def __call__(self, cls):
def wrappedClass(*args):
return cls(*args)
return type("TestClass", (cls,), dict(newMethod=self.newMethod, classattr=self.arg))
def newMethod(self, value):
return value * 2
#Decorator("decorated class")
class TestClass(object):
def __init__(self):
self.name = "TestClass"
print "init %s"%self.name
def TestMethodInTestClass(self):
print "test method in test class"
def newMethod(self, value):
return value * 3
Except, in the above, wrappedClass is not a class, but a function manipulated to return a class type. I would like to write the same callable as follows:
def __call__(self, cls):
class wrappedClass(cls):
def __init__(self):
... some code here ...
return wrappedClass
How would this be done?
I'm not entirely sure what goes into """... some code here ..."""
If you want to overwrite new_method(), just do it:
class Decorator(object):
def __init__(self, arg):
self.arg = arg
def __call__(self, cls):
class Wrapped(cls):
classattr = self.arg
def new_method(self, value):
return value * 2
return Wrapped
#Decorator("decorated class")
class TestClass(object):
def new_method(self, value):
return value * 3
If you don't want to alter __init__(), you don't need to overwrite it.
After this, the class NormalClass becomes a ClassWrapper instance:
def decorator(decor_arg):
class ClassWrapper:
def __init__(self, cls):
self.other_class = cls
def __call__(self,*cls_ars):
other = self.other_class(*cls_ars)
other.field += decor_arg
return other
return ClassWrapper
#decorator(" is now decorated.")
class NormalClass:
def __init__(self, name):
self.field = name
def __repr__(self):
return str(self.field)
Test:
if __name__ == "__main__":
A = NormalClass('A');
B = NormalClass('B');
print A
print B
print NormalClass.__class__
Output:
A is now decorated. <br>
B is now decorated. <br>
\__main__.classWrapper

Python Decorators and inheritance

Help a guy out. Can't seem to get a decorator to work with inheritance. Broke it down to the simplest little example in my scratch workspace. Still can't seem to get it working.
class bar(object):
def __init__(self):
self.val = 4
def setVal(self,x):
self.val = x
def decor(self, func):
def increment(self, x):
return func( self, x ) + self.val
return increment
class foo(bar):
def __init__(self):
bar.__init__(self)
#decor
def add(self, x):
return x
Oops, name "decor" is not defined.
Okay, how about #bar.decor? TypeError: unbound method "decor" must be called with a bar instance as first argument (got function instance instead)
Ok, how about #self.decor? Name "self" is not defined.
Ok, how about #foo.decor?! Name "foo" is not defined.
AaaaAAaAaaaarrrrgggg... What am I doing wrong?
Define decor as a static method and use the form #bar.decor:
class bar(object):
def __init__(self):
self.val = 4
def setVal(self,x):
self.val = x
#staticmethod
def decor(func):
def increment(self, x):
return func(self, x) + self.val
return increment
class foo(bar):
def __init__(self):
bar.__init__(self)
#bar.decor
def add(self, x):
return x
I know the question has been asked 11 years ago ...
I had the same problem, here is my solution to use an inherited private decorator :
class foo:
def __bar(func):
def wrapper(self):
print('beginning')
func(self)
print('end')
return wrapper
class baz(foo):
def __init__(self):
self.quux = 'middle'
#foo._foo__bar
def qux(self):
print(self.quux)
a = baz()
a.qux()
The output is :
beginning
middle
end

Why can #decorator not decorate a staticmethod or a classmethod?

Why can decorator not decorate a staticmethod or a classmethod?
from decorator import decorator
#decorator
def print_function_name(function, *args):
print '%s was called.' % function.func_name
return function(*args)
class My_class(object):
#print_function_name
#classmethod
def get_dir(cls):
return dir(cls)
#print_function_name
#staticmethod
def get_a():
return 'a'
Both get_dir and get_a result in AttributeError: <'classmethod' or 'staticmethod'>, object has no attribute '__name__'.
Why does decorator rely on the attribute __name__ instead of the attribute func_name? (Afaik all functions, including classmethods and staticmethods, have the func_name attribute.)
Edit: I'm using Python 2.6.
classmethod and staticmethod return descriptor objects, not functions. Most decorators are not designed to accept descriptors.
Normally, then, you must apply classmethod and staticmethod last when using multiple decorators. And since decorators are applied in "bottom up" order, classmethod and staticmethod normally should be top-most in your source.
Like this:
class My_class(object):
#classmethod
#print_function_name
def get_dir(cls):
return dir(cls)
#staticmethod
#print_function_name
def get_a():
return 'a'
It works when #classmethod and #staticmethod are the top-most decorators:
from decorator import decorator
#decorator
def print_function_name(function, *args):
print '%s was called.' % function.func_name
return function(*args)
class My_class(object):
#classmethod
#print_function_name
def get_dir(cls):
return dir(cls)
#staticmethod
#print_function_name
def get_a():
return 'a'
Is this what you wanted?
def print_function_name(function):
def wrapper(*args):
print('%s was called.' % function.__name__)
return function(*args)
return wrapper
class My_class(object):
#classmethod
#print_function_name
def get_dir(cls):
return dir(cls)
#staticmethod
#print_function_name
def get_a():
return 'a'

Categories