I have a class __init__ that accepts variable length arguments. I am trying to figure out how to separate the *args into str, and floats/ints.
So, for example, in my mind that might look like:
class Example():
def __init__(self, *legs, *vals, named_input: float, named_input_2: str):
*legs are a string. *vals are floats & ints.
My goal is that the user can do:
a = Example('1y', '5y', named_input = 100, named_input_2 = 'setting_1')
a.legs = ['1y', '5y']
a.vals = []
a = Example('1y', '5y', 15, named_input = 100, named_input_2 = 'setting_1')
a.legs = ['1y', '5y']
a.vals = [15]
a = Example('1y', 0, 15, 30, named_input = 100, named_input_2 = 'setting_1')
a.legs = ['1y']
a.vals = [ 0, 15, 30,]
At least 1 *leg must always be supplied. vals can be None though.
Overcomplicated it.. just had to do this:
class test():
def __init__(self, *args):
self.legs = []
self.vals = []
for x in args:
if type(x) in [str]:
self.legs.append(x)
elif type(x) in [float, int]:
self.vals.append(x)
Related
I created a SARIMAX wrapper to use and run my data with, but I got an error. I think I wrote the wrapper correctly, but I get an error. Can I get some help on this?
class SARIMAX_wrapper(object):
def __init__(self, data: pd.DataFrame, p_val: int, d_val: int, q_val: int, P_val: int, D_val: int, Q_val: int, s_val: int) -> None:
self.p_val = p_val
self.q_val = q_val
self.d_val = d_val
self.P_val = P_val
self.Q_val = Q_val
self.D_val = D_val
self.s_val = s_val
self.data = data
#self.model_ = self.fit_model_()
def fit_model_(self) -> None:
try:
temp_model = SARIMAX(self.data, order=(self.p_val, self.d_val, self.q_val), seasonal_order=(self.P_val, self.D_val, self.Q_val, self.s_val))
temp_fitted_model__ = temp_model.fit()
#return temp_fitted_model__
self.model_ = temp_fitted_model__
except:
print('Something is not right!')
pass
#return temp_fitted_model_
def forecast_(self) -> list:
forecast_vals = self.model_.forecast(steps=12)
return forecast_vals
if __name__ == '__main__':
temp1 = SARIMAX_wrapper(data, 2, 2, 2, 0, 0, 0, 0)
temp2 = temp1.fit_model_()
results = temp2.forecast_()
It fails on the results line. Is there a better way to write this wrapper? Thanks!
This is my code. I would like to know how to combine the "_transactions" attributes from 2+ objects.
Could you please help me out?
class Account:
def __init__(self, owner, amount=0):
self.owner = owner
self.amount = amount
self._transactions = []
def add_transaction(self, amount):
if type(amount) != int:
raise ValueError("please use int for amount")
self._transactions.append(amount)
def __add__(self, other):
name = f"{self.owner}&{other.owner}"
starting_amount = self.amount + other.amount
self._transactions += other._transactions
return Account(name, starting_amount)
acc = Account('bob', 10)
acc2 = Account('john')
acc.add_transaction(20)
acc.add_transaction(-20)
acc.add_transaction(30)
acc2.add_transaction(10)
acc2.add_transaction(60)
acc3 = acc + acc2
print(acc3._transactions)
The output should be:
[20, -20, 30, 10, 60]
But instead is:
[]
You should modify the __add__ function in order to sum the transactions; infact when you instatiate a new class, the self._transactions attribute is an empty list by default.
class Account:
def __init__(self, owner: str, amount: int = 0, transactions: list = None):
self.owner = owner
self.amount = amount
self._transactions = [] if transactions is None else transactions
def __add__(self, other):
name = f"{self.owner}&{other.owner}"
starting_amount = self.amount + other.amount
transactions = self._transactions + other._transactions
return Account(name, starting_amount, transactions)
def add_transaction(self, amount):
if type(amount) != int:
raise ValueError("please use int for amount")
self._transactions.append(amount)
acc = Account('bob', 10)
acc2 = Account('john')
acc.add_transaction(20)
acc.add_transaction(-20)
acc.add_transaction(30)
acc2.add_transaction(10)
acc2.add_transaction(60)
acc3 = acc + acc2
print(acc3._transactions)
>>> [20, -20, 30, 10, 60]
Here is a class:
class CoordinateRow(object):
def __init__(self):
self.coordinate_row = []
def add(self, input):
self.coordinate_row.append(input)
def weave(self, other):
result = CoordinateRow()
length = len(self.coordinate_row)
for i in range(min(length, len(other))):
result.add(self.coordinate_row[i])
result.add(other.coordinate_row[i])
return result
This is a part of my program:
def verwerk_regel(regel):
cr = CoordinateRow()
coordinaten = regel.split()
for coordinaat in coordinaten:
verwerkt_coordinaat = verwerk_coordinaat(coordinaat)
cr.add(verwerkt_coordinaat)
cr2 = CoordinateRow()
cr12 = cr.weave(cr2)
print cr12
def verwerk_coordinaat(coordinaat):
coordinaat = coordinaat.split(",")
x = coordinaat[0]
y = coordinaat[1]
nieuw_coordinaat = Coordinate(x)
adjusted_x = nieuw_coordinaat.pas_x_aan()
return str(adjusted_x) + ',' + str(y)
But I'm geting an error at "cr12 = cr.weave(cr2)":
for i in range(min(length, len(other))):
TypeError: object of type 'CoordinateRow' has no len()
You need to add a __len__ method, then you can use len(self) and len(other):
class CoordinateRow(object):
def __init__(self):
self.coordinate_row = []
def add(self, input):
self.coordinate_row.append(input)
def __len__(self):
return len(self.coordinate_row)
def weave(self, other):
result = CoordinateRow()
for i in range(min(len(self), len(other))):
result.add(self.coordinate_row[i])
result.add(other.coordinate_row[i])
return result
In [10]: c = CoordinateRow()
In [11]: c.coordinate_row += [1,2,3,4,5]
In [12]: otherc = CoordinateRow()
In [13]: otherc.coordinate_row += [4,5,6,7]
In [14]:c.weave(otherc).coordinate_row
[1, 4, 2, 5, 3, 6, 4, 7]
Iterating over a range of len(something) is very much an anti-pattern in Python. You should be iterating over the contents of the containers themselves.
In your case, you can just zip the lists together and iterate over that:
def weave(self, other):
result = CoordinateRow()
for a, b in zip(self.coordinate_row, other.coordinate_row):
result.add(a)
result.add(b)
return result
Here is the complete solution for the Cart and Item class implementation.
class Item:
def __init__(self, name, price):
self.name = name
self.price = price
def getPrice(self):
return self.price
def getName(self):
return self.name
class ShoppingCart:
def __init__(self):
self.list = []
def __len__(self):
return len(self.list)
def add(self, item):
self.list.append(item)
def total(self):
total = 0
for item in self.list:
total = total + item.getPrice()
return total
other is of type CoordinateRow, which does not have a length. Use len(other.coordinate_row) instead. This is the list that does have the length property.
I need to operate on two separate infinite list of numbers, but could not find a way to generate, store and operate on it in python.
Can any one please suggest me a way to handle infinite Arithmetic Progession or any series and how to operate on them considering the fact the minimal use of memory and time.
Thanks every one for their suggestions in advance.
You are looking for a python generator instead:
def infinitenumbers():
count = 0
while True:
yield count
count += 1
The itertools package comes with a pre-built count generator.
>>> import itertools
>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> for i in itertools.islice(c, 5):
... print i
...
2
3
4
5
6
This is where the iterator comes in. You can't have an infinite list of numbers, but you can have an infinite iterator.
import itertools
arithmetic_progression = itertools.count(start,step) #from the python docs
The docs for Python2 can be found here
I have another python3 solution (read SICP chapter 3.5)
class Stream:
def __init__(self, head, tail):
self.head = head
self.tail = tail
self.memory = None
self.isDone = False
def car(self):
return self.head
def cdr(self):
if self.isDone:
return self.memory
self.memory = self.tail()
self.isDone = True
return self.memory
def __getitem__(self, pullFrom):
if pullFrom < 1 or self.memory == []:
return []
return [self.car()] + self.cdr()[pullFrom - 1]
def __repr__(self):
return "[" + repr(self.car()) + " x " + repr(self.tail) + "]"
def map(self, func):
if self.memory == []:
return []
return Stream(func(self.car()), lambda: Stream.map(self.cdr(), func))
def from_list(lst):
if lst == []:
return []
return Stream(lst[0], lambda:
Stream.from_list(lst[1:]))
def filter(self, pred):
if self.memory == []:
return []
elif pred(self.car()):
return Stream(self.car(), lambda: Stream.filter(self.cdr(), pred))
else:
return self.cdr().filter(pred)
def sieve(self):
return Stream(self.car(), lambda: self.cdr().filter(lambda n: n % self.car() > 0).sieve())
def foreach(self, action, pull = None):
if pull is None:
action(self.car())
self.cdr().foreach(action, pull)
elif pull <= 0:
return
else:
action(self.car())
self.cdr().foreach(action, pull-1)and run:
a = Stream(0, lambda: a.map((lambda x: x + 1)))
print(a[10])
which returns:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] .
But streams are lazily evaluated, so:
>>> a = Stream(0, lambda: a.map((lambda x: x + 1)))
>>> print(a)
prints:
[0 x [...]]
To create an object that acts like a "mutable" infinite list, you can overload the __getitem__ and __setitem__ methods in a class:
class infinite_list():
def __init__(self, func):
self.func = func
self.assigned_items = {}
def __getitem__(self, key):
if key in self.assigned_items:
return self.assigned_items[key]
else:
return self.func(key)
def __setitem__(self, key , value):
self.assigned_items[key] = value
Then, you can initialize the "infinite list" with a lambda expression and modify an item in the list:
infinite_thing = infinite_list(lambda a: a*2)
print(infinite_thing[1]) #prints "2"
infinite_thing[1] = infinite_thing[2]
print(infinite_thing[1]) #prints "4"
Similarly, it is possible to create an "infinite dictionary" that provides a default value for each missing key.
Perhaps the natural way to generate an infinite series is using a generator:
def arith(a, d):
while True:
yield a
a += d
This can be used like so:
print list(itertools.islice(arith(10, 2), 100))
My solution is:
from hofs import *
def cons_stream(head,tail):
return [head,tail,False,False]
def stream_cdr(strm):
if strm[2]:
return strm[3]
strm[3] = strm[1]()
strm[2] = True
return strm[3]
def show_stream(stream, num = 10):
if empty(stream):
return []
if num == 0:
return []
return adjoin(stream[0], show_stream(stream_cdr(stream), num - 1))
def add_streams(a , b):
if empty(a):
return b
if empty(b):
return a
return cons_stream(a[0] + b[0] , lambda : add_streams( stream_cdr(a), stream_cdr(b)))
def stream_filter( pred , stream ):
if empty(stream):
return []
if pred(stream[0]):
return cons_stream(stream[0], lambda : stream_filter(pred, stream_cdr(stream)))
else:
return stream_filter( pred , stream_cdr( stream ))
def sieve(stream):
return cons_stream(stream[0] , lambda : sieve(stream_filter(lambda x : x % stream[0] > 0 , stream_cdr(stream))))
ones = cons_stream(1, lambda : ones)
integers = cons_stream(1, lambda : add_streams(ones, integers))
primes = sieve(stream_cdr(integers))
print(show_stream(primes))
Copy the Python code above.
When I tried it, i got [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] which is 10 of an infinite list of primes.
You need hofs.py to be
def empty(data):
return data == []
def adjoin(value,data):
result = [value]
result.extend(data)
return result
def map(func, data):
if empty(data):
return []
else:
return adjoin(func(data[0]), map(func, data[1:]))
def keep(pred, data):
if empty(data):
return []
elif pred(data[0]):
return adjoin( data[0] , keep(pred, data[1:]))
else:
return keep(pred, data[1:])
I assume you want a list of infinite numbers within a range. I have a similar problem, and here is my solution:
c = 0
step = 0.0001 # the difference between the numbers
limit = 100 # The upper limit
myInfList = []
while c <= limit:
myInfList.append(c)
c = c + step
print(myInfList)
What's the most idiomatic way to write a class definition? There's no way that my code below is the best way to do this.
class Course:
crn = course = title = tipe = cr_hours = seats = instructor = days = begin = end = location = exam = ""
def __init__(self, pyQueryRow):
self.crn = Course.get_column(pyQueryRow, 0)
self.course = Course.get_column(pyQueryRow, 1)
self.title = Course.get_column(pyQueryRow, 2)
self.tipe = Course.get_column(pyQueryRow, 3)
self.cr_hours = Course.get_column(pyQueryRow, 4)
self.seats = Course.get_column(pyQueryRow, 5)
self.instructor = Course.get_column(pyQueryRow, 6)
self.days = Course.get_column(pyQueryRow, 7)
self.begin = Course.get_column(pyQueryRow, 8)
self.end = Course.get_column(pyQueryRow, 9)
self.location = Course.get_column(pyQueryRow, 10)
self.exam = Course.get_column(pyQueryRow, 11)
def get_column(row, index):
return row.find('td').eq(index).text()
[First of all python is an awesome language. This is my first project using python and I've made a ridiculous amount of progress already.]
def__init__(self, pyQueryRow):
for i,attr in enumerate("crn course title tipe cr_hours seats instructor"
" days begin end location exam".split()):
setattr(self, attr, self.get_column(pyQueryRow, i))
This way avoids multiple calls to self.get_column
def__init__(self, pyQueryRow):
attrs = ("crn course title tipe cr_hours seats instructor"
" days begin end location exam".split())
values = [td.text for td in pyQueryRow.find('td')]
for attr, value in zip(attrs, values):
setattr(self, attr, value)
Personally, I'd use a dictionary to map the property to column numbers:
class Course:
crn = course = title = tipe = cr_hours = seats = instructor = days = begin = end = location = exam = ""
def __init__(self, pyQueryRow):
course_row_mapping = {
'crn' : 0,
'course' : 1,
'title' : 2,
'tipe' : 3, # You probably mean "type"?
'cr_hours' : 4,
'seats' : 5,
'instructor' : 6,
'days' : 7,
'begin' : 8,
'end' : 9,
'location' : 10,
'exam' : 11,
}
for name, col in course_row_mapping.iteritems():
setattr(self, name, Course.get_column(pyQueryRow, col))
def get_column(row, index):
return row.find('td').eq(index).text()
I'm not sure that there is a "better" way. What you have is certainly quite readable. If you wanted to avoid duplicating the Course.get_column code you could define a lambda for that, as in Matthew Flaschen's answer, eg.
class Course:
def __init__(self, pyQueryRow):
get_column = lambda index: pyQueryRow.find('td').eq(index).text()
self.crn = get_column(0)
self.course = get_column(1)
self.title = get_column(2)
self.tipe = get_column(3)
self.cr_hours = get_column(4)
self.seats = get_column(5)
self.instructor = get_column(6)
self.days = get_column(7)
self.begin = get_column(8)
self.end = get_column(9)
self.location = get_column(10)
self.exam = get_column(11)
Note that you don't need the line that initialises all the fields to "" beforehand - just setting them in __init__ is fine. Edit: in fact, as Matthew says, that sets class fields, not instance fields - I totally missed that.
EDIT: Actually, the best might be:
self.crn, self.course, self.title, self.tipe, self.cr_hours, self.seats,\
self.instructor, self.days, self.begin, self.end, self.location, self.exam = \
[pq(td).text() for td in pyQueryRow.find('td')]
That assumes you've imported PyQuery as pq. This avoids ever using indices at all.
self.crn, self.course, self.title, self.tipe, self.cr_hours, self.seats,\
self.instructor, self.days, self.begin, self.end, self.location, self.exam = \
map(lambda index: get_column(pyQueryRow, index), xrange(0, 12))
or if you want a list comprehension:
self.crn, self.course, self.title, self.tipe, self.cr_hours, self.seats,\
self.instructor, self.days, self.begin, self.end, self.location, self.exam = \
[get_column(pyQueryRow, index) for index in xrange(0, 12)]
I don't know if these are the most idiomatic, but there's definitely less boilerplate.
Also, remove the crn = course =. You're assigning to the class, not the instance.
Personally I feel a class shouldn't really know about the outside world. So move it all out and your class looks much prettier. And also more reusable.
class Course:
def __init__(
self,
crn="",
course="",
title="",
tipe="",
cr_hours="",
seats="",
instructor="",
days="",
begin="",
end="",
location="",
exam=""
):
self.crn = crn
self.course = course
self.title = title
self.tipe = tipe
self.cr_hours = cr_hours
self.seats = seats
self.instructor = instructor
self.days = days
self.begin = begin
self.end = end
self.location = location
self.exam = exam
def course_from_row(row):
column_mapping = {
'crn': 0,
'course': 1,
'title': 2,
'tipe': 3,
'cr_hours': 4,
'seats': 5,
'instructor': 6,
'days': 7,
'begin': 8,
'end': 9,
'location': 10,
'exam': 11
}
course = {}
for attr, col in column_mapping.items():
course[attr] = row.find('td').eq(col).text()
return Course(**course)