[Tutor] pass tuples to user defined function(beginner)
Peter Otten
__peter__ at web.de
Tue Nov 29 13:38:32 CET 2011
Steven D'Aprano wrote:
> bob gailer wrote:
>> On 11/28/2011 12:47 PM, James Reynolds wrote:
>>>
>>>
>>> On Mon, Nov 28, 2011 at 12:32 PM, Mayo Adams <mayoadams at gmail.com
>>> <mailto:mayoadams at gmail.com>> wrote:
>>>
>>> I am trying to pass a set of tuple strings from a file to a
>>> function I
>>> have defined. Each tuple is on a separate line, and looks something
>>> like this:
>>> ('note',2048)
>>>
>>
>> As already pointed out - this is a string (a representation of a tuple),
>> not a tuple.
>>
>> Your code must parse the string to extract the string representations of
>> the values, then convert as needed to the desired Python values.
>>
>> Tasks like this are not trivial.
>
>
> In general, parsing can be a hard problem. In this case though, it is easy
> to solve 95% of the problem with a hand-built converter, which may be good
> enough.
>
> def strto2tuple(s):
> """Convert a string like "('abc', 42)" to a tuple with two items."""
> # Ignore leading and trailing whitespace.
> s = s.strip()
> # Check for round brackets (parentheses), and remove them.
> if s[0] != '(' or s[-1] != ')':
> raise ValueError('malformed string, missing ( or )')
> s = s[1:-1]
> # Split the string into exactly two pieces.
> # FIXME this assumes that the first item contains no commas.
> items = s.split(',')
> n = len(items)
> if n != 2:
> raise ValueError('expected exactly two items but found %d' % n)
> a, b = items
> # Ignore spaces around each item, e.g. ( 'abc' , 42 ) => ('abc', 42)
> a = a.strip()
> b = b.strip()
> # Make sure that the first item looks like a string.
> quotes = '"\'' # FIXME no support for triple quotes yet, or raw
> strings. assert len(quotes) == 2
> for q in quotes:
> if a.startswith(q) and a.endswith(q):
> # Don't include the delimiter quotes in the string.
> a = a[1:-1]
> break
> else:
> # This executes if we don't hit a break in the for loop.
> raise ValueError('mismatched or missing quotes')
> assert isinstance(a, str)
> # Make sure the second item is an integer.
> b = int(b, 0) # Support hex and octal formats too.
> return (a, b) # And return a real tuple.
>
>
> This untested function will convert strings in a file like these:
>
> ( 'fe', 1)
> ( 'fi' ,2 )
> ("fo",0x03)
> ( "fum" , 4 )
>
> into proper tuples with a string and a number. Notice that we allow the
> user to be sloppy with spaces, but we are strict about quotation marks and
> brackets.
>
>
> Our converter function is both a little too strict (e.g. it forbids the
> user from including triple-quoted strings) and a little too lax (e.g. it
> allows malformed strings like ''abc'). You might not care about these
> weaknesses. If you do, you need to move up to a real parser, which is
> significantly more complex.
And here's the lazy-bastard version:
>>> lines = """( 'fe', 1)
... ( 'fi' ,2 )
... ("fo",0x03)
... ( "fum" , 4 )
... ("gvn", __import__("os").remove("that could be your valuable data.txt"))
... """.splitlines()
>>> import ast
>>> for line in lines:
... print ast.literal_eval(line.strip())
...
('fe', 1)
('fi', 2)
('fo', 3)
('fum', 4)
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/usr/lib/python2.6/ast.py", line 68, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python2.6/ast.py", line 58, in _convert
return tuple(map(_convert, node.elts))
File "/usr/lib/python2.6/ast.py", line 67, in _convert
raise ValueError('malformed string')
ValueError: malformed string
More information about the Tutor
mailing list