ecomkalinin
ecomkalinin

Reputation: 27

Make dictionary iterable inside Python Class

Noob in python class. Try to make iterations inside class. Is there any solution for this problem?

# some dict
d_init = {'a': 'a_value', 'b': 'b_value', 'c': 'c_value'}


# class 1
class Store1:
    def __init__(self, input_dict):
        self.class_dict = input_dict


# class 2
class Store2:
    def __init__(self, input_dict):
        self.res = []
        self.class_dict = input_dict
        self.class_list = [self.res.append(self.class_dict[k1]) for k1 in self.class_dict.keys()]



obj1 = Store1(d_init)
print("iter 1 = ", [obj1.class_dict[k] for k in obj1.class_dict.keys()])


obj2 = Store2(d_init)
print("iter 2 = ", obj2.class_list)

Output:

iter 1 = ['a_value', 'b_value', 'c_value']
iter 2 = [None, None, None]

Desired output:

iter 1 = ['a_value', 'b_value', 'c_value']
iter 2 = ['a_value', 'b_value', 'c_value']

Upvotes: 0

Views: 154

Answers (4)

user10881750
user10881750

Reputation:

Short answer:
Change

print("iter 2 = ", obj2.class_list)

To
Better answer:

print("iter 2 = ", obj2.res)

When you use list comprehension, and executing methods inside with iteration's return value. It leaves a None data type, because you shifted output to self.res of class Store2. Hence, [None, None, None]. To make self.class_list equal to self.res of you can do this..

# class 2
class Store2:
    def __init__(self, input_dict):
        self.res = []
        self.class_dict = input_dict
        ## run the list comp. after setup of 'res' and 'class_dict'
        [self.res.append(self.class_dict[k1]) for k1 in self.class_dict.keys()]
        ## the local scope of class [None, None, None] value, will be trashed
        ## thanks python, for the dynamic cleanup   :D
        self.class_list = self.res.copy()

obj2 = Store2(d_init)
print("iter 2 = ", obj2.class_list)

Output

iter 2 = ['a_value', 'b_value', 'c_value']

Upvotes: 1

Alvi15
Alvi15

Reputation: 335

self.class_list = [self.res.append(self.class_dict[k1]) for k1 in self.class_dict.keys()]

this right here will just append self.res, so you should return self.res and remove class_list or remove self.res and change your code to

self.class_list = [self.class_dict[k1] for k1 in self.class_dict.keys()]

Upvotes: 1

Chase
Chase

Reputation: 5615

You're misunderstanding list comprehensions-

self.class_list = [self.res.append(self.class_dict[k1]) for k1 in self.class_dict.keys()]

This will store a list of the result of .append inside self.class_list (and .append will obviously return None). The actual values are appended to self.res as you commanded it to do. If you printed obj2.res instead you would have gotten your desired result.

If you want the dict values to be in class_list, why are you appending to a different list altogether? why not just-

self.class_list = [self.class_dict[k1] for k1 in self.class_dict.keys()]

Even better, all those list comprehensions to get the values from a dict can easily be simplified to-

list(self.class_dict.values())

or if you prefer golfing-

[*self.class_dict.values()]

Upvotes: 1

Glech
Glech

Reputation: 781

# class 2
class Store2:
    def __init__(self, input_dict):
        self.class_dict = input_dict
        self.class_list = [self.class_dict[k1] for k1 in self.class_dict]
        # or
        self.class_list = list(self.class_dict.values())

Upvotes: 1

Related Questions