views:

123

answers:

5

Through tutorials I had learned that you can define two variables in the same statement, e.g.:

In [15]: a, b = 'hello', 'hi!'

In [16]: a
Out[16]: 'hello'

In [17]: b
Out[17]: 'hi!'

well how does that apply to here?

fh, opened = cbook.to_filehandle(fname, 'w', return_opened = True)

I prodded further:

In [18]: fh
Out[18]: <open file 'attempt.csv', mode 'w' at 0xaac89d0>

In [19]: opened
Out[19]: True

my issue comes really with 'opened'. Well normally if two variables are being defined, there would be a comma and then whatever is there would define 'opened.' This is not the case. Even with that issue looming, 'opened' is equal to True which I assume is because 'return_opened = True.' Well that's weird because I don't remember in any tutorial that you could just add a 'return_' before a variable to affect that variable.

I play with it some more and I change the True to False and I get this:

In [10]: fh, opened = cbook.to_filehandle(fname, 'w', return_opened = False)
---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)

/home/blahblahblah/Documents/Programming/EXERCISES/piece.py in <module>()
----> 1 
      2 
      3 
      4 
      5 

IOError: [Errno 9] Bad file descriptor

so I guess it only accepts False.

I guess I'd like if someone could explain what is going on here.

Gracias amigos!

here's the entire code:

if missingd is None:
    missingd = dict()

def with_mask(func):
    def newfunc(val, mask, mval):
        if mask:
            return mval
        else:
            return func(val)
    return newfunc

formatd = get_formatd(r, formatd)
funcs = []
for i, name in enumerate(r.dtype.names):
    funcs.append(with_mask(csvformat_factory(formatd[name]).tostr))

fh, opened = cbook.to_filehandle(fname, 'w', return_opened=True)
writer = csv.writer(fh, delimiter=delimiter)
header = r.dtype.names
writer.writerow(header)

# Our list of specials for missing values
mvals = []
for name in header:
    mvals.append(missingd.get(name, missing))

ismasked = False
if len(r):
    row = r[0]
    ismasked = hasattr(row, '_fieldmask')

for row in r:
    if ismasked:
        row, rowmask = row.item(), row._fieldmask.item()
    else:
        rowmask = [False] * len(row)
    writer.writerow([func(val, mask, mval) for func, val, mask, mval
                     in zip(funcs, row, rowmask, mvals)])
if opened:
    fh.close()
+2  A: 

My guess is that the function internally looks something like this:

def to_filehandle(filename, mode, return_opened=False):
    # do something to open the file and set opened
    # to True if it worked, False otherwise
    if return_opened:
        return the_filehandle, opened
    else:
        return the_filehandle

There is nothing special or magical about the return_opened keyword argument; it is simply changing the behavior of this particular function.

dcrosta
A: 

In Python, a function have more than one return value. In this case, the function 'cbook.to_filehandle' return the two value.

About the error, I think we cannot tell much about it until we know what 'cbook.to_filehandle' supposes to do or see it code.

NawaMan
+2  A: 

With tuple assignment, the right side doesn't need to be an explicit tuple:

x = 1, 0
a, b = x

does the same thing as:

a, b = 1, 0

If a function returns a tuple, you can unpack it with tuple assignment:

def my_fn():
    return 1, 0

a, b = my_fn()
Ned Batchelder
+1  A: 

Unpacking is not a magic process : every tuple (for example, (1, 2, 3) is a tuple with three values) can be unpacked into three values. But the tuple itself is also a value, so you can assign it to a variable or return it from a function :

x = (1, 2, 3)
a, b, c = x

# Or, for example :
def function_returning_a_tuple():
    return (True, False)

a, b = function_returning_a_tuple()

As you may now understand, cbook.to_filehandle is only a function returning a tuple of two values (file, opened). There is no magic behind that, nothing about return_something parameters handled differently.

Pierre Bourdon
+2  A: 

As @dcrosta says, there is nothing magical about the variable names. To better see what's going on, try:

result = cbook.to_filehandle(fname, 'w', return_opened=True)

and examine result, type(result), etc: you'll see it's a tuple (could conceivably be a list or other sequence, but that's not likely) with exactly two items. result[0] will be an open file, result[1] will be a bool. Most likely, that's because function to_filehandle is coded with a return thefile, thebool-like statement, as dcrosta also surmises.

So, this part is "packing" -- two things are packed into one return value, making the latter a tuple with two items. The "unpacking" part is when you later do:

fh, opened = result

and the two-item sequence is unpacked into two variables. By doing the unpacking directly, you're just "cutting out the middleman", the variable I here named result (to make it easier for you to examine exactly what result comes from that function call, before it gets unpacked). If you know in advance you'll always get a 2-item sequence, and don't need the sequence as such but rather each item with a separate name, then you might as well unpack at once and save one "intermediate step" -- that's all there is to it!

Alex Martelli