(answering to the OP)
Piyush Anonymous wrote:
i wrote this code
--
class Person(object):
instancesCount = 0
def __init__(self, title=""):
Person.instancesCount += 1
self.id <http://self.id> = "tempst"
def testprint(self):
print "blah blah"
def __getattribute__(self, name):
print "in get attribute"
a = Person()
a.testprint()
print a.id <http://a.id>
-----
but i am getting this error
----
in get attribute
Traceback (most recent call last):
File "trapmethodcall1.py", line 15, in <module>
a.testprint()
TypeError: 'NoneType' object is not callable
------
why is it so? __getattribute__ is called whenever an attribute or
method is called, rt?
Yes. Methods are attributes too. And __getattribute__ is the attribute
lookup operator implementation - it is invoked *everytime* you have
obj.attr or getattr(obj, "attr") or hasattr(obj, "attr"). IOW, you'd
better *not* touch it unless 1/ you really know what you're doing, 2/
you have a very compelling reason to do so and 3/ you're ok to pay the
performance hit (the default implementation in 'object' being optimized).
or if i set __getattribute__ , i cannot have
methods in class?
Yes, you can. But you have to write a proper implementation of
__getattribute__. The one above will prevent you from accessing any
class or instance attribute (or, more exactly, will always return None).
actually my aim is to trap all method calls and keep a counter which
is update whenever method called or returned. how should i go about it?
Using __getattribute__, you'll only get at the method when it is looked
up (which doesn't imply it will be called). If you want to log calls and
returns, you'll have to wrap the method in a decorator. You can do this
either manually (ie manually adding the logger decorator on methods),
via monkeypatching on class objects (but this can be tricky too), or
adding a properly implemented version of __getattribute__ (but this
won't work if the method is looked up on the class itself)
# a Q&D method call logger
def log(meth):
if hasattr(meth, "logged"):
# already wrapped
return meth
def logged(*args, **kw):
if hasattr(meth, "im_self"):
# wrapping a method
what = "method %s " % meth
else:
# wrapping a function, 'self' or 'cls' is the first arg
what = "method %s of object %s" % (meth, args[0])
print "%s called with %s %s" % (what, str(args), kw)
try:
result = meth(*args, **kw)
except Exception, e:
print "%s raised %s" % (what, e)
raise
else:
print "%s returned %s" % (what, str(result))
return result
logged.logged = True
return logged
# manual decoration
class Foo(object):
@log
def bar(self):
pass
# using __getattribute__
class Foo(object):
def bar(self):
pass
def __getattribute__(self, name):
attr = super(Foo2, self).__getattribute__(name)
if hasattr(attr, "im_self"):
attr = log(attr)
return attr
Given the shortcomings of the __getattribute__ version (performance hit
and only triggered on instance lookup), I'd strongly suggest the manual
decoration - possibly using a flag (global setting or environment
variable) to switch it off, ie:
if globals().get("DEBUG", False):
def log(func):
def logged(*args, **kw):
# wrapping a function
# we assume this function is used as a method, so
# 'self' or 'cls' is the first arg
what = "method %s of object %s" % (func, args[0])
print "%s called with %s %s" % (what, str(args), kw)
try:
result = func(*args, **kw)
except Exception, e:
print "%s raised %s" % (what, e)
raise
print "%s returned %s" % (what, str(result))
return result
return logged
else:
def log(func):
# no-op
return func
NB : all this is pretty Q&D and mostly untested, but it should get you
started.
HTH
--
http://mail.python.org/mailman/listinfo/python-list