Tuesday, March 18, 2008

Python rocks!

Ok... it still sucks that I can't do something as simple as make a PullChar function the way I want... but at least I can do a hack thanks to Albert Sweigart and his quick reply to my earlier post today.

I always end up implementing the same library of things when I want to handle text... and this won't be an exception.

I've got a weird set of text (.pto files from Hugin) that I want to play with... they don't follow the normal python conventions for data because the program is written in C++ (I think)...

I need functions that can PULL text off of a buffer... and it looks like I'll be using the workaround to get the job done. My other alternative is something like writing a class to handle strings... which seems very weird to me, considering strings are built in.

Oh well... there's lots to like about python... but lack of variable parameters is something I'm really going to miss.


Albert Sweigart said...

Python also supports this. Just use this prototype:

def spam(eggs, *args, *kwargs):
    print eggs
    print args
    print kwargs

Then a call like this...

spam('scrambled', 'info', 'moreinfo', foo='bar')

...will make the function display this:

('info', 'moreinfo')
{'foo': 'bar'}

The one-asterisk is used for any excess arguments passed to the function (these values are in a tuple). The two-asterisk are for any keyword arguments the caller uses (these values are in a dictionary).

I like it. It really is the simplest way I can think of implementing such a scheme.

Adam said...

Your example has a spelling error.

def spam(eggs, *args, **kwargs):
print eggs
print args
print kwargs

Hope thus hekos,

Anonymous said...

To Albert:
I think we still hasn't understood that strings are an immutable type, and that what he meant to say with variable parameters, was "by reference" so that if he modifies the paramenter he would be modifying the reference...

To Mike:
mutable vs immutable types can be a bit tricky at first, try reading more about it in the python docs.

helium said...

WTF? Python has no variable parameters? This has nothing to do with the problem of immutable strings.
A string is immutable. It can't be changed. Once you've created a string it will be allways the same string.
Lists ar mutable. So if you want to change a part of a string (mutate it) convert it to a list.

Anonymous said...

The right way in Python to pull text from a buffer is probably to use a file-like object... Take a look at the StringIO/cStringIO packages in the documentation.

from cStringIO import StringIO

buf = StringIO("letters")
while True:
    c = buf.read(1)
    if not c:
    print c

Alternatively, you might look at generators. Here's a generator that returns just the consonants in a string:

def just_consonants(s):
    for c in s:
        if c.lower() not in 'aeiou':
            yield c

for c in just_consonants("letters"):
    print c

You can use this to sequentially parse and return whole tokens from a string, if desired.

When parsing text files, I find it easiest to parse by line, then split the line by whitespace -- not always the correct thing to do, but good enough in most cases. To print the control points in your hugin .pto file, for instance:

f = file('hugin.pto')
for line in f:
    if line.startswith('c'):
        toks = line.split()
        def get_prefix_tok(prefix):
            for tok in toks:
                if tok.startswith(prefix):
                    return tok[1:]
            return ''
        x1 = get_prefix_tok('x')
        y1 = get_prefix_tok('y')
        x2 = get_prefix_tok('X')
        y2 = get_prefix_tok('Y')
        print "(%s, %s) - (%s, %s)" % (x1, y1, x2, y2)