-2

I have a source list of images which looks like this (simplified for brevity):

images = [
    {
        'url': 'https://example.com/image.jpg',
        'description': 'Caption',
        'type': 'photograph',
        'order': 1
    },
    {
        'url': 'https://example.com/image.jpg',
        'description': 'Caption',
        'type': 'photograph',
        'order': 2
    }
]

And I'm using a dictionary comprehension inside a list comprehension to remove 2 dictionary items and build a new list of cleaned dictionaries:

images_cleaned = [{k:v for k,v in i.items() if k != 'order' and k != 'type'} for i in images]

I then return the new list at the end of my function:

return images_cleaned

This is inside a list of properties (real estate) which contain a list of images available via a separate request. For 25 properties the code works fine, but then I get to the 26th and it trips up with an error:

UnboundLocalError: local variable 'images_cleaned' referenced before assignment

Looking at the images available for this property however, doesn't reveal anything different. It contains the same list of images.

Is there anything noticeably wrong with my images_cleaned list and dictionary comprehension which would result in nothing behind assigned to images_cleaned variable before returning? It's my assumption that even if there were no images then the variable would still be an empty list []?

Edit: Specifically the error occurs on the return statement, returning images_cleaned.

ianyoung
  • 2,863
  • 4
  • 26
  • 31
  • 1
    Nothing I see based on what's there. But the issue likely lies elsewhere in your code, I don't think it's possibe to spot from one-line snippets. Would need to whole script or a continuous pseudo-code at least. – logicOnAbstractions May 20 '22 at 16:57
  • 3
    It looks like the error is in a part of your code that you are not sharing here. – Mortz May 20 '22 at 16:58
  • Agreed with above commenters. If I were to take a guess, it's likely indent / block-level scoping of `images_cleaned`, and you need to check its position / placement. It's something left out of the question in its current form. – tony May 20 '22 at 16:59
  • Agreed with others. Wrapping a function around the dict/list comprehension and running it with your data does not yield an error. – hrvg May 20 '22 at 17:00
  • Thanks for the input. I'll try to copy the relevant parts to a gist to provide a better overview... – ianyoung May 20 '22 at 17:10
  • I've put together a gist of 3 parts providing a better overview of the parts involved including the source response of the 26th property (some fields stripped for brevity). Also, specifically the error is triggering on the return statement for `images_cleaned`. https://d.pr/NkwTiJ – ianyoung May 20 '22 at 17:23
  • `parse.py` calls `get_images.py` which makes the request and cycles through the results. `response.json` shows the actual (but simplified) JSON response. – ianyoung May 20 '22 at 17:25

1 Answers1

0

Your existing code works fine when I tested it, seems the issue is on another part of your code. Note: I just replace multiple condition check with not in,

images = [
    {
        'url': 'https://example.com/image.jpg',
        'description': 'Caption',
        'type': 'photograph',
        'order': 1
    },
    {
        'url': 'https://example.com/image.jpg',
        'description': 'Caption',
        'type': 'photograph',
        'order': 2
    }
]

def filter_and_clean_image(images):
    images_cleaned = [{k:v for k,v in i.items() if k not in ['order','type']} for i in images]
    return images_cleaned


print(filter_and_clean_image(images))

Output:

[{'url': 'https://example.com/image.jpg', 'description': 'Caption'}, {'url': 'https://example.com/image.jpg', 'description': 'Caption'}]

What could be your case:

Referenced from here

The local variable referenced before the assignment occurs when some variable is referenced before the assignment within a function’s body. The error usually occurs when the code tries to access the global variable. As the global variables have global scope and can be accessed from anywhere within the program, the user usually tries to use the global variable within a function.

In Python, we do not have to declare or initialized the variable before using it; a variable is always considered local by default. Therefore when the program tries to access the global variable within a function without specifying it as global, the code will return the local variable referenced before the assignment error, since the variable being referenced is considered a local variable.

The below example code demonstrates the code scenario where the program will end up with the “local variable referenced before assignment” error.

count = 10
def myfunc():
    count = count + 1
    print(count)
  
myfunc()

Output:

UnboundLocalError: local variable 'count' referenced before assignment

To fix that, We need to declare the count variable as global using the global keyword to resolve this error. The below example code demonstrates how the error can be resolved using the global keyword in the above code scenario.

count = 10
def myfunc():
    global count
    count = count + 1
    print(count)
  
myfunc()

Output:

11
A l w a y s S u n n y
  • 36,497
  • 8
  • 60
  • 103
  • Thanks @Always Sunny. In this case the error is triggering on my return statement where I'm returning the `images_cleaned` variable. So if my list comprehension ran then it should have that variable assigned as it's all in the same function. I've put together a gist better showing the components involved and the source data itself: https://d.pr/NkwTiJ – ianyoung May 20 '22 at 17:22
  • @ianyoung here is the working code I created from your gist: https://rextester.com/GRLZ58729 I just used response as it is without doing HTTP request. – A l w a y s S u n n y May 20 '22 at 17:28
  • Thanks, although it doesn't look like anything has changed? I'm just confused as to why it would work for 25 properties and not that 26th when the JSON looks to be the same? – ianyoung May 20 '22 at 17:34
  • Is there any scenario where `images_cleaned` wouldn't be available to return after running `get_images.py`? – ianyoung May 20 '22 at 17:35