On 20 Sep 2005 12:31:19 -0700, "ago" <[EMAIL PROTECTED]> wrote:
>Is it possible to have a default value associated python objects? I.e. >to flag an attribute in such a way that the assignment operator for the >object returns the default attribute instead of the object itself, but >calls to other object attributes are properly resolved? (I don't think >so, but I am not sure) > >Example: > >class obj(object): > x=1 #assume x is somehow made into a default value > y=2 > >Ideally this should be the result: > >myobj=obj() normal >print myobj #-> 1 expression myobj interpreted as myobj.x? >print myobj.y #-> 2 normal >x=myobj normal, because expression myobj in this context of immediate assignment does not mean myobj.x? >print x #-> 1 expression x is the same as expression myobj, which is intrpreted as myobj.x (alias x.x) if not assigned? >print type(x) #int ditto > If you wanted to have this effect inside a function, you could write a byte-code-munging decorator to evaluate selected_name as selected_name.selected_attr except where assigning to an alias name is all that a statement does, as in x = myobj. But what if you actually wanted to pass the object per se somewhere, or return it from a function? Maybe you could have the expression myobj.x mean the normal myobj, and vice versa in a kind of terrible symmetry ;-) Then usage might be something like @agostino_effect(myobj='x') # eval myobj as myobj.x def foo(): myobj=obj() print myobj #-> 1 print myobj.y #-> 2 x = myobj print x #-> 1 return x, myobj, x.y, myobj.x # with .x having "symmetrically-other" effect ;-) xval, myobjval, x_dot_y_val, myobj_per_se = foo() # assignment from function is not interfered with myobj_per_se.y #->2 myobj_per_se #-> 1 myobj_val.y -> AttributeError: 'int' object has no attribute 'y' I'm not suggesting this is a good way to go forward, I am just playing with the feasibility of doing what you want, even if it's not good for you ;-) I suspect there is a better way, but it wouldn't be that hard to do the above, as you can see from the code of foo that the agostino_effect decorator would be modifying: >>> def foo(): ... myobj=obj() ... print myobj #-> 1 ... print myobj.y #-> 2 ... x = myobj ... print x #-> 1 ... return x, myobj, x.y, myobj.x # with .x having "symmetrically-other" effect ;-) ... >>> import dis >>> dis.dis(foo) 2 0 LOAD_GLOBAL 0 (obj) 3 CALL_FUNCTION 0 6 STORE_FAST 0 (myobj) 3 9 LOAD_FAST 0 (myobj) Here you'd notice that the next instruction was not STORE_FAST so you'd insert a LOAD_ATTR 1 (x) similar to the .y access below 12 PRINT_ITEM 13 PRINT_NEWLINE 4 14 LOAD_FAST 0 (myobj) 17 LOAD_ATTR 2 (y) Here you'd notice the above wasn't LOAD_ATTR (x) (which you'd otherwise have to remove for object-per-se) 20 PRINT_ITEM 21 PRINT_NEWLINE 5 22 LOAD_FAST 0 (myobj) 25 STORE_FAST 1 (x) This you notice is an immediate assignment and you leave it alone, and note the alias 6 28 LOAD_FAST 1 (x) Here you notice the alias and insert LOAD_ATTR 1 (x) as before with myobj 31 PRINT_ITEM 32 PRINT_NEWLINE 7 33 LOAD_FAST 1 (x) insert LOAD_ATTR 1 (x) again 36 LOAD_FAST 0 (myobj) insert LOAD_ATTR 1 (x) again 39 LOAD_FAST 1 (x) 42 LOAD_ATTR 2 (y) other attribute, no change to above byte code 45 LOAD_FAST 0 (myobj) 48 LOAD_ATTR 3 (x) anti-attribute, remove above byte code 51 BUILD_TUPLE 4 54 RETURN_VALUE You might want to do the same for LOAD_GLOBAL/STORE_GLOBAL, and STORE_DEREF/LOAD_DEREF, I don't know. But it wouldn't be a big deal to get a hack working. Thorough testing is another matter, not to mention justifying it ;-) Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list