From: dmitrey on 20 Jul 2010 06:10 hi all, I have a class (FuncDesigner oofun) that has no attribute "size", but it is overloaded in __getattr__, so if someone invokes "myObject.size", it is generated (as another oofun) and connected to myObject as attribute. So, when I invoke in other code part "hasattr(myObject, 'size')", instead o returning True/False it goes to __getattr__ and starts constructor for another one oofun, that wasn't intended behaviour. Thus "hasattr(myObject, 'size')" always returns True. It prevents me of some bonuses and new features to be done in FuncDesigner. >>> 'size' in dir(b) False >>> hasattr(b,'size') True >>> 'size' in dir(b) True Could you fix it?
From: Chris Rebert on 20 Jul 2010 06:37 On Tue, Jul 20, 2010 at 3:10 AM, dmitrey <dmitrey.kroshko(a)scipy.org> wrote: > hi all, > I have a class (FuncDesigner oofun) that has no attribute "size", but > it is overloaded in __getattr__, so if someone invokes > "myObject.size", it is generated (as another oofun) and connected to > myObject as attribute. > > So, when I invoke in other code part "hasattr(myObject, 'size')", > instead o returning True/False it goes to __getattr__ and starts > constructor for another one oofun, that wasn't intended behaviour. > Thus "hasattr(myObject, 'size')" always returns True. It prevents me > of some bonuses and new features to be done in FuncDesigner. > >>>> 'size' in dir(b) > False >>>> hasattr(b,'size') > True >>>> 'size' in dir(b) > True > > Could you fix it? There's probably some hackery you could do to check whether hasattr() is in the call stack, and then not dynamically create the attribute in __getattr__ if that's the case, but that's obviously quite kludgey. /Slightly/ less hackish: Replace hasattr() in the __builtin__ module with your own implementation that treats instances of FuncDesigner specially. Least ugly suggestion: Just don't use hasattr(); use your `x in dir(y)` trick instead. > Subject: [...] I think this is Python bug Nope, that's just how hasattr() works. See http://docs.python.org/library/functions.html#hasattr (emphasis mine): """ hasattr(object, name) The arguments are an object and a string. The result is True if the string is the name of one of the objectâs attributes, False if not. (***This is implemented by calling getattr(object, name)*** and seeing whether it raises an exception or not.) """ I suppose you could argue for the addition of a __hasattr__ special method, but this seems like a really rare use case to justify adding such a method (not to mention the language change moratorium is still currently in effect). Cheers, Chris -- http://blog.rebertia.com
From: dmitrey on 20 Jul 2010 06:59 On Jul 20, 1:37 pm, Chris Rebert <c...(a)rebertia.com> wrote: > On Tue, Jul 20, 2010 at 3:10 AM, dmitrey <dmitrey.kros...(a)scipy.org> wrote: > > hi all, > > I have a class (FuncDesigner oofun) that has no attribute "size", but > > it is overloaded in __getattr__, so if someone invokes > > "myObject.size", it is generated (as another oofun) and connected to > > myObject as attribute. > > > So, when I invoke in other code part "hasattr(myObject, 'size')", > > instead o returning True/False it goes to __getattr__ and starts > > constructor for another one oofun, that wasn't intended behaviour. > > Thus "hasattr(myObject, 'size')" always returns True. It prevents me > > of some bonuses and new features to be done in FuncDesigner. > > >>>> 'size' in dir(b) > > False > >>>> hasattr(b,'size') > > True > >>>> 'size' in dir(b) > > True > > > Could you fix it? > > There's probably some hackery you could do to check whether hasattr() > is in the call stack, and then not dynamically create the attribute in > __getattr__ if that's the case, but that's obviously quite kludgey. It's too unreliable solution, hasattr may or may not appear in stack wrt different cases > /Slightly/ less hackish: Replace hasattr() in the __builtin__ module > with your own implementation that treats instances of FuncDesigner > specially. It's too unreliable as well > Least ugly suggestion: Just don't use hasattr(); use your `x in > dir(y)` trick instead. something in dir() consumes O(n) operations for lookup, while hasattr or getattr() require O(log(n)). It matters for me, because it's inside deeply nested mathematical computations FuncDesigner is made for. > > > Subject: [...] I think this is Python bug > > Nope, that's just how hasattr() works. Seehttp://docs.python.org/library/functions.html#hasattr(emphasis mine): > """ > hasattr(object, name) > The arguments are an object and a string. The result is True if > the string is the name of one of the objects attributes, False if > not. (***This is implemented by calling getattr(object, name)*** and > seeing whether it raises an exception or not.) > """ Thus I believe this is very ugly implementation. Some code implemented via "__getattr__" can start to execute arbitrary Python code, that is certainly not desired behaviour "hasattr" was designed for (to perform a check only), and it's too hard to reveal the situations, that makes a potential holes for viruses etc. Moreover, the implementation via "try getattr(object, name)" slowers code evaluation, I wonder why it is implemented so. > > I suppose you could argue for the addition of a __hasattr__ special > method, but this seems like a really rare use case to justify adding > such a method (not to mention the language change moratorium is still > currently in effect). I think much more easier solution would be to implement an additional argument to hasattr, e.g. hasattr(obj, field, onlyLookupInExistingFields = {True/False}). I think by default it's better set to True, now it behaves like False. D.
From: Jean-Michel Pichavant on 20 Jul 2010 08:00 dmitrey wrote: > hi all, > I have a class (FuncDesigner oofun) that has no attribute "size", but > it is overloaded in __getattr__, so if someone invokes > "myObject.size", it is generated (as another oofun) and connected to > myObject as attribute. > > So, when I invoke in other code part "hasattr(myObject, 'size')", > instead o returning True/False it goes to __getattr__ and starts > constructor for another one oofun, that wasn't intended behaviour. > Thus "hasattr(myObject, 'size')" always returns True. It prevents me > of some bonuses and new features to be done in FuncDesigner. > > >>>> 'size' in dir(b) >>>> > False > >>>> hasattr(b,'size') >>>> > True > >>>> 'size' in dir(b) >>>> > True > > Could you fix it? > Quite simple, when calling b.size, return the computed value but do not set it as attribute, the value will be computed on each b.size call, and hasattr w. If you don't want to compute it each time, cause there no reason for it to change, use a private dummy attribute to record the value instead of size (__size for instance) and return the value of __size when getting the value of size. class Foo(object): def __init__(self): self.__size = None def __getattr__(self, name): if name == "size": if self.__size is None: self.__size = 5 # compute the value return self.__size raise AttributeError(name) b = Foo() print 'size' in dir(b) print hasattr(b, 'size') print 'size' in dir(b) False True False JM
From: Christian Heimes on 20 Jul 2010 08:40 Am 20.07.2010 12:10, schrieb dmitrey: > hi all, > I have a class (FuncDesigner oofun) that has no attribute "size", but > it is overloaded in __getattr__, so if someone invokes > "myObject.size", it is generated (as another oofun) and connected to > myObject as attribute. How about using a property instead of the __getattr__() hook? A property is a computed attribute that (among other things) plays much nicer with hasattr.
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: How is memory managed in python? Next: urllib2 test fails (2.7, linux) |