Static lambdas in python - python

I have class in python like this
import numpy as np
class BackPropogationNetwork:
# Static lambdas
sigmoid = lambda x : 1/(1+np.exp(-x))
sigmoid_prime = lambda sigmoid: sigmoid(1-sigmoid)
and this is the contructor
def __init__(self):
self.some_attr = self.sigmoid(2)
I get this error
TypeError: <lambda>() takes exactly 1 argument (2 given)
If I call like this
self.some_attr = ClassName.sigmoid()
I get this error
TypeError: unbound method <lambda>() must be called with BackPropogationNetwork instance as first argument (got int instance instead)

You need to wrap the lambdas in staticmethod objects:
class BackPropogationNetwork:
sigmoid = staticmethod(lambda x : 1/(1+np.exp(-x)))
sigmoid_prime = staticmethod(lambda sigmoid: sigmoid(1-sigmoid))
lambda expressions still produce function objects, just using different (limited) syntax. The same rules apply as defining functions in a class; if you want it to be a static method then you still need to wrap them.

So your sigmoid function is kinda independent of the class, it would make sense to keep it outside, unless:
you want to not pollute the namespace of the module
you want to increase the discoverability of the function
you want this method to me overwritten.
Let's assume you have made up your mind and nothing can change it, well in that case you can do this.
When you call a method like self.method() python passes the the first argument to the funtion the instance self, so either you can make you lambda like this: sigmoid = lambda self, x : 1/(1+np.exp(-x))
or you can do what others have suggested like make it a staticmethod, since staticmethod is a decorator, (function that takes a function) it can be called like this
In [1]: class A:
...: s = staticmethod(lambda x: x)
...: def a(self):
...: print self.s(10)
...:
In [2]: f = A()
In [3]: f.a()
10

Your two sigmoid's are not class methods. This means when you call them they expect Class as the implicit first argument.
This error
TypeError: <lambda>() takes exactly 1 argument (2 given)
occurs on this call
self.some_attr = self.sigmoid(2)
because Class instance object is being passed implicitly along with the int 2. But your sigmoid is defined to accept only one argument.
And I don't think you will get this error
TypeError: unbound method <lambda>() must be called with BackPropogationNetwork instance as first argument (got int instance instead)
with this call
self.some_attr = ClassName.sigmoid()
The error you should get should be something like.
TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'type'
May be you made a copy paste error while typing the question.

Related

TypeError: Mean() missing 1 required positional argument: 'data'

I'm trying to program a basic mean calculator using classes. However, I'm getting the error
TypeError: Mean() missing 1 required positional argument: 'data'
I have two files: one which contains the class with the mean function and then one which calls it, and that is when I'm getting the error. My code is:
class Statistics:
def __init__(self,mean_x,mean_y,var,covar):
self.mean_x=mean_x
self.mean_y=mean_y
self.var=var
self.covar=covar
def Mean(self,data):
return sum(data)/float(len(data))
And the code which throws the error is:
from Statistics import Statistics
X=(0,1,3,5)
mean_x=Statistics.Mean(X)
print(mean_x)
Mean is an instance method, so you need to call it on an instance (which will become the self argument for the method invocation).
statistics = Statistics(None, None, None, None)
mean_x = statistics.Mean((0, 1, 3, 5))
Since the parameters on Statistics.__init__ aren't used I'd suggest removing them (or just removing the __init__ altogether):
class Statistics:
def mean(self, data):
return sum(data)/float(len(data))
from Statistics import Statistics
X = (0,1,3,5)
statistics = Statistics()
mean_x = statistics.mean(X)
print(mean_x)
Note that Python comes with a statistics module that has a mean function built in:
import statistics
X = (0,1,3,5)
mean_x = statistics.mean(X)
print(mean_x)
You define the instance method, but there is no instance.
Also, it is better to change the 'Mean' to 'mean'.

pass class method to fsolve

I have the following code:
import scipy.optimize
class demo(object):
def get_square(self, var):
return var ** 2 - 4
new = demo()
scipy.optimize.fsolve(new.get_square(), 1)
And I got the following error:
TypeError: get_square() missing 1 required positional argument: 'var'
But get_square() should always have self and self need not be passed. What's the problem?
You're actually calling the function before fsolve has a change to do anything; since the call has no arguments this will raise the expected TypeError.
You could either remove the call () to new.get_square:
scipy.optimize.fsolve(new.get_square, 1)
or, since you aren't actually even using self in get_square, make it a #staticmethod:
class demo(object):
#staticmethod
def get_square(var):
return var ** 2 - 4
new = demo()
scipy.optimize.fsolve(new.get_square, 1)
Two small notes:
Use CapWords for class names, that is, demo -> Demo.
If you aren't trying to be portable between Python 2/3, no need to inherit from object.

Passing multiple arguments to pool.map using class function

I'm trying to thread as described in this post, and also pass multiple arguments in Python 2.7 through a work-around described here.
Right now I have something like this, a function that is part of class pair_scraper:
def pool_threading(self):
pool = ThreadPool(4)
for username in self.username_list:
master_list = pool.map(self.length_scraper2,
itertools.izip(username*len(self.repo_list),
itertools.repeat(self.repo_list)))
def length_scraper2(self, username, repo):
#code
However, when I run my code I get the error:
TypeError: length_scraper2() takes exactly 3 arguments (2 given)
Which seems to be because it wants self passed as an argument, which is nonsensical given I'm using a class function within the class. Thoughts on how to fix?
itertools.izip(username*len(self.repo_list),itertools.repeat(self.repo_list)) yields a tuple.
You need to pass 2 arguments explicitly to your method (self is implicitly passed because it's a non-static method), but you only pass 1 tuple explicitly, plus the implicit self which makes 2 arguments, hence the confusing error message.
You have to use * to pass your tuple as 2 separate arguments, like this:
master_list = pool.map(self.length_scraper2,
*itertools.izip(username*len(self.repo_list),itertools.repeat(self.repo_list)))
simple test using the classical map on a simple function:
def function(b,c):
return (b,c)
print(list(map(function,zip([1,2],[4,5]))))
error:
print(list(map(function,zip([1,2],[4,5]))))
TypeError: function() missing 1 required positional argument: 'c'
now adding single asterisk to expand args:
print(list(map(function,*zip([1,2],[4,5]))))
works:
[(1, 2), (4, 5)]
same goes for class method:
class Foo:
def function(self,b,c):
return (b,c)
f = Foo()
print(list(map(f.function,*zip([1,2],[4,5]))))

Declaring a function in a parameter list in python

I'm looking to build a generic object for curve fitting, where I define parameter names, values and bounds. Sometimes, I want to use the incoming data to help define the bounds using a function (min, max, etc.).
Here is the object:
class CurveFitObject(object):
def __init__(self,paramList,growthEquation):
self.paramList = paramList
self.gmod = Model(growthEquation)
def calcCurveFit(data):
for param in self.paramList:
self.gmod.set_param_hint(self.paramList['name'],
value=self.paramList['value'](data),
min=self.paramList['min'](data),
max=self.paramList['max'](data))
Here I am trying to use np.min(data) as my guess, 0.975 * np.min(data) as my lower bound, and 1.025 * np.min(data) as my upper bound.
def growthEquation(self, t, A): return A
keys = ['name','guess','min','max','vary']
logisticGrowth = CurveFitObject(
[dict(zip(keys,['A',np.min,0.975*np.min,1.025*np.min,True])),
growthEquation
)
I get the following error: TypeError: unsupported operand type(s) for *: 'float' and 'function'
which makes sense since it's trying to do math on the function 0.975*np.min rather than 0.975*np.min(data).
What is the best way to implement this behavior? If any?
It looks like you want to create a wrapper for an existing function. For example, you have:
0.975*np.min
But this doesn't work, since it's trying to multiply a float times a function. You can create a new function inline by using:
lambda data: 0.957*np.min(data)
This is probably what you're looking for. It's equivalent to defining a named function:
def myfunc(data):
return 0.957*np.min(data)
and then using myfunc. The difference is that the lambda syntax creates an anonymous function that can be defined inline.

class method generates "TypeError: ... got multiple values for keyword argument ..."

If I define a class method with a keyword argument thus:
class foo(object):
def foodo(thing=None, thong='not underwear'):
print thing if thing else "nothing"
print 'a thong is',thong
calling the method generates a TypeError:
myfoo = foo()
myfoo.foodo(thing="something")
...
TypeError: foodo() got multiple values for keyword argument 'thing'
What's going on?
The problem is that the first argument passed to class methods in python is always a copy of the class instance on which the method is called, typically labelled self. If the class is declared thus:
class foo(object):
def foodo(self, thing=None, thong='not underwear'):
print thing if thing else "nothing"
print 'a thong is',thong
it behaves as expected.
Explanation:
Without self as the first parameter, when myfoo.foodo(thing="something") is executed, the foodo method is called with arguments (myfoo, thing="something"). The instance myfoo is then assigned to thing (since thing is the first declared parameter), but python also attempts to assign "something" to thing, hence the Exception.
To demonstrate, try running this with the original code:
myfoo.foodo("something")
print
print myfoo
You'll output like:
<__main__.foo object at 0x321c290>
a thong is something
<__main__.foo object at 0x321c290>
You can see that 'thing' has been assigned a reference to the instance 'myfoo' of the class 'foo'. This section of the docs explains how function arguments work a bit more.
Thanks for the instructive posts. I'd just like to keep a note that if you're getting "TypeError: foodo() got multiple values for keyword argument 'thing'", it may also be that you're mistakenly passing the 'self' as a parameter when calling the function (probably because you copied the line from the class declaration - it's a common error when one's in a hurry).
This might be obvious, but it might help someone who has never seen it before. This also happens for regular functions if you mistakenly assign a parameter by position and explicitly by name.
>>> def foodo(thing=None, thong='not underwear'):
... print thing if thing else "nothing"
... print 'a thong is',thong
...
>>> foodo('something', thing='everything')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foodo() got multiple values for keyword argument 'thing'
This error can also happen if you pass a key word argument for which one of the keys is similar (has same string name) to a positional argument.
>>> class Foo():
... def bar(self, bar, **kwargs):
... print(bar)
...
>>> kwgs = {"bar":"Barred", "jokes":"Another key word argument"}
>>> myfoo = Foo()
>>> myfoo.bar("fire", **kwgs)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() got multiple values for argument 'bar'
>>>
"fire" has been accepted into the 'bar' argument. And yet there is another 'bar' argument present in kwargs.
You would have to remove the keyword argument from the kwargs before passing it to the method.
just add 'staticmethod' decorator to function and problem is fixed
class foo(object):
#staticmethod
def foodo(thing=None, thong='not underwear'):
print thing if thing else "nothing"
print 'a thong is',thong
I want to add one more answer :
It happens when you try to pass positional parameter with wrong
position order along with keyword argument in calling function.
there is difference between parameter and argument you can read in detail about here Arguments and Parameter in python
def hello(a,b=1, *args):
print(a, b, *args)
hello(1, 2, 3, 4,a=12)
since we have three parameters :
a is positional parameter
b=1 is keyword and default parameter
*args is variable length parameter
so we first assign a as positional parameter , means we have to provide value to positional argument in its position order, here order matter.
but we are passing argument 1 at the place of a in calling function and then we are also providing value to a , treating as keyword argument.
now a have two values :
one is positional value: a=1
second is keyworded value which is a=12
Solution
We have to change hello(1, 2, 3, 4,a=12) to hello(1, 2, 3, 4,12)
so now a will get only one positional value which is 1 and b will get value 2 and rest of values will get *args (variable length parameter)
additional information
if we want that *args should get 2,3,4 and a should get 1 and b should get 12
then we can do like this
def hello(a,*args,b=1):
pass
hello(1, 2, 3, 4,b=12)
Something more :
def hello(a,*c,b=1,**kwargs):
print(b)
print(c)
print(a)
print(kwargs)
hello(1,2,1,2,8,9,c=12)
output :
1
(2, 1, 2, 8, 9)
1
{'c': 12}
Also this can happen in Django if you are using jquery ajax to url that reverses to a function that doesn't contain 'request' parameter
$.ajax({
url: '{{ url_to_myfunc }}',
});
def myfunc(foo, bar):
...

Categories