On Sun, 26 Jun 2005 04:08:31 +1000, Steven D'Aprano <[EMAIL PROTECTED]> wrote:
>On Fri, 24 Jun 2005 15:47:45 -0700, James Stroud wrote: > >> On Friday 24 June 2005 05:58 am, Steven D'Aprano wrote: >>> with colour do begin >>> red := 0; blue := 255; green := 0; >>> end; >>> >>> instead of: >>> >>> colour.red := 0; colour.blue := 255; colour.green := 0; >>> >>> Okay, so maybe it is more of a feature than a trick, but I miss it and it >>> would be nice to have in Python. How do you like the following? >>> color = type('',(),{})() # an instance that will accept attributes >>> vars(color) {} The single line replacing """ with colour do begin red := 0; blue := 255; green := 0; end; """ follows: >>> vars(color).update(red=0, blue=255, green=0) which sets all the attributes: >>> vars(color) {'blue': 255, 'green': 0, 'red': 0} >>> color.blue 255 >>> color.red 0 >>> color.green 0 Of course, I defined a class on the fly above, so I could have given it defaults as class variables (using English spelling ;-) : >>> colour = type('Colour',(),dict(red=0,blue=255,green=0))() # an instance >>> with defaults >>> vars(colour) {} Which don't show up in the instance dict, but do show up as attributes: >>> colour.red 0 >>> colour.green 0 >>> colour.blue 255 Then we can update the instance dict that holds its attributes: >>> vars(colour).update(red=111,green=222,blue=333) And they show up, shadowing the class vars >>> vars(colour) {'blue': 333, 'green': 222, 'red': 111} You can do one attribute this way: >>> vars(colour).update(red='RED') >>> vars(colour) {'blue': 333, 'green': 222, 'red': 'RED'} though this is obviously more concise: >>> colour.green = 'GREEN' >>> vars(colour) {'blue': 333, 'green': 'GREEN', 'red': 'RED'} >>> The class vars are still there, even though we don't have a local name binding for the class: >>> map(vars(type(colour)).__getitem__, 'red green blue'.split()) [0, 0, 255] The instance is separate: >>> vars(colour) {'blue': 333, 'green': 'GREEN', 'red': 'RED'} We can clear those attributes from the instance dict: >>> vars(colour).clear() >>> vars(colour) {} And then they don't shadow the class vars, so getting attributes make the class vars show again: >>> [getattr(colour, c) for c in 'red green blue'.split()] [0, 0, 255] Or: >>> map(colour.__getattribute__, 'red green blue'.split()) [0, 0, 255] Actually, you could make that a few characters shorter using a temporary short name to make a kind of with inside a list comprehension: >>> [[c.red, c.green, c.blue] for c in [colour]][0] [0, 0, 255] Though list comprehensions leak bindings: >>> c <__main__.Colour object at 0x02F8FFCC> Which generator expressions don't: >>> del c >>> list(([c.red, c.green, c.blue] for c in [colour]))[0] [0, 0, 255] >>> c Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'c' is not defined Or we can get the pairs and build a dict: >>> [(c,getattr(colour, c)) for c in 'red green blue'.split()] [('red', 0), ('green', 0), ('blue', 255)] >>> dict([(c,getattr(colour, c)) for c in 'red green blue'.split()]) {'blue': 255, 'green': 0, 'red': 0} Of course, rgb is usually ordered, so why not >>> colour = type('Colour',(),dict(rgb=(0,255,0)))() # an instance with >>> default rgb >>> vars(colour) {} >>> colour.rgb (0, 255, 0) >>> colour.rgb = 111,222,333 >>> vars(colour) {'rgb': (111, 222, 333)} >>> colour.rgb (111, 222, 333) >>> type(colour).rgb (0, 255, 0) >> >> class color: # americanized >> red = 0 >> blue = 255 >> green = 0 > >The problem is, you have made colour (returning to English spelling >instead of foreign) into a class. If you need two colour variables, you >have to duplicate the code for the class (perhaps only changing the >numeric constants. You can't even make instances from the class, because >they all share the same RGB values, which is pretty useless if they are >meant to represent different colours. > > >> Less typing than pascal. > >You have missed the point. I'm not comparing Python vs Pascal for >creating records representing RBG values. I'm talking about a Pascal >feature that reduced typing by allowing you to use an implicit record. >Here is one possible way you might use such a feature as a Python idiom, >letting "with" specify an implicit object. Instead of doing this: > ># read a class attribute >print myobject.__class__.myattribute ># set an instance attribute >myobject.widget.datapoints[myobject.collector] \ >= myobject.dispatcher(myobject.widget.current_value) > >you might do this: > >with myobject: > # read a class attribute > print .__class__.myattribute > # set an instance attribute > .widget.datapoints[.collector] = .dispatcher(.widget.current_value) > def mywith(o=myobject): # read a class attribute print o.__class__.myattribute # set an instance attribute o.widget.datapoints[o.collector] = o.dispatcher(o.widget.current_value) mywith() Or if we had a lambda-replacing anonymous def permitting full suites: (def(o=myobject): # read a class attribute print o.__class__.myattribute # set an instance attribute o.widget.datapoints[o.collector] = o.dispatcher(o.widget.current_value) )() Is a one-character prefix to the dot objectionable? >> Also avoids those stupid little colons. > >Using := and = for assignment and equality is precisely as stupid as using >= and == for assignment and equality. Perhaps less stupid: why do we use >== for equals, but not ++ for plus and -- for minus? > I agree, but I think := would be nice in python for RE-binding an existing binding, wherever it is seen from the local context. Thus you could write def foo(): x:=123 and x = 456 def bar(): x = 789 foo() # finds and rebinds local x print x bar() # -> 123 print x # -> 456 foo() # finds and rebinds the global x print x # -> 123 but del x foo() #-> NameError exception, can't find any x to rebind hm, wandered a bit OT there, ;-/ Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list