beginner question: extending python types

Bengt Richter bokr at oz.net
Thu May 16 14:46:56 EDT 2002


On Thu, 16 May 2002 13:30:51 GMT, "Terry Reedy" <tjreedy at udel.edu> wrote:

>> > > * Uwe Mayer
>> > > |>I found Python lacking the type of a "set". i.e. an unordered
>list.
>
>> > Jeremy Yallop wrote:
>> > > Use a dictionary, with the same value (1) for every key.
>
>> Bob Horvath <usenet at horvath.com> writes:
>> > Is there any significance to the value 1?
>
>"Michael Hudson" <mwh at python.net> wrote in message
>> In this context, no.  It might be a tad confusing to have something
>> that was false, so None, 0 and () might be bad choices.  But I don't
>> think there's a good reason.
>
>For choosing between 0 and 1, confusion is the only reason to choose
>1.  However, in the current C implementation, there are reasons to
>reject the others.  'Small' ints are preallocated and handled
>specially (more efficiently) by the compiler.  A set with 100000
>members would have 100000 pointers to the same preallocated object.
>The same would be true for None, but 'None' would be looked up in both
>module and builtin dicts 100000 times.  '{}' or '()' would generate
>100000 empty and useless objects.
>
>If/when None is made a keyword, it *might* become the more efficient
>choice since it would then be special-cased even earlier than 0/1.
>

I was going to post something a lot like the above (until I started
generating examples ;-) ...

You may or may not get multiple objects for the dummy directory entry value.
E.g., if you are using a constant literal to set the values in one statement,
the code generated for that statement is going to use the same constant.
(Multiple identical literals in the same scope also appear to share the same
value object, as one would hope, but I don't know if that is a bullet proof
assumption).

 >>> d={}
 >>> for x in 'abcd': d[x]=1234
 ...
 >>> map(id,d.values())
 [7952224, 7952224, 7952224, 7952224]

On the other hand, if the value is generated dynamically or in a
different scope, as opposed to a constant literal, then
(note the first three get the same identical value vs the others):

 >>> d={'a':1234,'b':1234,'c':(lambda x:x)(1234),'d':(lambda:1234)(),
 ...    'e':1233+1,'f':int('1234'),'g':eval('1234')}
 >>> map(id,[d[x] for x in 'abcdefg'])
 [8203428, 8203428, 8203428, 8203440, 8203356, 8203452, 8203692]

Or, to make it clearer:

 >>> dtext="""{'a':1234,'b':1234,'c':(lambda x:x)(1234),'d':(lambda:1234)(),
 ...    'e':1233+1,'f':int('1234'),'g':eval('1234')}""".split(',')
 >>> for k in 'abcdefg': print k,d[k],id(d[k]),'<=',dtext[ord(k)-ord('a')].strip()
 ...
 a 1234 8203428 <= {'a':1234
 b 1234 8203428 <= 'b':1234
 c 1234 8203428 <= 'c':(lambda x:x)(1234)
 d 1234 8203440 <= 'd':(lambda:1234)()
 e 1234 8203356 <= 'e':1233+1
 f 1234 8203452 <= 'f':int('1234')
 g 1234 8203692 <= 'g':eval('1234')}

Running the same test with 1, you get a reference to the magically cached value:

 >>> d={'a':1,'b':1,'c':(lambda x:x)(1),'d':(lambda:1)(),
 ...    'e':0+1,'f':int('1'),'g':eval('1')}
 >>> map(id,[d[x] for x in 'abcdefg'])
 [7952992, 7952992, 7952992, 7952992, 7952992, 7952992, 7952992]
 >>> dtext=""" 'a':1,'b':1,'c':(lambda x:x)(1),'d':(lambda:1)(),
 ...    'e':0+1,'f':int('1'),'g':eval('1')""".split(',')
 >>> for k in 'abcdefg': print k,d[k],id(d[k]),'<=',dtext[ord(k)-ord('a')].strip()
 ...
 a 1 7952992 <= 'a':1
 b 1 7952992 <= 'b':1
 c 1 7952992 <= 'c':(lambda x:x)(1)
 d 1 7952992 <= 'd':(lambda:1)()
 e 1 7952992 <= 'e':0+1
 f 1 7952992 <= 'f':int('1')
 g 1 7952992 <= 'g':eval('1')

On the other hand, as the 'c' examples show, you should be able to make up
any value and re-use it as a single value by referring to it by name:

 >>> a_value=('clunky','generated','value',123*10+4)
 >>> id(a_value)
 8000816
 >>> d={}
 >>> d[1]=a_value
 >>> d[2]=a_value
 >>> d[3]=a_value
 >>> map(id,[d[x] for x in 1,2,3])
 [8000816, 8000816, 8000816]

So the memory explosion is not a foregone thing. (Speed of access is related
and also varies, depending).

Regards,
Bengt Richter



More information about the Python-list mailing list