I am trying to create python classes from a program that I wrote in functions only. So the code is working fine with functions but giving an error/errors when I convert the code to python classes.
Functions:
def eachList(index):
Series=df_ideal.iteritems()
bigList = []
for (columnName,item) in Series:
bigList.append(item)
return bigList[index]
def isResult(listing):
mylist=[]
for i in range(len([column_name for column_name in df_ideal])):
result = map(lambda x:x*x,residual(listing,eachList(i)))
Sum = int(sum(result))
mylist.append(Sum)
return(mylist)
With Classes
class Task1:
def __init__(self,train,ideal):
self.train = train
self.ideal = ideal
def __str__(self):
return self.ideal[index]
def residual(self,lst1,lst2):
self.subtracted = []
for item1,item2 in zip(lst1,lst2):
self.subtracted.append(item1-item2)
return self.subtracted
def eachList(self,index):
Series=df_ideal.iteritems()
self.bigList = []
for (columnName,item) in Series:
self.bigList.append(item)
return self.bigList[index]
Inheritance
class Resultant(Task1):
def __init__(self,train,ideal):
super().__init__(train,ideal)
def isResult(self,listing):
mylist=[]
for i in range(len([column_name for column_name in df_ideal])):
result = map(lambda x:x*x,Task1.residual(listing,Task1.eachList(i)))
Sum = int(sum(result))
mylist.append(Sum)
return(mylist)
The error you're hitting (I'm guessing) is that you're calling Task1.residual as if it's a class method, when it's not:
result = map(lambda x:x*x,Task1.residual(listing,Task1.eachList(i)))
For this to work you should be calling self.residual.
However, I think it would be better to just have a simple set of functions, since there's nothing in the implementation of these functions that requires any kind of persistent state to be shared between them. The logic is simple enough that each could be written as a single list comprehension:
def eachList():
return [item for _columnName, item in df_ideal.iteritems()]
def residual(lst1, lst2):
return [item1 - item2 for item1, item2 in zip(lst1, lst2)]
def isResult(listing):
return [sum(x * x for x in residual(listing, item)) for item in eachList()]
Related
I have the following simplified code:
class States:
def __init__(self):
pass
def state1(self):
a = 2*10
return a
def state2(self):
a = 50/10
return a
class Results:
def __init__(self):
pass
def result(self):
states = States()
x = []
for i in [state1,state2]:
state_result = states.i()
x.append(state_result)
return x
I want to loop through every function in the class "States". Of course
for i in [state1,state2]
will return "name 'state1' is not defined", but I hope it gives an idea what I try to achieve.
You can use dir() to get the name of the functions of a class. You can then use getattr() to call the function.
class States:
def __init__(self):
pass
def state1(self):
a = 2*10
return a
def state2(self):
a = 50/10
return a
state = States()
for func in dir(States):
if func.startswith('__'):
continue
print(func)
print(getattr(state, func)())
Will output
state1
20
state2
5.0
You can do this tho:
def result(self):
states = States()
x = []
for i in [states.state1,states.state2]: # changed state1 to states.state1 and so on
state_result = i()
x.append(state_result)
return x
I think you can use lambda. Here, i made a simple example for you.
def foo(text):
print(text)
a = [lambda: foo("hey"), lambda: foo("boo")]
for i in a:
i()
Result:
hey
boo
In your case, you should come over with this:
for i in [lambda: state1(), lambda:state2()]:
state_result = i()
x.append(state_result)
But if you ask my opinion, it's important to inform you that calling functions through a list is not a healthy way. A software languge usually has a solution for many cases; but in this case, i think your point of view is wrong. Doing work by messing with built-in techniques and trying to find some secret tricks is is not a suggested thing.
The clean way to do this is to "register" your state methods. SOmething like this:
class States():
states = []
def register_state(cache):
def inner(fn):
cache.append(fn)
return inner
#register_state(states)
def state1(self):
a = 2*10
return a
#register_state(states)
def state2(self):
a = 50/10
return a
Then your Results class can do
class Results:
def __init__(self):
pass
def result(self):
states = States()
x = []
for i in states.states:
state_result = i(states)
x.append(state_result)
return x
You can get the members of class States via the class' dict as:
States.__dict__
Which'll give you all the attributes and function of your class as:
{'__module__': '__main__', '__init__': <function States.__init__ at 0x00000183066F0A60>, 'state1': <function States.state1 at 0x00000183066F0AF0>, 'state2': <function States.state2 at 0x000001830 ...
You can filter this into a list comprehension dict to not include dunders as:
[funcname for funcname in States.__dict__ if not (str.startswith('__') and str.endswith('__'))]
This will return you a list of member functions as:
['state1', 'state2']
Then create an object of States as:
states = States()
get the whole calculation done as:
for funcname in [funcname for funcname in States.__dict__ if not (funcname.startswith('__') and funcname.endswith('__'))]:
x.append(States.__dict__[funcname](states))
Better yet, make it a comprehension as:
[States.__dict__[funcname](states) for funcname in States.__dict__ if not (funcname.startswith('__') and funcname.endswith('__'))]
Your answer after applying this approach is: [20, 5.0]
or get the dict of functionName and returnValues as a comprehension:
{funcname: States.__dict__[funcname](states) for funcname in States.__dict__ if not (funcname.startswith('__') and funcname.endswith('__'))}
Which'll give you an output as:
{'state1': 20, 'state2': 5.0}
I am writing a python library that will be called by a pyspark code. As part of this library there is a slow function.
I would like to cache the results of this function so that a table is kept in memory. (At least in each worker).
For example:
def slow_function(x):
time.sleep(10)
return x*2
class CacheSlowFunction():
def __init__(self):
self.values = {}
def slow_function(x):
if x in self.values:
return self.values[x]
else:
res = slow_function(x)
self.values[x] = res
return res
def main(x):
csf = CacheSlowFunction()
s = 0
for i in range(x):
s += csf.slow_function(i)
return s
and the code is called from spark with something like:
map(main, [i for i in range(10000)])
Now the code will create a table (self.values) for each call. Is it possible to have this table at least shared across computations done on the same worker?
I am working on some project, and we have lots of some code usage like this;
# filtering fields are different from each other, please ignore the similarity below
def function1(self, param):
list_x = Model1.objects.filter(foo=bar, bla=bla).values_list('field', flat=True)
list_y = Model2.objects.filter(foo=bar, bla=bla).values_list('field', flat=True)
lists_to_delete = set(list_x) - set(list_y)
# here is the code line with set() that needed to be method
self._delete(lists_to_delete)
def function2(self, param):
list_z = Model3.objects.filter(foo=bar, bla=bla).values_list('field', flat=True)
list_q = Model4.objects.filter(foo=bar, bla=bla).values_list('field', flat=True).distinct()
list_w = Model5.objects.filter(foo=bar, bla=bla).values_list('field', flat=True)
lists_to_delete = set(list_x) - set(list_y) - set(list_w)
# here is the code line with set() that needed to be method
self._delete(lists_to_delete)
... # other functions continues like above
...
...
So, as you can see we have same usage with set() function. And I need to change this usage with custom method. I tried to write a method like this;
def _get_deleted_lists(self, *args):
value = set()
for arg in args:
value |= set(arg)
return value
and usage will be change like;
lists_to_delete = self._get_deleted_lists(list_x, list_y, ...)
instead of this;
lists_to_delete = set(list_x) - set(list_y)
But my custom method not return same value as before. How can I achieve this?
| operation on sets returns their union. What you want is the difference (-)
def _get_deleted_lists(*lists):
if not lists:
return set()
result = set(lists[0])
for l in lists[1:]:
result -= set(l)
return result
In Clojure I can do something like this:
(-> path
clojure.java.io/resource
slurp
read-string)
instead of doing this:
(read-string (slurp (clojure.java.io/resource path)))
This is called threading in Clojure terminology and helps getting rid of a lot of parentheses.
In Python if I try to use functional constructs like map, any, or filter I have to nest them to each other. Is there a construct in Python with which I can do something similar to threading (or piping) in Clojure?
I'm not looking for a fully featured version since there are no macros in Python, I just want to do away with a lot of parentheses when I'm doing functional programming in Python.
Edit: I ended up using toolz which supports pipeing.
Here is a simple implementation of #deceze's idea (although, as #Carcigenicate points out, it is at best a partial solution):
import functools
def apply(x,f): return f(x)
def thread(*args):
return functools.reduce(apply,args)
For example:
def f(x): return 2*x+1
def g(x): return x**2
thread(5,f,g) #evaluates to 121
I wanted to take this to the extreme and do it all dynamically.
Basically, the below Chain class lets you chain functions together similar to Clojure's -> and ->> macros. It supports both threading into the first and last arguments.
Functions are resolved in this order:
Object method
Local defined variable
Built-in variable
The code:
class Chain(object):
def __init__(self, value, index=0):
self.value = value
self.index = index
def __getattr__(self, item):
append_arg = True
try:
prop = getattr(self.value, item)
append_arg = False
except AttributeError:
try:
prop = locals()[item]
except KeyError:
prop = getattr(__builtins__, item)
if callable(prop):
def fn(*args, **kwargs):
orig = list(args)
if append_arg:
if self.index == -1:
orig.append(self.value)
else:
orig.insert(self.index, self.value)
return Chain(prop(*orig, **kwargs), index=self.index)
return fn
else:
return Chain(prop, index=self.index)
Thread each result as first arg
file = Chain(__file__).open('r').readlines().value
Thread each result as last arg
result = Chain(range(0, 100), index=-1).map(lambda x: x * x).reduce(lambda x, y: x + y).value
I have a function which returns a list of objects (I used the code below for example). Each object has attribute called text:
def mylist():
mylist = []
for i in range(5):
elem = myobject(i)
mylist.append(elem)
return mylist
for obj in mylist():
print obj.text
How can I rewrite this code so mylist() returned each iteration new value and I iterate over iterator? In other words how can I reuse here a mylist in python so use it like xrange()?
If I understood right, you're looking for generators:
def mylist():
for i in range(5):
elem = myobject(i)
yield elem
Complete code for you to play with:
class myobject:
def __init__(self, i):
self.text = 'hello ' + str(i)
def mylist():
for i in range(5):
elem = myobject(i)
yield elem
for obj in mylist():
print obj.text
You can also use a generator expression:
mylist = (myobject(i) for i in range(5))
This will give you an actual generator but without having to declare a function beforehand.
Please note the usage of parentheses instead of brackets to denote a generator comprehension instead of a list comprehension
What georg said, or you can return the iter of that list
def mylist():
mylist = []
for i in range(5):
mylist.append(myobject(i))
return iter(mylist)
probably not a good idea to use your function name as a variable name, though :)
llist = [0,4,5,6]
ii = iter(llist)
while (True):
try:
print(next(ii))
except StopIteration:
print('End of iteration.')
break