On Fri, 8 Jul 2005 21:21:36 -0500, Alex Gittens <[EMAIL PROTECTED]> wrote:
>I'm trying to define a function that prints fields of given widths >with specified alignments; to do so, I wrote some helper functions >nested inside of the print function itself. I'm getting an >UnboundLocalError, and after reading the Naming and binding section in >the Python docs, I don't see why. > >Here's the error: >>>> fieldprint([5, 4], 'rl', ['Ae', 'Lau']) >Traceback (most recent call last): > File "<stdin>", line 1, in ? > File "fieldprint.py", line 35, in fieldprint > str +=3D cutbits() > File "fieldprint.py", line 11, in cutbits > for i in range(0, len(fields)): >UnboundLocalError: local variable 'fields' referenced before assignment > >This is the code: >def fieldprint(widths,align,fields): > > def measure(): > totallen =3D 0 > for i in range(0, len(fields)): > totallen +=3D len(fields[i]) > return totallen > > def cutbits(): > cutbit =3D [] > for i in range(0, len(fields)): > if len(fields[i]) >=3D widths[i]: > cutbit.append(fields[i][:widths[i]]) > fields =3D fields[widths[i]:] fields[i] = fields[i][widths[i]:] # did you mean this, analogous to [1] below? > elif len(fields[i]) > 0: > leftover =3D widths[i] - len(fields[i]) > if align[i] =3D=3D 'r': > cutbit.append(' '*leftover + fields= >[i]) > elif align[i] =3D=3D 'l': > cutbit.append(fields[i] + ' '*lefto= >ver) > else: > raise 'Unsupported alignment option= >' > fields[i] =3D '' ^^^^^^^^^-- [1] > else: > cutbit.append(' '*widths[i]) > return cutbit.join('') > > if len(widths) !=3D len(fields) or len(widths)!=3Dlen(align) or >len(align)!=3Dlen(fields): > raise 'Argument mismatch' > > str =3D '' > > > while measure()!=3D0: > str +=3D cutbits() > >What's causing the error? Maybe the missing [i]'s ? It's not clear what you are trying to do with a field string that's wider than the specified width. Do you want to keep printing lines that have all blank fields except for where there is left-over too-wide remnants? E.g., if the fields were ['left','left12345','right','12345right'] and the widths were [5,5,6,6] and align 'llrr' should the printout be (first two lines below just for ruler reference) 1234512345123456123456 LLLLLLLLLLRRRRRRRRRRRR left left1 right12345r 2345 ight or what? I think you can get the above with more concise code :-) but a minor mod to yours seems to do it: >>> def fieldprint(widths,align,fields): ... def measure(): ... totallen = 0 ... for i in range(0, len(fields)): ... totallen += len(fields[i]) ... return totallen ... def cutbits(): ... cutbit = [] ... for i in range(0, len(fields)): ... if len(fields[i]) >= widths[i]: ... cutbit.append(fields[i][:widths[i]]) ... #fields = fields[widths[i]:] ... fields[i] = fields[i][widths[i]:] # did you mean this, analogous to [1] below? ... elif len(fields[i]) > 0: ... leftover = widths[i] - len(fields[i]) ... if align[i] == 'r': ... cutbit.append(' '*leftover + fields[i]) ... elif align[i] == 'l': ... cutbit.append(fields[i] + ' '*leftover) ... else: ... raise 'Unsupported alignment option' ... fields[i] = '' # <-- [1] ... else: ... cutbit.append(' '*widths[i]) ... # XXX return cutbit.join('') ... return ''.join(cutbit) ... if len(widths) != len(fields) or len(widths)!=len(align) or len(align)!=len(fields): ... raise 'Argument mismatch' ... # str = '' ... result_lines = [] ... while measure()!=0: ... result_lines.append(cutbits()) ... #str += cutbits() ... return '\n'.join(result_lines) ... >>> fieldprint([5,5,6,6], 'llrr', ['left', 'left12345', 'right', '12345right']) 'left left1 right12345r\n 2345 ight' >>> print fieldprint([5,5,6,6], 'llrr', ['left', 'left12345', 'right', >>> '12345right']) left left1 right12345r 2345 ight Note that for i in xrange(len(items)): item = items[i] # mess with item just to walk through items one item at a time is more concisely written for item in items: # mess with item and if you really need the index i as well, for i, item in enumerate(items): # use item and i here Also, if you are going to raise 'Argument mismatch' it would be better to do it at the beginning and use a standard exception. String exceptions are frowned upon these days, so probably raise ValueError or TypeError with the string as an argument instead, unless you have a more informative thing to do. BTW, measure above can be defined with current builtins as (untested) def measure(): return sum([len(field) for field in fields]) I'll leave a few things ... HTH Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list