0

The goal of this question is to understand how "built in" are the built-in functions in python.

If I override setattr method, how can I get it back? For example, I have class "Working" like this:

class WorkingSetAttr:
    def a(self): return 'a'
    def b(self): return 'b'

and class "NonWorking" like this:

class NonWorkingSetAttr: 
    def a(self): return 'a'
    def b(self): return 'b'
    def __setattr__(self,a,b): pass

Now I create objects w and n, and run the following:

w = WorkingSetAttr()
setattr(w,'a',w.b)
print "w.a = %s, w.b = %s" % (w.a(), w.b())

n = NonWorkingSetAttr()
setattr(n, 'a', n.b)
print "n.a = %s, n.b = %s" % (n.a(), n.b())

The output is:

w.a = b, w.b = b
n.a = a, n.b = b

Notice that n.a should print "b", but it prints "a" because setattr does not change the attribute.

The question is: How should I modify the object n so that it works like object w. Notice that I mean objects, not classes.

Juha
  • 2,053
  • 23
  • 44
  • It's (almost) always a bad idea to modify _objects_ without modifying their classes. After all, an instance is meant to be an instance of a particular class! If you break that relationship, you end up with "things" about which you don't really know much and which you can't debug. – Katriel Feb 07 '12 at 18:44
  • @KevinDTimm the builtin Python method `setattr` sets an attribute, which in turn calls `__setattr__` on the class object. – Katriel Feb 07 '12 at 18:47
  • `__setattr__` is called from setattr. See how it works for the case "w" (output is changed from "a" to "b"). The point is exactly this: How can I get back the built-in function if I just "broke" it. – Juha Feb 07 '12 at 18:49
  • Since you're using Python 2.x, your classes should all inherit from `object`. (For one thing, this makes it much more obvious how to un-override your method: just reset it to the default `__setattr__`, which is inherited from `object`.) – Katriel Feb 07 '12 at 18:52

1 Answers1

1

You can just remove the custom __setattr__ from the class object.

>>> n = NonWorkingSetAttr()
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = a, n.b = b
>>> 
>>> del NonWorkingSetAttr.__setattr__
>>>
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = b, n.b = b

Note that this modifies the class, not the object. You (almost certainly) don't want to modify the object itself, because then you have an object that looks like it should be a NonWorkingSetAttr but is in fact some sort of dynamic thingy that you don't really understand.

If you can't modify the class, you can just make a subclass and re-overwrite __setattr__ with object's:

>>> class FixedNonWorkingSetAttr(NonWorkingSetAttr):
...     __setattr__ = object.__setattr__
... 
>>> n = FixedNonWorkingSetAttr()
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = b, n.b = b
>>> isinstance(n, NonWorkingSetAttr)
True
Katriel
  • 120,462
  • 19
  • 136
  • 170
  • Correct if I am wrong, but object = instance of a class? And in python objects are dynamic? I mean it still is an instance of a class even it has some extra stuff with it, right? – Juha Feb 07 '12 at 18:59
  • 1
    Yes: you _could_ tweak an object. You can even do some really hairy stuff like modifying the class of an instance on the fly. But you shouldn't unless you absolutely have to, because you will end up with objects that _look like_ they are instances of some class but actually don't have the same methods. This will make debugging hell. – Katriel Feb 07 '12 at 19:09
  • Think about it: if you have some code that defines a class, and instantiate that class, you expect the resulting object -- no matter how much computation you've done with it -- to act like an instance of that class. – Katriel Feb 07 '12 at 19:11
  • I think that choosing python to be the programming language, you accept that everything (except builtins?) can change on the fly. So classical debugging is not the way to solve problems. To your last comment, I am thinking about it as positive thing: you are not bound to the "rules" that you have written (in form of a class) and you have the power to change the rules on the fly. For example command pattern is very interesting when you can stringify it -> store -> unstringify and change -> exceute (simple in python, slightly more difficult in C). – Juha Feb 08 '12 at 11:50