OT: Re: Just took a look in the perl newsgroup....
Bengt Richter
bokr at oz.net
Thu May 29 12:34:57 EDT 2003
On Wed, 28 May 2003 23:10:57 -0600, Steven Taschuk <staschuk at telusplanet.net> wrote:
>Quoth Bengt Richter:
>> On Wed, 28 May 2003 14:17:37 -0600, Steven Taschuk <staschuk at telusplanet.net> wrote:
>> >Quoth Bengt Richter:
> [...]
>> >> ## a local case structure with rebinding in local scope
>> >> try: raise `x`
>> >> except '1':
> [...]
>> >Inherently fragile due to reliance on interning of repr(x). Won't
>> >work at all if/when string exceptions go away.
>>
>> Which version requires interning of repr(x)? It looks like the code is less
>> efficient than the corresponding if/elif/else code, however.
>
>It is the quoted try/except version that relies on interning. For
>example:
>
> >>> x = 12345
> >>> try:
> ... raise `x`
> ... except '12345':
> ... print 'case 12345'
> ...
> Traceback (most recent call last):
> File "<stdin>", line 2, in ?
> 12345
>
>Because string exceptions are caught by identity, not equality,
>and, as it happens, '12345' doesn't get interned.
ITYM `12345` doesn't get "interned" (neither does '1234'+'5')
>
> [...]
>> class Switch(object):
>> def __init__(self, *caseNames):
>> for name in caseNames:
>> if not isinstance(name,str): name = `name`
>> exec ('class _%s(Exception):pass'%name) in self.__dict__
>> del self.__dict__['__builtins__']
>> def __call__(self, name):
>> raise getattr(self, '_%s'%name, ValueError)
>
>Yikes again. This one depends on repr(x) fitting into identifier
>syntax, so I couldn't use it with tuples (to pick one example of
>many).
Sheesh ;-)
====< caseswitch.py >=============================================
class Switch(object):
def __init__(self, *caseNames):
self.halias = {}
for name in caseNames:
try:
hname = '_%X' % hash(name)
except TypeError:
raise ValueError, 'Switch requires hashable case values'
exec ('class %s(Exception):pass'%hname) in self.__dict__
self.halias[name] = getattr(self, hname)
del self.__dict__['__builtins__']
def __call__(self, name):
raise self.halias.get(name, ValueError)
def __getitem__(self, iargs):
if not isinstance(iargs, tuple): iargs = (iargs,)
return tuple([self.halias.get(i, '') for i in iargs])
==================================================================
====< zcase.py >==================================================
from caseswitch import Switch
CASES = (1, 2, 'foo', ('a', 'tuple'), 4, 5)
case = switch = Switch(*CASES)
def f(x):
def g(x):
inner_var = 5
## a local case structure with rebinding in local scope
try: switch(x)
except case[1]:
# case code in same scope as case
inner_var = '<<value bound in scope of "case" 1)>>'
except case[2]:
inner_var = '<<value bound in scope of "case" 2>>'
except case['foo', 4 ,5]:
inner_var = '<<value bound in scope of "case" foo, 4, 5>>'
except case[('a', 'tuple'),]:
inner_var = '''<<value bound in scope of "case" ('a', 'tuple')>>'''
except:
inner_var = '<<value bound in scope of "case" default>>'
print 'inner_var as seen at end of "case":', inner_var
g(x)
for i in CASES + (0,): print '---- f(%r) -----'%(i,); f(i)
==================================================================
[ 9:31] C:\pywk\clp>zcase.py
---- f(1) -----
inner_var as seen at end of "case": <<value bound in scope of "case" 1)>>
---- f(2) -----
inner_var as seen at end of "case": <<value bound in scope of "case" 2>>
---- f('foo') -----
inner_var as seen at end of "case": <<value bound in scope of "case" foo, 4, 5>>
---- f(('a', 'tuple')) -----
inner_var as seen at end of "case": <<value bound in scope of "case" ('a', 'tuple')>>
---- f(4) -----
inner_var as seen at end of "case": <<value bound in scope of "case" foo, 4, 5>>
---- f(5) -----
inner_var as seen at end of "case": <<value bound in scope of "case" foo, 4, 5>>
---- f(0) -----
inner_var as seen at end of "case": <<value bound in scope of "case" default>>
Note that I had to make a choice re the tuple ambiguity. I.e., case[('a', 'tuple'),]
would be the same as case['a', 'tuple'] if you leave out the comma, which would specify
two cases instead of a single tuple case.
Of course this is not terribly efficient code compared to the corresponding if/elif/else chain ;-)
I'm not recommending anyone adopt use of caseswitch.py, but IMO it reads fairly well
and does a lot of what you'd like a real case mechanism for python to do ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list