Undefined variable assignment to list

So I’ve just started playing around with python. My first script was to spool through a pipe deliminated csv.

I noticed this language is slightly more strict than PHP :slight_smile: I receive an error when trying to assign a non existant variable to a new list.


#open csv file
ifile  = open('/tmp/file.dat', "rb")
reader = csv.reader(ifile,delimiter='|')
for row in reader:
     op = {
          'column': row[4]
      }

If row[4] happens to be null for that row, then it will error out. I’ve come across a few solutions such as setdefault. But I’m curious how some of your setups might be, especially for something dynamic like spooling a csv.

I notice the Python code around me does lots and lots and lots of try-excepts. Which I guess is good. The main thing with those being, to keepy the try parts as small as possible… some people stuff everything into their try statements which is a bit dumb since now there could be many different types of exceptions that your ‘except’ won’t catch. I do the bare-minimum test in my try’s and then after the except, I stuff everything else in the Else.

A non-Pythonic answer I’ve seen states a regex to match the value against in an if statement before attempting assignment. That seems more Perlish really.

In many instances where there are classes and defs, the arguments fed to it are keyword vars with var=None as a default… that’s super common.

One thing I really liked going from Javascript to Python is the named variables and default var values in functions.

As Stomme said, try using try-excepts, or test for the presence of what you’ve been returned (the example below is terrible, but you can do it if you really want):

if 4 < len(row):
       do_something()

See here for more info: http://stackoverflow.com/a/8570694

I would use the following approach


import csv
ifile  = open('/tmp/file.dat', "rb")
reader = csv.reader(ifile,delimiter='|')
column_values = [row[4] if len(row) > 4 else None for row in reader]

This uses a list comprehension (which is neater and faster than a for loop) and returns all the values of column 5 as a list.
Also, you are assigning the value of row[4] to a dictionary in your example code, so a list comprehension may not suit your use case in this instance. However, I would personally gather the desired values first, then perform operations on them, which is why I have used a list comprehension here.

My example doesn’t use try/except
try/except is usually pretty fast, unless the exception is triggered - see how fast are exceptions
In this case I assume the exception will be triggered, and thus the check for len(row) is the better option. You would only know which method was faster by profiling your particular code and data, which I have not done in this case. In general I avoid using try / except (unless it makes more sense than a conditional check).

If list comprehensions tickle your fancy, also check out generators. For this problem I would actually use a generator not a list comprehension, but as you are a beginner a list comprehension is probably an easier way to be introduced to the concepts at play.

Hopefully this makes sense and suits your needs.

Great point made here about python and preferring Easier To Ask For Forgiveness Than Permission vs Look Before You Leap

Easier to ask for forgiveness than permission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C.

It’s very common to use try/except in python code, so please don’t interpret my preference to ‘only use them where it makes sense’ as ‘use try/except sparingly’, just that I prefer not to use a short for loop when I can use a list comprehension.

Code style is an interesting thing.

Well I guess I provided a bad example. Im not referring to adding a single item. I’m referring to doing an operation for each item in row, not just row[4].

You could still use the list comprehension, with a variable in place of the 4.
Since I don’t think in list comprehensions, I usually write out first two for loops, one nested in the other. Then I can change that around into a list comp.

Pythonistas encourage list comprehensions over for loops and for loops over while loops because people have been tweaking the interpreter to be more efficient with those, so in many cases they’re the fastest option (use timeit to check any given case, though I’ve seen people on LinkedIn showing differences between for example 32- and 64-bit architecture…).

Off-topic,
There’s a French dude on SO, e-satis, who has a couple of really nice “answers” describing decorators and generators, with code details and everything. Look him up, they’re fun to read.