On Mon, 03 Sep 2007 04:37:54 +0000, Brian Munroe wrote: > On Sep 2, 3:33 pm, Steven D'Aprano <[EMAIL PROTECTED] > cybersource.com.au> wrote: > > >> In a nutshell, like all double-underscore methods, __setattr__ are for >> overriding behaviour in your own classes. With very few exceptions, you >> shouldn't need to directly call double-underscore methods (although you >> often may _write_ double-underscore methods). >> >> > I think I understand. You are saying that if I wanted to override the > normal behavior when doing something like > > p1.firstName = "Brian" > > then I'd override __setattr__()? > > But if I am doing something like creating dynamic attributes, the more > 'correct' way is to use setattr? Even though they both appear to do the > same thing, the more Pythonic way is to never directly call magic > methods (if you can help it)?
No, they don't do the same thing. The normal way of accessing an object attribute is with the dot operator: obj.name Behind the scenes, Python does a whole lot of magic to make that work. Under *normal* circumstances, when you write "obj.name" Python looks for an attribute called "name", and returns whatever it finds. The *details* of the lookup process itself can be as simple as "look in obj.__dict__" or it can be significantly more complicated if obj has slots and super- classes and properties. But don't worry about the complications, just think of "look up an attribute" as a single operation for now. What if you don't know the name of the attribute when you are writing your code, but only at runtime? You want something like this: s = "na" + "me" # We don't know this until runtime. obj.s but that doesn't work, because Python looks up an attribute called s. That's where getattr(), setattr() and delattr() come into play: you can give the name of the attribute as a string at runtime, not hard coded in your source code: getattr(obj, s) evaluates s as the string "name", then looks up the attribute called "name" just as if you had written obj.name. Now, what about __getattr__ __setattr__ and __delattr__? They too take the name of the attribute as a string, but that's about the only similarity with the non-underscore versions. They exist for a completely different reason. The underscore versions are for customizing the lookup process, not for dynamically looking up names. If your class needs to do something non- standard when you write obj.name, you might need to write methods __getattr__ etc. Regardless of whether your attribute lookup was from obj.name or from getattr(obj, "name"), when Python goes to do the actual lookup, it will call on the double-underscore versions if needed: if the __getattr__ method exists, it is ONLY called if the lookup fails; if the __getattribute__ method exists, it is called for EVERY lookup; if the __setattr__ method exists, it is called when you try to assign to an attribute; if the __delattr__ method exists, it is called when you try to delete an attribute. In a nutshell: getattr() etc. are for looking up attributes dynamically when you don't know the name of the attribute until runtime. __getattr__ etc. are for looking up attributes when you need to compute the value on the fly. (But an easier, less troublesome way of doing that is with properties.) -- Steven. -- http://mail.python.org/mailman/listinfo/python-list