masher
masher

Reputation: 4096

Application of class instance method results in making class instance variable None?

I have a class I've made to hold all information about my data points. Data points are often collected in a series of measurements, so I want to keep them together: hence, DataPoints and LotsOfDataPoints

#this is simplified code, but reproduces my issue

class DataPoint:    
    def __init__(self, value):
        self.value = value
    
    def add_number(self, number):
        self.value += number
    
    def __repr__(self):
        return str(self.value)
        
class LotsOfDataPoints:    
    def __init__ (self, *values):
        self.lst = []      
        for value in values:
            self.lst.append(DataPoint(value))
            
    def add_one(self):
        self.lst = [d.add_number(1) for d in self.lst]

I can successfully create a DataPoint:

d = DataPoint(1)
print(d)
> 1

d.add_number(1)
print(d)
> 2

I can successfully make LotsOfDataPoints:

ds = LotsOfDataPoints(1,2,3,4,5)
print(ds.lst)
> [1, 2, 3, 4, 5]

I can call the DataPoint method on an individual DataPoint

ds.lst[0].add_number(1)
print(ds.lst)
> [2, 2, 3, 4, 5]

However, when I try to add_one() to my LotsOfDataPoints, they all turn to None.

ds.add_one()
print(ds.lst)
> [None, None, None, None, None]

What have I done wrong here?

Upvotes: 0

Views: 28

Answers (2)

sotmot
sotmot

Reputation: 1313

This can be fixed by returning self.value in the function add_number. Because, in the loop - [d.add_number(1) for d in self.lst], the function is just being called. The values aren't saved. The modified code is as follows:

class DataPoint:    
    def __init__(self, value):
        self.value = value
    
    def add_number(self, number):
        self.value += number
        return self.value
    
    def __repr__(self):
        return str(self.value)
        
class LotsOfDataPoints:    
    def __init__ (self, *values):
        self.lst = []      
        for value in values:
            self.lst.append(DataPoint(value))
            
    def add_one(self):
        self.lst = [d.add_number(1) for d in self.lst]

The output obtained is as follows:

d = DataPoint(1)
print(d)
> 1
ds = LotsOfDataPoints(1,2,3,4,5)
print(ds.lst)
> [1, 2, 3, 4, 5]
ds.add_one()
print(ds.lst)
> [2, 3, 4, 5, 6]

Upvotes: 1

Sandra
Sandra

Reputation: 41

I would say the problem lies here

def add_one(self):
    self.lst = [d.add_number(1) for d in self.lst]

Your DataPoint.add_number method does not return anything, hence the self.lst is filled with None values. What you actually want to do is

def add_one(self):
    for d in self.lst:
        d.add_number(1)

This should edit the DataPoint objects without emptying the LotsOfDataPoints.lst attribute.

Upvotes: 1

Related Questions