Re: [Python-ideas] List Revolution

Here is my proposal which hopefully would settle the issue to rest class List(list): """ >>> a=List() >>> for i in range(100000): a.append(i) >>> print a.first 0 >>> print a.second 1 >>> print a.third 2 >>> print a.twentieth 19 >>> print a.twentysecond 21 >>> print a.onehundredthirtyfifth 134 >>> print a.onethousandfivehundredandthirtyeighth 1537 """ def __getattr__(self,name): import re if name.endswith('first'): name = name[:-5]+'one' elif name.endswith('second'): name = name[:-6]+'two' elif name.endswith('third'): name = name[:-5]+'three' elif name.endswith('fth'): name = name[:-3]+'ve' elif name.endswith('hth'): name = name[:-3]+'th' elif name.endswith('ieth'): name = name[:-4]+'y' elif name.endswith('th'): name = name[:-2] subs = { 'one':'+1', 'two':'+2', 'three':'+3', 'four':'+4', 'five':'+5', 'six':'+6', 'seven':'+7', 'eigth':'+8', 'nine':'+9', 'ten':'+10', 'eleven':'+11', 'twelve':'+12', 'thirteen':'+13', 'fourteen':'+14', 'fiftheen':'+15', 'sixteen':'+16', 'seventeen':'+17', 'eighteen':'+18', 'nineteen':'+19', 'ten':'+10', 'twenty':'+20', 'thirty':'+30', 'fourty':'+40', 'fifthy':'+50', 'sixty':'+60', 'seventy':'+70', 'eighty':'+80', 'ninety':'+90', 'hundred':')*100+(', 'thousand':')*1000+(', 'million':')*1000000+(', 'billion':')*1000000000+(', 'trillion':')*100000000000+(', 'and',''} for key,value in subs.items(): name = name.replace(key,value) if '(' in name: name='('+name+')' name.replace('()','1') if not re.compile('[\d\+\*\(\)]+').match(name): return AttributeError try: return self[eval(name)-1] except: raise AttributeError I would like to stress that the use of eval in this case is safe as the expression is first validated against a regex. Massimo

So you are saying that with my code (which was meant as joke not as serious proposal) you can do a = List() getattr(a,'(2**1024)**(2**1024)') and that is a vulnerability? But you can already do a = [] a[(2**1024)**(2**1024)] or simply (2**1024)**(2**1024) The ability write insane code is not a vulnerability. It is a feature. Exposing that to users may constitute a vulnerability. Massimo On Sep 11, 2011, at 5:46 AM, Dag Odenhall wrote:

I thought we were all just having a little bit of fun with what's obviously the least-likely-to-be-accepted proposal to have hit python-ideas in a long time; and now I see serious questions about it on Twitter and Quora... Time to start adding smileys to all posts! :-) (Though seriously, Massimo, you should be able to implement the same idea without using eval() at all.) --Guido On Sat, Sep 10, 2011 at 10:50 AM, Massimo Di Pierro <massimo.dipierro@gmail.com> wrote:
-- --Guido van Rossum (python.org/~guido)

Of course. It was a proof of concept. Here is with an inline parser: class List(list): """ >>> a=List() >>> for i in range(100000): a.append(i) >>> print a.first 0 >>> print a.second 1 >>> print a.third 2 >>> print a.twentieth 19 >>> print a.twentysecond 21 >>> print a.onehundredthirtyfifth 134 >>> print a.onethousandfivehundredthirtyeighth 1537 """ def __getattr__(self,name): if name.endswith('first'): name = name[:-5]+'one' elif name.endswith('second'): name = name[:-6]+'two' elif name.endswith('third'): name = name[:-5]+'three' elif name.endswith('fth'): name = name[:-3]+'ve' elif name.endswith('hth'): name = name[:-3]+'th' elif name.endswith('ieth'): name = name[:-4]+'y' elif name.endswith('th'): name = name[:-2] subs = [ ("eleven","+11"), ("twelve","+12"), ("thirteen","+13"), ("fourteen","+14"), ("fiftheen","+15"), ("sixteen","+16"), ("seventeen","+17"), ("eighteen","+18"), ("nineteen","+19"), ("ten","+10"), ("twenty","+20"), ("thirty","+30"), ("fourty","+40"), ("fifty","+50"), ("sixty","+60"), ("seventy","+70"), ("eighty","+80"), ("ninety","+90"), ("one","+1"), ("two","+2"), ("three","+3"), ("four","+4"), ("five","+5"), ("six","+6"), ("seven","+7"), ("eigth","+8"), ("nine","+9"), ("ten","+10"), ("hundred",")*100+("), ("thousand",")*1000+("), ("million",")*1000000+("), ("billion",")*1000000000+("), ("trillion",")*100000000000+("), ("and","")] for key,value in subs: name = name.replace(key,value) if '(' in name: name='('+name+')' name.replace('()','1') ## parser import re tokenizer = re.compile('\+|\(\+|\(|\)|\*|[\d]+') stack = [0] while name: token = tokenizer.match(name) if not token: raise AttributeError if token.group() in ('(','(+'): stack.append(0) if token.group().isdigit(): stack.append(int(token.group())) if token.group() in ')+' and len(stack)>1: stack[-2:]=[stack[-1]+stack[-2]] if token.group()=='*': name = name[1:] token = tokenizer.match(name) if not token or not token.group().isdigit(): raise AttrbuteError stack[-1:]=[stack[-1]*int(token.group())] name = name[token.end():] number = sum(stack) ## end parser try: return self[number-1] except: raise IndexError On Sep 10, 2011, at 1:00 PM, Guido van Rossum wrote:

Not to open a can of worms but why not use eval in this example? It is faster. It is 5x more compact. It allows me to take advantage of the Python parser instead of reinventing the wheel. It is less error prone and easier to understand. It is a python keyword. # with eval if not re.compile('^[\*\+\(\)\d]+$').match(name): raise AttributeError try: number = eval(name) except: raise AttributeError # without eval tokenizer = re.compile('\+|\(\+|\(|\)|\*|[\d]+') stack = [0] while name: token = tokenizer.match(name) if not token: raise AttributeError elif token.group() in ('(','(+'): stack.append(0) elif token.group().isdigit(): stack.append(int(token.group())) elif token.group() in ')+' and len(stack)>1: stack[-2:]=[stack[-1]+stack[-2]] elif token.group()=='*': name = name[1:] token = tokenizer.match(name) if not token or not token.group().isdigit(): raise AttrbuteError stack[-1:]=[stack[-1]*int(token.group())] name = name[token.end():] number = sum(stack) Massimo On Sep 10, 2011, at 1:00 PM, Guido van Rossum wrote:

So you are saying that with my code (which was meant as joke not as serious proposal) you can do a = List() getattr(a,'(2**1024)**(2**1024)') and that is a vulnerability? But you can already do a = [] a[(2**1024)**(2**1024)] or simply (2**1024)**(2**1024) The ability write insane code is not a vulnerability. It is a feature. Exposing that to users may constitute a vulnerability. Massimo On Sep 11, 2011, at 5:46 AM, Dag Odenhall wrote:

I thought we were all just having a little bit of fun with what's obviously the least-likely-to-be-accepted proposal to have hit python-ideas in a long time; and now I see serious questions about it on Twitter and Quora... Time to start adding smileys to all posts! :-) (Though seriously, Massimo, you should be able to implement the same idea without using eval() at all.) --Guido On Sat, Sep 10, 2011 at 10:50 AM, Massimo Di Pierro <massimo.dipierro@gmail.com> wrote:
-- --Guido van Rossum (python.org/~guido)

Of course. It was a proof of concept. Here is with an inline parser: class List(list): """ >>> a=List() >>> for i in range(100000): a.append(i) >>> print a.first 0 >>> print a.second 1 >>> print a.third 2 >>> print a.twentieth 19 >>> print a.twentysecond 21 >>> print a.onehundredthirtyfifth 134 >>> print a.onethousandfivehundredthirtyeighth 1537 """ def __getattr__(self,name): if name.endswith('first'): name = name[:-5]+'one' elif name.endswith('second'): name = name[:-6]+'two' elif name.endswith('third'): name = name[:-5]+'three' elif name.endswith('fth'): name = name[:-3]+'ve' elif name.endswith('hth'): name = name[:-3]+'th' elif name.endswith('ieth'): name = name[:-4]+'y' elif name.endswith('th'): name = name[:-2] subs = [ ("eleven","+11"), ("twelve","+12"), ("thirteen","+13"), ("fourteen","+14"), ("fiftheen","+15"), ("sixteen","+16"), ("seventeen","+17"), ("eighteen","+18"), ("nineteen","+19"), ("ten","+10"), ("twenty","+20"), ("thirty","+30"), ("fourty","+40"), ("fifty","+50"), ("sixty","+60"), ("seventy","+70"), ("eighty","+80"), ("ninety","+90"), ("one","+1"), ("two","+2"), ("three","+3"), ("four","+4"), ("five","+5"), ("six","+6"), ("seven","+7"), ("eigth","+8"), ("nine","+9"), ("ten","+10"), ("hundred",")*100+("), ("thousand",")*1000+("), ("million",")*1000000+("), ("billion",")*1000000000+("), ("trillion",")*100000000000+("), ("and","")] for key,value in subs: name = name.replace(key,value) if '(' in name: name='('+name+')' name.replace('()','1') ## parser import re tokenizer = re.compile('\+|\(\+|\(|\)|\*|[\d]+') stack = [0] while name: token = tokenizer.match(name) if not token: raise AttributeError if token.group() in ('(','(+'): stack.append(0) if token.group().isdigit(): stack.append(int(token.group())) if token.group() in ')+' and len(stack)>1: stack[-2:]=[stack[-1]+stack[-2]] if token.group()=='*': name = name[1:] token = tokenizer.match(name) if not token or not token.group().isdigit(): raise AttrbuteError stack[-1:]=[stack[-1]*int(token.group())] name = name[token.end():] number = sum(stack) ## end parser try: return self[number-1] except: raise IndexError On Sep 10, 2011, at 1:00 PM, Guido van Rossum wrote:

Not to open a can of worms but why not use eval in this example? It is faster. It is 5x more compact. It allows me to take advantage of the Python parser instead of reinventing the wheel. It is less error prone and easier to understand. It is a python keyword. # with eval if not re.compile('^[\*\+\(\)\d]+$').match(name): raise AttributeError try: number = eval(name) except: raise AttributeError # without eval tokenizer = re.compile('\+|\(\+|\(|\)|\*|[\d]+') stack = [0] while name: token = tokenizer.match(name) if not token: raise AttributeError elif token.group() in ('(','(+'): stack.append(0) elif token.group().isdigit(): stack.append(int(token.group())) elif token.group() in ')+' and len(stack)>1: stack[-2:]=[stack[-1]+stack[-2]] elif token.group()=='*': name = name[1:] token = tokenizer.match(name) if not token or not token.group().isdigit(): raise AttrbuteError stack[-1:]=[stack[-1]*int(token.group())] name = name[token.end():] number = sum(stack) Massimo On Sep 10, 2011, at 1:00 PM, Guido van Rossum wrote:
participants (6)
-
Christopher King
-
Dag Odenhall
-
Devin Jeanpierre
-
Guido van Rossum
-
Massimo Di Pierro
-
Stefan Behnel