While developing a program, occur as a . Appropriate data structures reflect objects’ properties and allow the creation of a concise and intuitive solution. On the contrary, choosing the may and make further development even more problematic. For this reason, how to organize your data to simplify the processing is an issue that may . duplicate pieces of code may result of choosing particular data structures wrong data structure complicate the code highly affect the code Duplicate for loops We’ll consider an example I came across in practice where a choice of data structure caused in several methods of the same class. I simplified the code a bit to convey the idea. duplicate for loop def process_south_group(uid: int, settings: List[Tuple[str, int]]) -> None: for name, value in settings: if name == "working_time": pass elif name == "timeout": pass elif name == "temperature": pass def process_north_group(uid: int, settings: List[Tuple[str, int]]) -> None: for name, value in settings: if name == "temperature": pass elif name == "connected_to": pass In practice, the class contained 3–4 methods with the same pattern for processing. I have shown only 2 methods to illustrate : settings the pattern for name, value in settings: ... Each method takes as a parameter that is a list of tuples. The parameter represents a sensor’s settings. Settings have a predefined number of parameters: , where any of them can be optional. For instance, after reading from a file, settings may be: settings working_time, temperature, timeout, connected_to settings = { 'working_time': 15, 'timeout': 2, 'temperature': 25 } or settings = { 'working_time': 15 } or settings = { 'connected_to': 5 } It turns out we have to iterate over the list of to get hold of the attributes’ values due to an inappropriate choice of a data structure. For instance, if a method needed to process a temperature value somehow, we would have to: settings for name, value in settings: if name == "temperature": # to do something So, as we have to iterate over each tuple in the list, we come to the same in each method: for loop Avoiding for loops Let’s see how we can change the code to prevent us from in each method. We’d like to retrieve a temperature value like this: duplicating for loop setttings.temperature Since we need a data structure for storing data without associated behavior, is an appropriate candidate for this case: dataclass @dataclass class Settings: working_time: Optional[int] = None temperature: Optional[int] = None timeout: Optional[int] = None connected_to: Optional[int] = None # or from Python 3.10 you can use union syntax instead of Optional @dataclass class Settings: working_time: int | None = None temperature: int | None = None timeout: int | None = None connected_to: int | None = None Each of the parameters is by default as some of them may not be omitted. The original code transforms into: None def process_south_group(uid: int, settings: Settings) -> None: if settings.working_time is not None: pass if settings.timeout is not None: pass if settings.temperature is not None: pass def process_north_group(uid: int, settings: Settings) -> None: if settings.temperature is not None: pass if settings.connected_to is not None: pass We have to check whether the value to differentiate between undefined parameters and ones set to 0. is not None if settings.timeout: # skip if timeout = 0 or timeout is None pass if settings.timeout is not None: # skip only if timeout is None pass The data class has helped us to get rid of the in the methods. Besides, you can now look at the method signature and go to the definition of Settings to figure out which parameters it may have. Previously, we had to look through the source code of several methods to grasp all possible parameters for settings because some of them could work with various parameters. for loops The current implementation is far more flexible in terms of extensibility. For example, if you have different types of sensors with different settings, you may create a hierarchy of sensor classes derived from the base data class. When you add more behavior to the object, you may replace it with a regular class in Python. Duplicated code may also come across at the loop level. Sometimes, it roots from using an unsuitable data structure for abstracting purposes. It complicates your program as you need to build more complex logic to process them. In that case, think of choosing a different data structure that better reflects the object’s properties allowing you to avoid loops where they are redundant. Bear also in mind that variables with complex type annotations can be a sign of a possibility to split your object into several ones.