On 28 Nov 2005 14:48:35 GMT, Duncan Booth <[EMAIL PROTECTED]> wrote: >Antoon Pardon wrote: > >>> >>> def func(x): >>> ... if x in [1,3,5,7,8]: >>> ... print 'x is really odd' >>> ... >>> >>> dis.dis(func) >>> ... >>> 3 20 LOAD_FAST 0 (x) >>> 23 LOAD_CONST 2 (1) >>> 26 LOAD_CONST 3 (3) >>> 29 LOAD_CONST 4 (5) >>> 32 LOAD_CONST 5 (7) >>> 35 LOAD_CONST 6 (8) >>> 38 BUILD_LIST 5 >>> 41 COMPARE_OP 6 (in) >> >> I'm probably missing something, but what would be the problem if this >> list was created during compile time? > >Not much in this particular instance. 'x in aList' is implemented as >aList.__contains__(x), so there isn't any easy way to get hold of the >list[*] and keep a reference to it. On the other hand: > >def func(x): > return x + [1, 3, 5, 7, 8] > >we could pass in an object x with an add operator which gets hold of its >right hand operand and mutates it. > >So the problem is that we can't just turn any list used as a constant into >a constant list, we need to be absolutely sure that the list is used only >in a few very restricted circumstances, and since there isn't actually any >benefit to using a list here rather than a tuple it hardly seems >worthwhile. > >There might be some mileage in compiling the list as a constant and copying >it before use, but you would have to do a lot of timing tests to be sure. > >[*] except through f.func_code.co_consts, but that doesn't count.
If we had a way to effect an override of a specific instance's attribute accesses to make certain attribute names act as if they were defined in type(instance), and if we could do this with function instances, and if function local accesses would check if names were one of the ones specified for the function instance being called, then we could define locally named constants etc like properties. The general mechanism would be that instance.__classvars__ if present would make instance.x act like instance.__classvars__['x'].__get__(instance). IOW as if descriptor access for descriptors defined in type(instance). Thus if you wrote instance.__classvars__ = dict(t=property(lambda self, t=__import__('time').ctime:t())) then that would make instance.t act as if you had assigned the property to type(instance).t -- which is handy for types whose instances don't let you assign to type(instance). This gets around to instances of the function type. Let's say we had a decorator defined like def deco(f): f.__classvars__ = dict(now= property(lambda f, t=__import__('time').ctime:t())) return f then if function local name access acted like self.name access where self was the function instance[1], and type(self) was checked for descriptors, meaning in this case foo.__classvars__ would get checked like type(self).__dict__, then when you wrote @deco def foo(): print now # => print foo.__classvars__['now'].__get__(foo, type(foo)) # (i.e., as if property defined as type(self) attribute where self is foo # but not accessed via global name as in above illustrative expression) now = 42 # => AttributeError: can't set attribute This would also let you add properties to other unmodifiable types like the module type you see via type(__import__('anymod')), e.g., import foomod foomod.__classvars__ = dict(ver=property(lambda mod: '(Version specially formatted): 'r'%mod.version) # (or foomod could define its own __classvars__) then foomod.ver would act like a property defined in the __classvars__ - extended class variable namespace, and return what a normal property would. Plain functions in foomod.__classvars__ would return bound methods with foomod in "self" position, so you could call graphics.draw(args) and know that draw if so designed could be defined as def draw(mod, *args): ... Just another idea ;-) [1] actually, during a function call, the frame instance if probably more like the "self", but let's say the name resolution order for local access extends to foo.__classvars__ somethow as if that were an overriding front end base class dict of the mro chain. Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list