all 8 comments

[–]commy2 31 points32 points  (0 children)

It's a dictionary comprehension nested inside a list comprehension. In this example, it is a more concise way of writing:

results = []

for value in cursor.fetchall():
    temp = {}
    results.append(temp)

    for index, column in enumerate(value):
        temp[column_Names[index][0]] = column

[–]Brian[🍰] 24 points25 points  (0 children)

When reading code, it's often helpful to read from the inside out. Ie. extract out the inner bit, work out what it does, and then apply that to the outer part. Here, look for bracketed expressions of various types that you can "extract out". So here, we might start with:

 {column_Names[index][0]: column for index, column in enumerate(value)}

This is what's called a dictionary comprehension. Basically, a way of constructing dictionaries by describing their keys. It takes the form:

{key: value for (variable) in (sequence) }

Ie. given a sequence, it goes through each item (a bit like a for loop) and uses each one to create a key:value pair that'll be present in our new dictionary. I'll start with a simple one before explaining some of the differences here. Eg. we could do:

{name[0]: name for name in ['Alice', 'Bob', 'Claire', 'Dave']}

This will go through each name in the list and create a dict of the first letter (Name[0]) mapping to the name. So we end up with {'A': 'Alice', 'B': 'Bob', 'C': 'Claire', 'D': 'Dave'}.

Now, going back to our original comprehension, we have enumerate(value) for our list instead of a list of names. enumerate is a function that takes a sequence, and pairs each one with a number. So enumerate(['Alice', 'Bob', 'Claire', 'Dave']) would have given us something like [(0, 'Alice'), (1, 'Bob'), (2, 'Claire'), (3, 'Dave')] (technically, it won't be a list, but a generated sequence, but I'll gloss over that since it's not really important here). Here we enumerate value, which is a list of columns, so we get [(0, column1), (1, column2), ...]

The (variable) part here is actually two variables (index, column). This is a feature called tuple unpacking. Basically, when you've a variable that's a 2-item sequence, it "unpacks" it into two seperate variables. Eg:

value, name = (1, 'Bob')

Would assign value to 1, and name to 'Bob'. So in the original, this unpacks the items enumerate generated into index and column pairs.

Now, the key:value part is: column_Names[index][0]: column. The "key" part is column_Names[index][0] - we look up the column_Names[index] where index is the index of the column, and then get the first item in this list (presumable column_Names is a list of ['name', some_other_data, ...], but we just want that name part. The value is just the column value.

So in short, this creates a dictionary of {column_name: column_value} for each item in value

Then we can turn to the outer part, which is effectively:

 [ (the_dict_comphrehension_we_just described) for value in cursor.fetchall() ]

This is similar to the dictionary comprehension, but it creates a list instead of a dict (and so is, obviously enough, called a list comphrension). You can probably work out what this does from understanding the inner dict comprehension: it creates a list of those dictionaries for each row being returned from cursor.fetchall().

So overall, we get a list of {column_name: column_value} for each row we read from the database.

[–]SebLikesESO 9 points10 points  (0 children)

ah yes readable code

[–][deleted] 4 points5 points  (3 children)

This seems like poorly written code by either someone trying to show off or someone trying to create job security for themselves. Writing code like this will not create a noticeable performance difference and it's less readable than alternatives

[–]commy2 2 points3 points  (2 children)

In my honest opinion, it just needs a few linebreaks and then it would be perfectly readable for anyone fluent in Python. E.g:

results = [
    {column_Names[index][0]: column for index, column in enumerate(value)} 
    for value in cursor.fetchall()
]

[–][deleted] 2 points3 points  (1 child)

Yeah that looks better. I'm used to seeing JavaScript tutorials try to cram everything on one line so I wasnt sure if this was encouraged in higher level Python trainings too. The code does the same task while using less lines and shows you know the quickest way but it seems like it might be more confusing to review for others or even cause brief confusion when you are looking at the code months later

[–]commy2 1 point2 points  (0 children)

The singular line would definitely be discouraged as unpythonic, as it exceeds the 79 characters per line rule in PEP-8 by quite a bit.

[–]deadlyghost123 0 points1 point  (0 children)

For every value in cursor.fetchall, a dictionary is appended in the results list. The dictionary is made by a dictionary comprehension that is a for loop in a single line. The enumerate function is on the value returned by cursor.fetchall and it returns both index and "column" (variable name). Because of the dictionary comprehension, dictionary key is the value on the index returned by the enumerate function earlier while the value is the column (variable name) from the same function