In [ ]:
import math
import numpy as np
import numpy.typing as npt

class ArrayableList:
    """
    Stores a list and converts to an array when requested. If the array is
    requested twice without appending in between, the same array is
    returned.
    """
    lst: list[float]
    arr: npt.NDArray[np.float64]
    
    def __init__(self) -> None:
        self.lst = []
        self.arr = np.array(self.lst)
        
    def append(self, value: float) -> None:
        """
        Append value to the contained list.
        """
        self.lst.append(value)
        # self.arr = np.array(self.lst)
        
    def array(self) -> npt.NDArray[np.float64]:
        """
        Return the contained list, as a NumPy array. If called twice without
        appending, the same array is returned.
        """
        if len(self.lst) != len(self.arr):
            self.arr = np.array(self.lst)
        return self.arr
    
al = ArrayableList()
al.append(42)
al.append(math.pi)
al.append(-1/12)
x = al.array()
print(x)
y = al.array()
print(x is y)
[42.          3.14159265 -0.08333333]
True
In [ ]:
import math

class StatsList:
    """
    Stores a list of numbers and provides some simple statistics.
    """
    lst: list[float]
    sum: float
    product: float
    min: float
    max: float
    
    def __init__(self) -> None:
        self.lst = []
        self.sum = 0.0
        self.product = 1.0
        # We don't know a min or max yet, so nonsense
        self.min = 0.0
        self.max = 0.0
        
    def append(self, val: float) -> None:
        """
        Append val to the stored list, while also maintaining StatsList's
        internal statistics.
        """
        self.lst.append(val)
        self.sum += val
        self.product *= val # Watch for zero[e]s!
        
        if len(self.lst) == 1:
            self.min = val
            self.max = val
        else:
            if val < self.min:
                self.min = val
            if val > self.max:
                self.max = val
        
    def mean(self) -> float:
        """
        Returns the mean of the stored list.
        """
        return self.sum / len(self.lst)
    
    def geometricMean(self) -> float:
        """
        Returns the geometric mean of the stored list.
        """
        return self.product ** (1/len(self.lst))

x = StatsList()
x.append(42)
x.append(math.sqrt(2))
x.append(math.pi)
x.append(-1/12)
print("lst is", x.lst)
print("sum is", x.sum)
print("mean is", x.mean())
print("geomean is", x.geometricMean())
print("min is", x.min)
print("max is", x.max)
lst is [42, 1.4142135623730951, 3.141592653589793, -0.08333333333333333]
sum is 46.47247288262955
mean is 11.618118220657388
geomean is (1.4041652819706363+1.404165281970636j)
min is -0.08333333333333333
max is 42
In [ ]:
import math

class StatsList:
    """
    Stores a list of numbers and provides some simple statistics.
    
    Invariants:
     - sum is always the sum of the values in lst
     - product is always the product of the values in lst
     - min is always the least value in lst
     - max is always the greatest value in lst
    """
    lst: list[float]
    sum: float
    product: float
    min: float
    max: float
    
    def __init__(self) -> None:
        self.lst = []
        self.sum = 0.0
        self.product = 1.0
        # We don't know a min or max yet, so nonsense
        self.min = 0.0
        self.max = 0.0
        
    def append(self, val: float) -> None:
        """
        Append val to the stored list, while also maintaining StatsList's
        internal statistics.
        """
        self.lst.append(val)
        self.sum += val
        self.product *= val # Watch for zero[e]s!
        
        if len(self.lst) == 1:
            self.min = val
            self.max = val
        else:
            if val < self.min:
                self.min = val
            if val > self.max:
                self.max = val
                
    def pop(self, idx: int) -> float:
        """
        Pops the value at index idx out of the contained list. Returns the
        popped value.
        """
        val = self.lst.pop(idx)
        self.sum -= val
        if val == 0:
            self.product = 1.0
            for x in self.lst:
                self.product *= x
        else:
            self.product /= val
        if len(self.lst) == 0:
            self.min = 0.0
            self.max = 0.0
        else:
            if val == self.min: # == again???
                self.min = min(self.lst)
            if val == self.max:
                self.max = max(self.lst)
        return val
        
    def mean(self) -> float:
        """
        Returns the mean of the stored list.
        """
        return self.sum / len(self.lst)
    
    def geometricMean(self) -> float:
        """
        Returns the geometric mean of the stored list.
        """
        return self.product ** (1/len(self.lst))

x = StatsList()
x.append(42)
x.append(math.sqrt(2))
x.append(math.pi)
x.append(-1/12)
print("lst is", x.lst)
print("sum is", x.sum)
print("mean is", x.mean())
print("geomean is", x.geometricMean())
print("min is", x.min)
print("max is", x.max)

x.pop(3)
print("geomean is now", x.geometricMean())

x.append(0)
print("geomean is now", x.geometricMean())

x.pop(-1)
print("geomean is now", x.geometricMean())
lst is [42, 1.4142135623730951, 3.141592653589793, -0.08333333333333333]
sum is 46.47247288262955
mean is 11.618118220657388
geomean is (1.4041652819706363+1.404165281970636j)
min is -0.08333333333333333
max is 42
geomean is now 5.714409866561776
geomean is now 0.0
geomean is now 5.714409866561776
In [ ]:
class FloatWithExtraWork:
    """
    Does nothing of any real value.
    """
    val: float
    
    def __init__(self, val: float) -> None:
        self.val = val
        
    def __add__(self, other):
        return FloatWithExtraWork(self.val + other.val)
    
    def __repr__(self) -> str:
        return f"FloatWithExtraWork({self.val})"
        
x = FloatWithExtraWork(3.1)
y = FloatWithExtraWork(0.04159)
z = x + y
print(z.val)
print(z)
3.14159
FloatWithExtraWork(3.14159)
In [ ]:
import math

class StatsList:
    """
    Stores a list of numbers and provides some simple statistics.
    
    Invariants:
     - sum is always the sum of the values in lst
     - product is always the product of the values in lst
     - min is always the least value in lst
     - max is always the greatest value in lst
    """
    lst: list[float]
    sum: float
    product: float
    min: float
    max: float
    
    def __init__(self) -> None:
        self.lst = []
        self.sum = 0.0
        self.product = 1.0
        # We don't know a min or max yet, so nonsense
        self.min = 0.0
        self.max = 0.0
        
    def append(self, val: float) -> None:
        """
        Append val to the stored list, while also maintaining StatsList's
        internal statistics.
        """
        self.lst.append(val)
        self.sum += val
        self.product *= val # Watch for zero[e]s!
        
        if len(self.lst) == 1:
            self.min = val
            self.max = val
        else:
            if val < self.min:
                self.min = val
            if val > self.max:
                self.max = val
                
    def pop(self, idx: int) -> float:
        """
        Pops the value at index idx out of the contained list. Returns the
        popped value.
        """
        val = self.lst.pop(idx)
        self.sum -= val
        if val == 0:
            self.product = 1.0
            for x in self.lst:
                self.product *= x
        else:
            self.product /= val
        if len(self.lst) == 0:
            self.min = 0.0
            self.max = 0.0
        else:
            if val == self.min: # == again???
                self.min = min(self.lst)
            if val == self.max:
                self.max = max(self.lst)
        return val
        
    def mean(self) -> float:
        """
        Returns the mean of the stored list.
        """
        return self.sum / len(self.lst)
    
    def geometricMean(self) -> float:
        """
        Returns the geometric mean of the stored list.
        """
        return self.product ** (1/len(self.lst))
    
    def __repr__(self) -> str:
        return f"StatsList({self.lst})"
    
    def __eq__(self, other) -> bool:
        return self.lst == other.lst
    
    def __ne__(self, other) -> bool:
        return self.list != other.lst
    
    def __lt__(self, other) -> bool:
        return self.list < other.lst
    
    def __le__(self, other) -> bool:
        return self.list <= other.lst
    
    def __gt__(self, other) -> bool:
        return self.list > other.lst
    
    def __ge__(self, other) -> bool:
        return self.list >= other.lst
    
    def __add__(self, other):
        ret = StatsList()
        for x in self.lst:
            ret.append(x)
        for x in other.lst:
            ret.append(x)
        return ret
    
    def __mul__(self, count: int):
        ret = StatsList()
        for _ in range(count):
            for x in self.lst:
                ret.append(x)
        return ret
    
    def __len__(self) -> int:
        return len(self.lst)

x = StatsList()
x.append(42)
x.append(math.sqrt(2))
x.append(math.pi)
x.append(-1/12)
print("lst is", x.lst)
print("sum is", x.sum)
print("mean is", x.mean())
print("geomean is", x.geometricMean())
print("min is", x.min)
print("max is", x.max)

x.pop(3)
print("geomean is now", x.geometricMean())

x.append(0)
print("geomean is now", x.geometricMean())

x.pop(-1)
print("geomean is now", x.geometricMean())

print(x)
print(x*3)
lst is [42, 1.4142135623730951, 3.141592653589793, -0.08333333333333333]
sum is 46.47247288262955
mean is 11.618118220657388
geomean is (1.4041652819706363+1.404165281970636j)
min is -0.08333333333333333
max is 42
geomean is now 5.714409866561776
geomean is now 0.0
geomean is now 5.714409866561776
StatsList([42, 1.4142135623730951, 3.141592653589793])
StatsList([42, 1.4142135623730951, 3.141592653589793, 42, 1.4142135623730951, 3.141592653589793, 42, 1.4142135623730951, 3.141592653589793])
In [ ]:
lst = [1, 2, 3]
print(lst * 2)
[1, 2, 3, 1, 2, 3]
In [ ]:
print((3).__add__(4).__mul__(12))
print((3 + 4) * 12)
84
84