```
"""
average an iterable, possibly strings interpretable as numbers or ready numbers
without producing inmemory list of values
"""
class AverageIterable(object):
""" stats counter for big iterable without producing copy in memory """
def __init__(self, it):
self.total = 0
for self.count, value in enumerate(it, 1):
self.total += number(value)
@property
def average(self):
return self.total / float(self.count)
def add(self, num):
self.total += number(num)
self.count += 1
def __str__(self):
return 'Average: %f (sum %s, count %i)' % (self.average, self.total, self.count)
def number(s):
""" If s is not number convert it to integer/float number, return s """
try:
1+s
# s is number allready, return it
return s
except TypeError:
# transform string to appropriate type based on precence of '.'
return float(s) if '.' in s else int(s)
if __name__ == '__main__':
# test data
data = """
57
83
99
12
45
81
74
30
29
66
95
87
42""".strip().splitlines()
it = AverageIterable(data)
print(it)
it.add(23)
print(it)
```

About the Author

The article starter has earned a lot of community kudos, and such articles offer a bounty for quality replies.