Python syntax in Lisp and Scheme

Bengt Richter bokr at oz.net
Sun Oct 5 04:27:39 EDT 2003


On Sat, 04 Oct 2003 19:48:54 GMT, Alex Martelli <aleax at aleax.it> wrote:

>Bengt Richter wrote:
>   ...
>> I like the Bunch class, but the name suggests vegetables to me ;-)
>
>Well, I _like_ vegetables...
>
>> BTW, care to comment on a couple of close variants of Bunch with
>> per-object class dicts? ...
>> 
>>     def mkNSC(**kwds): return type('NSC', (), kwds)()
>
>Very nice (apart from the yecchy name;-).
>
>> or, stretching the one line a bit to use the instance dict,
                                     ^^^^^^^^^^^^^^^^^^^^^^^^
>> 
>>     def mkNSO(**kwds): o=type('NSO', (), {})(); o.__dict__.update(kwds);
>>     return o
>
>I don't see the advantage of explicity using an empty dict and then
>updating it with kwds, vs using kwds directly.
          ^^-- not the same dict, as you've probably thought of by now, but
glad to see I'm not the only one who misread that ;-)

I.e., as you know, the contents of the dict passed to type is used to update the fresh class dict.
It's not the same mutable dict object, (I had to check)

 >>> d={'foo':'to check id'}
 >>> o = type('Using_d',(),d)()
 >>> d['y']='a y value'
 >>> o.__class__.__dict__.keys()
 ['__dict__', '__module__', 'foo', '__weakref__', '__doc__']

(If d were serving as class dict, IWT y would have shown up in the keys).

and also the instance dict is only a glimmer in the trailing ()'s eye
at the point the kwd dict is being passed to type ;-)

 >>> def mkNSC(**kwds): return type('NSC', (), kwds)()
 ...
 >>> def mkNSO(**kwds): o=type('NSO', (), {})(); o.__dict__.update(kwds); return o
 ...
 >>> class Bunch(object):
 ...     def __init__(self, **kw): self.__dict__.update(kw)
 ...
 >>> for inst in [mk(x=mk.__name__+'_x_value') for mk in (mkNSC, mkNSO, Bunch)]:
 ...     cls=inst.__class__; classname = cls.__name__
 ...     inst.y = 'added %s instance attribute y'% classname
 ...     print '%6s:  instance dict: %r' %(classname, inst.__dict__)
 ...     print '%6s class dict keys: %r' %('', cls.__dict__.keys())
 ...     print '%6s instance attr x: %r' %( '', inst.x)
 ...     print '%6s instance attr y: %r' %( '', inst.y)
 ...     print '%6s class var x    : %r' %( '', cls.__dict__.get('x','<x not there>'))
 ...     print
 ...
    NSC:  instance dict: {'y': 'added NSC instance attribute y'}
        class dict keys: ['__dict__', 'x', '__module__', '__weakref__', '__doc__']
        instance attr x: 'mkNSC_x_value'
        instance attr y: 'added NSC instance attribute y'
        class var x    : 'mkNSC_x_value'
 
    NSO:  instance dict: {'y': 'added NSO instance attribute y', 'x': 'mkNSO_x_value'}
        class dict keys: ['__dict__', '__module__', '__weakref__', '__doc__']
        instance attr x: 'mkNSO_x_value'
        instance attr y: 'added NSO instance attribute y'
        class var x    : '<x not there>'
 
  Bunch:  instance dict: {'y': 'added Bunch instance attribute y', 'x': 'Bunch_x_value'}
        class dict keys: ['__dict__', '__module__', '__weakref__', '__doc__', '__init__']
        instance attr x: 'Bunch_x_value'
        instance attr y: 'added Bunch instance attribute y'
        class var x    : '<x not there>'
 
Note where x and y went. So NSC is nice and compact, but subtly different. E.g.,

 >>> nsc = mkNSC(x='really class var')
 >>> nsc.x
 'really class var'
 >>> del nsc.x
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 AttributeError: 'NSC' object attribute 'x' is read-only

(Is that's a new message with 2.3?)

 >>> del nsc.__class__.x
 >>> nsc.x
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 AttributeError: 'NSC' object has no attribute 'x'

NS was for Name Space, and C vs O was for Class vs obj dict initialization ;-)

Regards,
Bengt Richter




More information about the Python-list mailing list