I want to do this:
a = TestClass1() <br>
a.test.fun() #==> this i want to call TestClass2 method fun() <br>
a.test(a=10).fun() #===> this i want to call TestClass3 method fun() <br>
Does anyone know how to separate this?
I have three classes:
class TestClass1:
aa = ""
def __init__(self):
self.aa = "ccc"
def __getattr__(self, item):
print("test 1 get attr = ",item)
return TestClass2() or TestClass3() #==> I don't how to seperate test and test(a =10)
def __getitem__(self, item):
print("__getitem__",item)
class TestClass2:
def __call__(self, *args, **kwargs):
print("TestClass2 __call__ ")
return self
def fun(self):
print("this TestClass2 fun()")
class TestClass3:
def __call__(self, *args, **kwargs):
print("TestClass3 33333 call 3 ")
return self
def fun(self):
print("this TestClass3 fun()")
in both examples given __getattr__ is called with argument "test".
you need to do something like this:
class TestClass1:
def __getattr__(self, item):
if item == 'test2':
return TestClass2()
elif item == 'test3':
return TestClass3()
a = TestClass1()
a.test2.fun()
a.test3.fun()
EDIT: Let me explain further. Well, in python there is no difference between a function and an attribute, everything in python is an object, all objects are treated the same, be it an integer or a function.
When you do a.test it is lowered to a.__getattr__('test').
And when you do a.test(a=10) it is lowered to a.__getattr__('test')(a=10).
The returned object from a.__getattr__('test') is the same.
In the second case you are fetching the attribute test then calling it with an argument a=10.
EDIT2: What you are trying to do could be achieved this way:
class TestClass1:
test = TestClass2()
class TestClass2:
def __call__(self, a):
if a == 10:
return TestClass3()
def fun():
print("this TestClass2 fun()")
a = TestClass1()
a.test # this is TestClass2
a.test.fun # this is TestClass2.fun
a.test(a=10) # this is TestClass3
a.test(a=10).fun # this is TestClass3.fun
EDIT3: A simpler approach would be making test a function:
class TestClass1:
def test(a=None):
if a is None:
return TestClass2()
if a == 10:
return TestClass3()
a = TestClass1()
a.test().fun # TestClass2.fun
a.test(a=10).fun # TestClass3.fun
Related
I have simple task: we have class TestingClass and we wanna simply test his methods. And we have class TestHelper for testing purpose.
class TestingClass():
def testing_method_1(self):
return False
def testing_method_2(self):
return True
class TestHelper():
def __init__(self, class_name):
pass
def add(self, func_name, func_result):
pass
def run(self):
pass
helper = TestHelper(TestingClass)
helper.add(“testing_method_1”, False)
helper.add(“testing_method_2”, True)
result = helper.run()
my target implement methods for class TestHelper . I solved it for myself but I think its bad realization. I initialize empty dictionary and test class. Next I add every method and test method result to dictionary. In run method I compare results.
class TestHelper():
def __init__(self, class_name):
self.test_class = class_name()
self.func_list = {}
def add(self, func_name, func_result):
temp = 'self.test_class.' + func_name
self.func_list[temp] = func_result
def run(self):
for f in self.func_list.keys():
if eval(f)() == self.func_list[f]:
print('yes')
else:
print('no')
Can I resolve it in best way? Thanks!
Using eval for this purpose is overkill.
You could instead use the getattr() function to retrieve the function and call it.
Read more: Python Docs
class TestHelper():
def __init__(self, class_name):
self.test_class = class_name()
self.func_list = {}
def add(self, func_name, func_result):
# { <function>:<desired result> }
self.func_list[func_name] = func_result
def run(self):
for func, desired_result in self.func_list.items():
if getattr(self.test_class, func)() is desired_result:
print('yes')
else:
print('no')
This code produces results:
...
>>> helper = TestHelper(TestingClass)
>>> helper.add("testing_method_1", False)
>>> helper.add("testing_method_2", True)
>>> result = helper.run()
yes
yes
Of course you should also test if the class even has an attribute with the given function name. You can use hasattr() for this.
I try to build a decorator for methods of instances (not classes) that flexibly puts code blocks in front and/or behind the method (and not affect other instances). Up to my code below works:
def Decorate(func, before = None, after = None):
def wrap(*args, **kwargs):
if before: before() # code block insert
result = func(*args, **kwargs)
if after: after() # code block insert
return result
return wrap
class Test():
def __init__(self, name):
self.name = name
def put(self, prefix):
print(prefix, self.name)
a = Test('me')
def Before():
print('before')
def After():
print('after')
a.put = Decorate(a.put, Before, After)
a.put('it is')
How can I extend the code blocks accessing/using variables and methods of the instance? A code example for this would look like this:
def Before():
print('before')
print(self.name)
self.any_method(any_argument) # just an example!
I already tried several things without success. And I already struggle to access the instance values directly in the wrapper:
def Decorate(func, before = None, after = None):
def wrap(self, *args, **kwargs):
if before: before() # code block insert
print(self.name) # --> even this DOES NOT WORK!
result = func(self, *args, **kwargs)
if after: after() # code block insert
return result
return wrap
Here print(self.name) throws an error: AttributeError: 'str' object has no attribute 'name'. So it looks like that I am far away in using the same comment in one of the code blocks (Before() & After()) below.
One addition: The approach works when I add a method to the instance:
This method is in the class (so for working with strings and exec, but that enables to deliver the name as string or the function itself):
def addMethod(self, method, givenName = ''):
print('add')
if givenName == '':
N = method.__name__
else:
N = givenName
self._methods.append(N)
exec('self.' + N + ' = ' + method.__name__ + '.__get__(self)')
The code in the main part looks like this:
def x(self):
print('hello,', self.name)
a.addMethod(x)
a.x()
Any solution is appreciated and many thanks in advance!
from functools import wraps
def Decorate(func, before = None, after = None):
#wraps(func)
def wrap(*args, **kwargs):
if before: before() # code block insert
result = func(*args, **kwargs)
if after: after() # code block insert
return result
return wrap
def Before():
print('before')
def After():
print('after')
class Test():
def __init__(self, name):
self.name = name
def put(self, prefix):
print(prefix, self.name)
put = Decorate(put, Before, After)
a = Test('me')
a.put("pre")
You could execute your decorator inside your class. In your wrap, pass whatever you get to func by (*args, **kwargs). self is still the first argument implicitly in args.
Edit: Code related concerns from comments
from functools import wraps
def Before(t):
print('before')
print(t.name)
def After(t):
print('after')
print(t.name)
def Decorate(func, before = None, after = None):
#wraps(func)
def wrap(*args, **kwargs):
if before: before(args[0]) # code block insert
result = func(*args, **kwargs)
if after: after(args[0]) # code block insert
return result
return wrap
class Test():
def __init__(self, name):
self.name = name
def put(self, prefix):
print(prefix, self.name)
put = Decorate(put, Before, After)
a = Test('me')
a.put("pre")
Can one write something like:
class Test(object):
def _decorator(self, foo):
foo()
#self._decorator
def bar(self):
pass
This fails: self in #self is unknown
I also tried:
#Test._decorator(self)
which also fails: Test unknown
I would like to temporarily change some instance variables
in the decorator and then run the decorated method, before
changing them back.
Would something like this do what you need?
class Test(object):
def _decorator(foo):
def magic( self ) :
print "start magic"
foo( self )
print "end magic"
return magic
#_decorator
def bar( self ) :
print "normal call"
test = Test()
test.bar()
This avoids the call to self to access the decorator and leaves it hidden in the class namespace as a regular method.
>>> import stackoverflow
>>> test = stackoverflow.Test()
>>> test.bar()
start magic
normal call
end magic
>>>
edited to answer question in comments:
How to use the hidden decorator in another class
class Test(object):
def _decorator(foo):
def magic( self ) :
print "start magic"
foo( self )
print "end magic"
return magic
#_decorator
def bar( self ) :
print "normal call"
_decorator = staticmethod( _decorator )
class TestB( Test ):
#Test._decorator
def bar( self ):
print "override bar in"
super( TestB, self ).bar()
print "override bar out"
print "Normal:"
test = Test()
test.bar()
print
print "Inherited:"
b = TestB()
b.bar()
print
Output:
Normal:
start magic
normal call
end magic
Inherited:
start magic
override bar in
start magic
normal call
end magic
override bar out
end magic
What you're wanting to do isn't possible. Take, for instance, whether or not the code below looks valid:
class Test(object):
def _decorator(self, foo):
foo()
def bar(self):
pass
bar = self._decorator(bar)
It, of course, isn't valid since self isn't defined at that point. The same goes for Test as it won't be defined until the class itself is defined (which its in the process of). I'm showing you this code snippet because this is what your decorator snippet transforms into.
So, as you can see, accessing the instance in a decorator like that isn't really possible since decorators are applied during the definition of whatever function/method they are attached to and not during instantiation.
If you need class-level access, try this:
class Test(object):
#classmethod
def _decorator(cls, foo):
foo()
def bar(self):
pass
Test.bar = Test._decorator(Test.bar)
import functools
class Example:
def wrapper(func):
#functools.wraps(func)
def wrap(self, *args, **kwargs):
print("inside wrap")
return func(self, *args, **kwargs)
return wrap
#wrapper
def method(self):
print("METHOD")
wrapper = staticmethod(wrapper)
e = Example()
e.method()
This is one way to access(and have used) self from inside a decorator defined inside the same class:
class Thing(object):
def __init__(self, name):
self.name = name
def debug_name(function):
def debug_wrapper(*args):
self = args[0]
print 'self.name = ' + self.name
print 'running function {}()'.format(function.__name__)
function(*args)
print 'self.name = ' + self.name
return debug_wrapper
#debug_name
def set_name(self, new_name):
self.name = new_name
Output (tested on Python 2.7.10):
>>> a = Thing('A')
>>> a.name
'A'
>>> a.set_name('B')
self.name = A
running function set_name()
self.name = B
>>> a.name
'B'
The example above is silly, but it works.
Here's an expansion on Michael Speer's answer to take it a few steps further:
An instance method decorator which takes arguments and acts on a function with arguments and a return value.
class Test(object):
"Prints if x == y. Throws an error otherwise."
def __init__(self, x):
self.x = x
def _outer_decorator(y):
def _decorator(foo):
def magic(self, *args, **kwargs) :
print("start magic")
if self.x == y:
return foo(self, *args, **kwargs)
else:
raise ValueError("x ({}) != y ({})".format(self.x, y))
print("end magic")
return magic
return _decorator
#_outer_decorator(y=3)
def bar(self, *args, **kwargs) :
print("normal call")
print("args: {}".format(args))
print("kwargs: {}".format(kwargs))
return 27
And then
In [2]:
test = Test(3)
test.bar(
13,
'Test',
q=9,
lollipop=[1,2,3]
)
start magic
normal call
args: (13, 'Test')
kwargs: {'q': 9, 'lollipop': [1, 2, 3]}
Out[2]:
27
In [3]:
test = Test(4)
test.bar(
13,
'Test',
q=9,
lollipop=[1,2,3]
)
start magic
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-576146b3d37e> in <module>()
4 'Test',
5 q=9,
----> 6 lollipop=[1,2,3]
7 )
<ipython-input-1-428f22ac6c9b> in magic(self, *args, **kwargs)
11 return foo(self, *args, **kwargs)
12 else:
---> 13 raise ValueError("x ({}) != y ({})".format(self.x, y))
14 print("end magic")
15 return magic
ValueError: x (4) != y (3)
I found this question while researching a very similar problem. My solution is to split the problem into two parts. First, you need to capture the data that you want to associate with the class methods. In this case, handler_for will associate a Unix command with handler for that command's output.
class OutputAnalysis(object):
"analyze the output of diagnostic commands"
def handler_for(name):
"decorator to associate a function with a command"
def wrapper(func):
func.handler_for = name
return func
return wrapper
# associate mount_p with 'mount_-p.txt'
#handler_for('mount -p')
def mount_p(self, slurped):
pass
Now that we've associated some data with each class method, we need to gather that data and store it in a class attribute.
OutputAnalysis.cmd_handler = {}
for value in OutputAnalysis.__dict__.itervalues():
try:
OutputAnalysis.cmd_handler[value.handler_for] = value
except AttributeError:
pass
I use this type of decorator in some debugging situations, it allows overriding class properties by decorating, without having to find the calling function.
class myclass(object):
def __init__(self):
self.property = "HELLO"
#adecorator(property="GOODBYE")
def method(self):
print self.property
Here is the decorator code
class adecorator (object):
def __init__ (self, *args, **kwargs):
# store arguments passed to the decorator
self.args = args
self.kwargs = kwargs
def __call__(self, func):
def newf(*args, **kwargs):
#the 'self' for a method function is passed as args[0]
slf = args[0]
# replace and store the attributes
saved = {}
for k,v in self.kwargs.items():
if hasattr(slf, k):
saved[k] = getattr(slf,k)
setattr(slf, k, v)
# call the method
ret = func(*args, **kwargs)
#put things back
for k,v in saved.items():
setattr(slf, k, v)
return ret
newf.__doc__ = func.__doc__
return newf
Note: because I've used a class decorator you'll need to use #adecorator() with the brackets on to decorate functions, even if you don't pass any arguments to the decorator class constructor.
The simple way to do it.
All you need is to put the decorator method outside the class.
You can still use it inside.
def my_decorator(func):
#this is the key line. There's the aditional self parameter
def wrap(self, *args, **kwargs):
# you can use self here as if you were inside the class
return func(self, *args, **kwargs)
return wrap
class Test(object):
#my_decorator
def bar(self):
pass
Declare in inner class.
This solution is pretty solid and recommended.
class Test(object):
class Decorators(object):
#staticmethod
def decorator(foo):
def magic(self, *args, **kwargs) :
print("start magic")
foo(self, *args, **kwargs)
print("end magic")
return magic
#Decorators.decorator
def bar( self ) :
print("normal call")
test = Test()
test.bar()
The result:
>>> test = Test()
>>> test.bar()
start magic
normal call
end magic
>>>
Decorators seem better suited to modify the functionality of an entire object (including function objects) versus the functionality of an object method which in general will depend on instance attributes. For example:
def mod_bar(cls):
# returns modified class
def decorate(fcn):
# returns decorated function
def new_fcn(self):
print self.start_str
print fcn(self)
print self.end_str
return new_fcn
cls.bar = decorate(cls.bar)
return cls
#mod_bar
class Test(object):
def __init__(self):
self.start_str = "starting dec"
self.end_str = "ending dec"
def bar(self):
return "bar"
The output is:
>>> import Test
>>> a = Test()
>>> a.bar()
starting dec
bar
ending dec
I have a Implementation of Decorators that Might Help
import functools
import datetime
class Decorator(object):
def __init__(self):
pass
def execution_time(func):
#functools.wraps(func)
def wrap(self, *args, **kwargs):
""" Wrapper Function """
start = datetime.datetime.now()
Tem = func(self, *args, **kwargs)
end = datetime.datetime.now()
print("Exection Time:{}".format(end-start))
return Tem
return wrap
class Test(Decorator):
def __init__(self):
self._MethodName = Test.funca.__name__
#Decorator.execution_time
def funca(self):
print("Running Function : {}".format(self._MethodName))
return True
if __name__ == "__main__":
obj = Test()
data = obj.funca()
print(data)
You can decorate the decorator:
import decorator
class Test(object):
#decorator.decorator
def _decorator(foo, self):
foo(self)
#_decorator
def bar(self):
pass
Given a class and a set of its methods - how can you determine from within that class which methods have been decorated with a certain decorator?
My goal is to basically get the actual values of the methods that are decorated, so something like:
class A():
def get_values(self):
...
# returned {'a-special-name': 1, 'b': 2}
#my_dec('a-special-name') # Ideally be able to also put optional name
def a(self):
return 1
#my_dec
def b(self):
return 2
Any idea on how to accomplish this?
Edit: this should also work on parent classes, that is, if A is a subclass of:
class B():
#my_dec
def c(self):
return 3
then get_values() of A instance should return {'a-special-name': 1, 'b': 2, 'c': 3} (order is irrelevant of course)
Edit: class based decorator that works but not with inheritance. Any idea how to make it work with inheritance but without having to decorate the class itself?
class my_dec(object):
def __init__(self, func, name=None):
self.func = func
self.name = name or func.__name__
self.func._some_flag = True
def __get__(self, instance, cls=None):
if instance is None:
return self
return self.func(instance)
If you can define the decorator yourself, then simply have it "mark" the method object in some way:
def my_dec(method):
method._this_be_decorated = True
return method
The class can then look for those marked methods; something like:
from inspect import isfunction
class A:
def get_values(self):
return filter(lambda i: isfunction(i) and hasattr(i, '_this_be_decorated'),
vars(type(self)).values())
This will return an iterable of function objects which you can process further as needed.
def my_dec(name):
if callable(name):
# name is callable – take its name
func = name # no make the code more readable
func.special_name = func.__name__
return func
else:
# name is the name to give – add an inner layer of functions
def inner(function_object):
function_object.special_name = name
return function_object
return inner
class A():
def get_values(self):
# return a dict of special name to call result mapping for every class member that has a special_name.
return {func.special_name: func(self) for func in self.__class__.__dict__.values() if hasattr(func, 'special_name')}
# returned {'a-special-name': 1, 'b': 2}
#my_dec('a-special-name') # Ideally be able to also put optional name
def a(self):
return 1
#my_dec
def b(self):
return 2
def no_dec(self):
return 42
should do what you want.
As deceze mentions, decorators can do whatever they want so there's no reliable generic answer. If you "own" the decorator you can add special properties to it's return value ie (Q&D py2.7 example):
def mydec(name=''):
# py27 hack - for py3 you want nonlocal instead
n = [name]
def innerdec(func):
# py27 hack - for py3 you want nonlocal instead
name = n[0] or func.__name__
def wrapper(*args, **kw):
print("in mydec.wrapper for {}".format(name))
return func(*args, **kw)
wrapper.ismydec = True # so we know this is decorated by mydec
wrapper.func = func # so we can get the original func
wrapper.name = name
return wrapper
return innerdec
def collect_dec(cls):
decorated = {}
for attname in dir(cls):
obj = getattr(cls, attname)
if getattr(obj, "ismydec", False):
decorated[obj.name] = obj.func
cls._decorated_funcs = decorated
return cls
#collect_dec
class A():
def get_values(self):
return {
name:func(self) for name, func in self._decorated_funcs.items()
}
#mydec('a-special-name') # Ideally be able to also put optional name
def a(self):
return 1
#mydec() # no name
def b(self):
return 2
a = A()
print(a.get_values())
Which outputs:
{'a-special-name': 1, 'b': 2}
I am looking for a way to intercept instance method calls in class MyWrapper below:
class SomeClass1:
def a1(self):
self.internal_z()
return "a1"
def a2(self):
return "a2"
def internal_z(self):
return "z"
class SomeClass2(SomeClass1):
pass
class MyWrapper(SomeClass2):
# def INTERCEPT_ALL_FUNCTION_CALLS():
# result = Call_Original_Function()
# self.str += result
# return result
def __init__(self):
self.str = ''
def getFinalResult(self):
return self.str
x = MyWrapper()
x.a1()
x.a2()
I want to intercept all function calls make through my wrapper class. In my wrapper class I want to keep track of all the result strings.
result = x.getFinalResult()
print result == 'a1a2'
Some quick and dirty code:
class Wrapper:
def __init__(self, obj):
self.obj = obj
self.callable_results = []
def __getattr__(self, attr):
print("Getting {0}.{1}".format(type(self.obj).__name__, attr))
ret = getattr(self.obj, attr)
if hasattr(ret, "__call__"):
return self.FunctionWrapper(self, ret)
return ret
class FunctionWrapper:
def __init__(self, parent, callable):
self.parent = parent
self.callable = callable
def __call__(self, *args, **kwargs):
print("Calling {0}.{1}".format(
type(self.parent.obj).__name__, self.callable.__name__))
ret = self.callable(*args, **kwargs)
self.parent.callable_results.append(ret)
return ret
class A:
def __init__(self, val): self.val = val
def getval(self): return self.val
w = Wrapper(A(10))
print(w.val)
w.getval()
print(w.callable_results)
Might not be thorough, but could be a decent starting point, I guess.
You could wrap your methods with decorators a instanciation time:
#!/usr/bin/env python
import inspect
def log(func):
def _logged(*args, **kw):
print "[LD] func", func.__name__, "called with:", args, kw
result = func(*args, **kw)
print "[LD] func", func.__name__, "returned:", result
return result
return _logged
class A(object):
def __init__(self):
for x in inspect.getmembers(self, (inspect.ismethod)):
if not x[0].startswith('__'):
setattr(self, x[0], log(getattr(self, x[0])))
def hello(self):
print "Hello"
def bye(self):
print "Bye"
return 0
Now if you call hello or bye, the call goes through log first:
a = A()
a.hello()
a.bye()
# [LD] func hello called with: () {}
# Hello
# [LD] func hello returned: None
# [LD] func bye called with: () {}
# Bye
# [LD] func bye returned: 0
What you want to do is quite similar to this question.
You should take your example code in the reverse order, i mean creating a class to record return values of method calls, and make the classes you want to watch inherit from it.
Which would give something like this
class RetValWatcher(object):
def __init__(self):
self.retvals = []
def __getattribute__(self, name):
attr = super(RetValWatcher, self).__getattribute__(name)
if callable(attr):
def wrapped(*args, **kwargs):
retval = attr(*args, **kwargs)
self.retvals.append(retval)
return retval
return wrapped
else:
return attr
def getFinalResult(self):
return ''.join(self.retvals)
class MyClass(RetValWatcher):
def a(self):
self.internal_z()
return 'a1'
def b(self):
return 'b1'
def internal_z(self):
return 'z'
x = MyClass()
x.a()
x.b()
print x.getFinalResult()
#'za1b1'
With some minor changes, this method would also allow you to record return values across all RetValWatcher instances.
Edit: added changes suggested by singularity's comment
Edit2: forgot to handle the case where attr is not a method (thx singularity again)
Edit3: fixed typo