-4

In Python 3 I am trying to print the outputs of a **kwargs using a list comprehension. I am unable to do so while using a for loop does print the elements of my list input. Below is the reproducible code:

Using list comprehension:

class Practice(object):
    __acceptable_keys_list = ['Right', 'left']

    def __init__(self, **kwargs):
        temp = ([self.__setattr__(key, kwargs.get(key)) for key in self.__acceptable_keys_list])
        print(temp)

Output is [None, None].

Where as using a for loop:

class Practice(object):
    __acceptable_keys_list = ['Right', 'Left']

    def __init__(self, **kwargs):   
         for key in self.__acceptable_keys_list:
             self.__setattr__(key,kwargs.get(key))
             print(key)

Output is [Right, Left].

Why the difference ? What am I missing ? Shouldn't list comp and for loops behave in similar manner?

Edit: Why the downvotes ? I am trying to understand things here.

WaterRocket8236
  • 1,442
  • 1
  • 17
  • 27
  • 4
    `__setattr__` returns `None`. – Aran-Fey Oct 08 '18 at 10:29
  • 3
    Those two aren't equivalent, try using `temp=self.__setattr__(key,kwargs.get(key));print(temp)` in the second one – Nick is tired Oct 08 '18 at 10:29
  • 3
    Abusing a list comprehension for its side effect is a big no no: https://stackoverflow.com/questions/5753597/is-it-pythonic-to-use-list-comprehensions-for-just-side-effects – DeepSpace Oct 08 '18 at 10:30
  • 2
    The answers [here](https://stackoverflow.com/questions/26027694/correct-style-for-python-functions-that-mutate-the-argument) explain why its conventional in Python for mutating methods to return `None`. – PM 2Ring Oct 08 '18 at 11:30

1 Answers1

0

Coding Style

You are abusing a side-effect in a list comprehension. This is considered very bad practice.

Return Value of __setattr__

Nonetheless, as already mentioned by @Aran-Fey, __setattr__ returns None. Your Code is not equivalent. The following code does the same:

class Practice(object):
    __acceptable_keys_list = ['Right', 'Left']

    def __init__(self, **kwargs):
        # Please do **NOT** do this at home!
        temp = ([self.__setattr__(key, kwargs.get(key)) for key in self.__acceptable_keys_list])
        print(temp)

class Practice(object):
    __acceptable_keys_list = ['Right', 'Left']

    def __init__(self, **kwargs):
         temp = []
         for key in self.__acceptable_keys_list:
             # Use the return value of __setattr__, which is None
             temp.append(self.__setattr__(key,kwargs.get(key)))
         print(temp)
Lucas Kahlert
  • 1,207
  • 9
  • 16