Home > other >  Refactoring a loop in Python
Refactoring a loop in Python

Time:12-06

I know this is not good coding and I'm looking to improve it. I want to get the first name by default if no name is supplied. My hack still enters the for loop and if it would be a big one it would be innefficient. But if I do all the attributions that I'm doing in the for loop's inside if, again, in the outside if, I would duplicate code. And I wouldn't use a function just to set attributes so I'm not sure how to proceed here.

    if not name:
        name = self.data['big_list'][0]['name']

    for i in range(len(self.data['big_list'])):
        if self.data['big_list'][i]['name'] == name:
            self.name = name
            self.address = self.data['big_list'][i]['address']
            ...
            return

CodePudding user response:

if think there is a general bad practice or misunderstanding of class: there is a class right? and you check if your instance has the same name of one of the names in your list, and set itself.

-> in your instance it seems you have large data, containing a list of people AND attributes for one person. That does not sound correct.

Let say the class is called Person.

  • you can create an init() method, which takes one row of your data['big_list']. instead of setting each attribute in a loop.
  • you might also want to create a equals() method which checks if a person is the same as someone else. (check duplicates)
  • consider taking your large_data out of that class.

Could you provide us with a little more context?

CodePudding user response:

Here are some comments (that might be insuficient because I do not really understand what you want to achieve with the program).

The purpose of the for loop seems to be to find an item of the list self.data['big_list'] that meets the condition self.data['big_list'][i]['name'] == name, get some data and then terminate. Each entry of self.data['big_list'] is a dict.

This is a good job for a technique called list comprehension, which is much faster than for-looping.

The expression

filtered = [item for item in self.data['big_list'][1:] if item['name'] == name]

results in a list of dicts that are not the first one and meet the name-condition. The used expression self.data['big_list'][1:] is all of self.data['big_list'] but the first one. This technique is called slicing of lists.

There may be more than one entry in filtered, or, none. I assume you are only interested in the first match, because your program does return when a match happens. Therefore, the second part of the program would be

if len(filtered) > 0:
    first_match = filtered[0]
    self.name = name
    self.address = first_match['address']
    ...

This way the structure of the program is more clear and other readers can better understand what the program does. Furthermore, it is much faster ;-).

  • Related