Referencing a class' method, not an instance's - python

I'm writing a function that exponentiates an object, i.e. given a and n, returns an. Since a needs not be a built-in type, the function accepts, as a keyword argument, a function to perform multiplications. If undefined, it defaults to the objects __mul__ method, i.e. the object itself is expected to have multiplication defined. That part is sort of easy:
def bin_pow(a, n, **kwargs) :
mul = kwargs.pop('mul',None)
if mul is None :
mul = lambda x,y : x*y
The thing is that in the process of calculating an the are a lot of intermediate squarings, and there often are more efficient ways to compute them than simply multiplying the object by itself. It is easy to define another function that computes the square and pass it as another keyword argument, something like:
def bin_pow(a, n, **kwargs) :
mul = kwargs.pop('mul',None)
sqr = kwargs.pop('sqr',None)
if mul is None :
mul = lambda x,y : x*y
if sqr is None :
sqr = lambda x : mul(x,x)
The problem here comes if the function to square the object is not a standalone function, but is a method of the object being exponentiated, which would be a very reasonable thing to do. The only way of doing this I can think of is something like this:
import inspect
def bin_pow(a, n, **kwargs) :
mul = kwargs.pop('mul',None)
sqr = kwargs.pop('sqr',None)
if mul is None :
mul = lambda x,y : x*y
if sqr is None :
sqr = lambda x : mul(x,x)
elif inspect.isfunction(sqr) == False : # if not a function, it is a string
sqr = lambda x : eval('x.'+sqr+'()')
It does work, but I find it an extremely unelegant way of doing things... My mastery of OOP is limited, but if there was a way to have sqr point to the class' function, not to an instance's one, then I could get away with something like sqr = lambda x : sqr(x), or maybe sqr = lambda x: x.sqr(). Can this be done? Is there any other more pythonic way?

You can call unbound methods with the instance as the first parameter:
class A(int):
def sqr(self):
return A(self*self)
sqr = A.sqr
a = A(5)
print sqr(a) # Prints 25
So in your case you don't actually need to do anything specific, just the following:
bin_pow(a, n, sqr=A.sqr)
Be aware that this is early binding, so if you have a subclass B that overrides sqr then still A.sqr is called. For late binding you can use a lambda at the callsite:
bin_pow(a, n, sqr=lambda x: x.sqr())

here's how I'd do it:
import operator
def bin_pow(a, n, **kwargs) :
pow_function = kwargs.pop('pow' ,None)
if pow_function is None:
pow_function = operator.pow
return pow_function(a, n)
That's the fastest way. See also object.__pow__ and the operator module documentations.
Now, to pass an object method you can pass it directly, no need to pass a string with the name. In fact, never use strings for this kind of thing, using the object directly is much better.
If you want the unbound method, you can pass it just as well:
class MyClass(object):
def mymethod(self, other):
return do_something_with_self_and_other
m = MyClass()
n = MyClass()
bin_pow(m, n, pow=MyClass.mymethod)
If you want the class method, so just pass it instead:
class MyClass(object):
#classmethod
def mymethod(cls, x, y):
return do_something_with_x_and_y
m = MyClass()
n = MyClass()
bin_pow(m, n, pow=MyClass.mymethod)

If you want to call the class's method, and not the (possibly overridden) instance's method, you can do
instance.__class__.method(instance)
instead of
instance.method()
I'm not sure though if that's what you want.

If I understand the design goals of the library function, you want to provide a library "power" function which will raise any object passed to it to the Nth power. But you also want to provide a "shortcut" for efficiency.
The design goals seem a little odd--Python already defines the mul method to allow the designer of a class to multiply it by an arbitrary value, and the pow method to allow the designer of a class to support raising it to a power. If I were building this, I'd expect and require the users to have a mul method, and I'd do something like this:
def bin_or_pow(a, x):
pow_func = getattr(a, '__pow__', None)
if pow_func is None:
def pow_func(n):
v = 1
for i in xrange(n):
v = a * v
return v
return pow_func(x)
That will let you do the following:
class Multable(object):
def __init__(self, x):
self.x = x
def __mul__(self, n):
print 'in mul'
n = getattr(n, 'x', n)
return type(self)(self.x * n)
class Powable(Multable):
def __pow__(self, n):
print 'in pow'
n = getattr(n, 'x', n)
return type(self)(self.x ** n)
print bin_or_pow(5, 3)
print
print bin_or_pow(Multable(5), 5).x
print
print bin_or_pow(Powable(5), 5).x
... and you get ...
125
in mul
in mul
in mul
in mul
in mul
3125
in pow
3125

I understand it's the sqr-bit at the end you want to fix. If so, I suggest getattr. Example:
class SquarableThingy:
def __init__(self, i):
self.i = i
def squarify(self):
return self.i**2
class MultipliableThingy:
def __init__(self, i):
self.i = i
def __mul__(self, other):
return self.i * other.i
x = SquarableThingy(3)
y = MultipliableThingy(4)
z = 5
sqr = 'squarify'
sqrFunX = getattr(x, sqr, lambda: x*x)
sqrFunY = getattr(y, sqr, lambda: y*y)
sqrFunZ = getattr(z, sqr, lambda: z*z)
assert sqrFunX() == 9
assert sqrFunY() == 16
assert sqrFunZ() == 25

Related

python callback function returning None

I have a simple class that adds 2 nos. Before adding 2 nos I pass a helper function that appends 2 zeros and passes the result.
When I try to print the add_nos.provide(append_zeros) it always shows None.
def append_zeros(x,y):
x = int(str(x) + '00' )
y = int(str(y) + '00')
print x+y
return x + y
class Add_Nos():
def __init__(self,input_array):
self.input_array = input_array
def provide(self,callback):
for each in self.input_array:
x,y = each
callback(x,y)
add_nos = Add_Nos([(1,2),(3,4)])
print add_nos.provide(append_zeros)
The method add_nos.provide(self, callback) has no return statement, thus it returns nothing, which in python means that it returns None.
To avoid this, either add a return statement to provide() or simply call the method without print.
It's not entirely clear what you are trying to do, but provide does not return anything. In python, the default return type of any function is None, so implicitly printing add_nos.provide(append_zeros) will do the function call, and then return None behind the scenes.
One option you have is to return self.input_array:
class Add_Nos():
def __init__(self,input_array):
self.input_array = input_array
def provide(self,callback):
for each in self.input_array:
x,y = each
callback(x,y)
return self.input_array
Note that you can also do for x, y in self.input_array: :)
Presumably, you actually want to be getting a new list out with the result of the computation. In this case, this is an excellent candidate for a list comprehension:
def provide(self,callback):
return [callback(x, y) for x, y in self.input_array]
This is a one-line equivalent of doing
def provide(self, callback):
ret = []
for x, y in self.input_array:
ret.append(callback(x, y))
return ret
You said:
I want the result to be 300 in the first instance and 700 in the
next instance, kind of generate a iterator object.
So you simply need to turn the .provide method into a generator, and then call it appropriately. Like this:
def append_zeros(x,y):
x = int(str(x) + '00')
y = int(str(y) + '00')
#print x+y
return x + y
class Add_Nos():
def __init__(self,input_array):
self.input_array = input_array
def provide(self,callback):
for each in self.input_array:
x,y = each
yield callback(x,y)
add_nos = Add_Nos([(1,2),(3,4)])
for t in add_nos.provide(append_zeros):
print t
output
300
700
That append_zeros function is a bit strange. Rather than converting the args to strings so you can append the zeros and then converting the results back to ints to do the arithmetic yu should simply multiply each arg by one hundred.
Also, you can make the .provide method a little more streamlined by using "splat" unpacking. And as tyteen4a03 mentioned, in Python 2 your Add_Nos class ought to inherit from object so that you get a new-style class instead of the deprecated old-style class. So here's another version with those changes; it produces the same output as the above code.
def append_zeros(x, y):
return x * 100 + y * 100
class Add_Nos(object):
def __init__(self, input_array):
self.input_array = input_array
def provide(self, callback):
for each in self.input_array:
yield callback(*each)
add_nos = Add_Nos([(1,2),(3,4)])
for t in add_nos.provide(append_zeros):
print t

How to use inputs within the class?

I am new to python and object language. I am learning class in python now. but the code below confused me.
class math:
def __init__(self, a, b):
self.a = a
self.b = b
math.add = self.a+self.b
def sum(self):
math.sum = self.a+self.b
s= math(2,1)
x = math.add
y = math.sum
the results look not right. x is 3 but y is not 3. where is my problem?
thanks
I'm guessing what you wanted to do was this.
class math:
def __init__(self, a, b):
self.a = a
self.b = b
self.add = self.a+self.b
def sum(self):
return self.a+self.b
s= math(2,1)
x = s.add
y = s.sum()
print(x)
print(y)
The errors were as follows
You were not calling your instance of math. As these are instance methods, they must reference an instance x = math.add should be x = s.add.
You created a method sum but did not call it y = s.sum simply creates a reference to the function and does not call it, instead you should use y = s.sum()
Your function sum doesn't return anything, so assigning a value to its return value will yield a value of None. To resolve this return a value from sum i.e. return self.a + self.b.
self.add is also quite strange, as it named like a function, but its actually a value, this will not be expected by others looking at your code. A better name for it might be total or remove it since it provides the same functionality as sum.

How to compose to functions several times?

I'm supposed to write a code which gets a mathematical function and a number and gives me as an output a function that is composed n times.
For example if n=3 I would get f(f(f(x))).
When I run my code I get an error, what should I fix in it?
Running examples :
>>> repeated(lambda x:x*x, 2)(5)
624
>>> repeated(lambda x:x*x, 4)(3)
43046721
This is my code :
def repeated(f, n):
g=f
for i in range(n):
g=lambda x: (g(g(x)))
return (g)
Return a new function that does the repeated applying only when called:
def repeated(f, n):
def repeat(arg):
return reduce(lambda r, g: g(r), [f] * n, arg)
return repeat
The reduce() method uses the list of f function references to create the right number of nested calls, starting with arg as the first argument.
Demo:
>>> def repeated(f, n):
... def repeat(arg):
... return reduce(lambda r, g: g(r), [f] * n, arg)
... return repeat
...
>>> repeated(lambda x:x*x, 2)(5)
625
>>> repeated(lambda x:x*x, 4)(3)
43046721
A version that doesn't use reduce() would be:
def repeated(f, n):
def repeat(arg):
res = arg
for _ in range(n):
res = f(res)
return res
return repeat
Depending on the context of your task (e.g. programming class), you might be interested in following straightforward solution:
def repeated(f, n):
if n < 1:
raise ValueError()
elif n == 1:
return f
else:
return lambda x: repeated(f, n-1)(f(x))
This is a naive recursive solution, which maps more directly to the requirements. If you already know about higher functions, such as reduce I suggest to go with Martijn Pieters solutions. Nevertheless this does work:
>>> repeated(lambda x:x*x, 2)(5)
625
>>> repeated(lambda x:x*x, 4)(3)
43046721
I thought this was an interesting enough problem that I wanted to think about it for a couple days before answering. I've created a set of generalizable, pythonic (I think), ways for composing a function on itself in the way described in the question. The most generic solution is just nest, which returns a generator that yields successively nested values of the function on the initial argument. Everything else builds off that, but the decorators could be implemented using one of the above solutions, as well.
#!/usr/bin/env python
"""
Attempt to create a callable that can compose itself using operators
Also attempt to create a function-composition decorator.
f(x) composed once is f(x)
f(x) composed twice is f(f(x))
f(x) composed thrice is f(f(f(x)))
This only makes sense at all if the function takes at least one argument:
f() * 2 -> f(?)
But regardless of its arity, a function can only return exactly one value (even if that value is iterable). So I don't think it makes sense for the function to have >1 arity, either. I could unpack the result:
f(x, y) * 2 -> f(*f(x, y))
But that introduces ambiguity -- not every iterable value should be unpacked. Must I inspect the function to tell its arity and decide whether or not to unpack on the fly? Too much work!
So for now, I just ignore cases other than 1-arity.
"""
def nest(func, arg):
"""Generator that calls a function on the results of the previous call.
The initial call just returns the original argument."""
while True:
yield arg
arg = func(arg)
def compose(n):
"""Return a decorator that composes the given function on itself n times."""
if n < 1: raise ValueError
def decorator(func):
def nested(arg):
gen = nest(func, arg)
for i in range(n):
next(gen)
return next(gen)
return nested
return decorator
class composable(object):
"""A callable that can be added and multiplied."""
def __init__(self, func):
self.func = func
def __add__(self, func2):
"""self(func2(x))"""
def added(a):
return self(func2(a))
return composable(added)
def __mul__(self, n):
"""self * 3 => self(self(self(a)))"""
def nested(a):
gen = nest(self, a)
for i in range(n):
next(gen)
return next(gen)
return composable(nested)
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
#compose(2)
def sq(x):
return x*x
#compose(4)
def qu(x):
return x*x
#composable
def add1(x):
return x + 1
compset = composable(set)
assert (compset + str.split)('abc def') == set(['abc', 'def']), (compset + str.split)('abc def')
assert add1(1) == 2, add1(1)
assert (add1 + (lambda x: x * x))(4) == 17, (add1 + (lambda x: x * x))(4)
assert (add1 * 3)(5) == 8, (add1 * 3)(5)
assert 625 == sq(5), sq(5)
assert 43046721 == qu(3), qu(3)

Implementing pointwise arithmetic with implicit type conversion

Suppose I have class Function, whose instances are callables that take one argument. I defined pointwise arithmetic for these classes in the straightforward way. Here's a simplified version of my code (I actually have more complex behavior in __init__ and __call__ but it's irrelevant for this question):
class Function:
'''
>>> f = Function(lambda x : x**2)
>>> g = Function(lambda x : x + 4)
>>> h = f/g
>>> h(6)
3.6
'''
def __init__(self, func):
self.func = func
def __call__(self, value):
return self.func(value)
def __truediv__(self, other):
if isinstance(other, Function):
return Function(lambda x:self(x)/other(x))
else:
return NotImplemented
# ...
I'm stuck when I try to allow implicit type conversions. For example, I want to be able to write:
>>> f = Function(lambda x : x ** 2)
>>> g = f+1
>>> g(5)
26
In other words, whenever I see a numeric object v in an arithmetic expression next to a Function instance, I want to convert v to Function(lambda x : v).
In addition, I want to achieve similar behavior for some of my user-defined types (again, whenever I see them in the same binary arithmetic expression with a Function object).
While I can certainly code this logic with a brute force assortment of regular and reflected binary arithmetic operators, each checking isinstance(v, numbers.Number), and isinstance(v, MyUserDefinedType), I feel there might be a more elegant way.
Also, if there are any other improvements possible with my design, please let me know. (Function objects are created rarely, but called very often, so performance is of some interest.)
EDIT:
To address #Eric's comment, I should clarify that I have another user-defined class Functional:
class Functional:
'''
>>> c = [1, 2, 3]
>>> f = Functional(lambda x : x + 1)
>>> f(c)
[2, 3, 4]
>>> g = Functional(lambda x : x ** 2)
>>> h = f + g
>>> h(c)
[3, 7, 13]
'''
def __init__(self, func):
self.func = func
#staticmethod
def from_function(self, function):
return Functional(function.func)
def __call__(self, container):
return type(container)(self.func(c) for c in container)
def __add__(self, other):
if isinstance(other, Functional):
return Functional(lambda x : self.func(x) + other.func(x))
else:
return NotImplemented
When I see both a Function and a Functional instance in the same arithmetic expression, I want Function to be implicitly converted to Functional using Functional.from_function method.
So, implicit type conversion hierarchy goes like this:
Functional
Function
anything else
And I'd like to implicitly convert to the highest type in this hierarchy seen in a given arithmetic expression.
Something like this for all operators would work well:
def __truediv__(self, other):
if callable(other):
return Function(lambda x:self(x)/other(x))
else:
return Function(lambda x:self(x)/other)
One option is to make all the operators in your Function class accept arbitrary values, which will be applied to the result of the underlying function if they're not functions themselves. For example, to extend allow f / 5, when f is a Function, simply modify the __truediv__ implementation you have to:
def __truediv__(self, other):
if isinstance(other, Function):
return Function(lambda x:self(x)/other(x))
else:
return Function(lambda x:self(x)/other)
You can optionally do some type checking to make sure that's sane (and raise errors early rather than later on), but it works without that.
After reading the comments and the other answers, I tried this approach. I'm posting it to ask for feedback. I like that I can handle both Function and Functional in one swoop, but I'm afraid it might be very expensive in terms of performance:
class Function:
'''
>>> f = Function(lambda x : x**2)
>>> g = Function(lambda x : x + 4)
>>> h = f/g
>>> h(6)
3.6
>>> k = f + 1
>>> k(5)
26
>>> m = f + (lambda x : x + 1)
>>> m(5)
31
'''
def __init__(self, arg):
if isinstance(arg, Function):
self.func = arg.func
elif callable(arg):
self.func = arg
else:
self.func = lambda x : arg
def __call__(self, value):
return self.func(value)
def __truediv__(self, other):
return self.__class__(lambda x:Function(self)(x)/Function(other)(x))
def __rtruediv__(self, other):
return self.__class__(lambda x:Function(other)(x)/Function(self)(x))
def __add__(self, other):
return self.__class__(lambda x:Function(self)(x)+Function(other)(x))
def __radd__(self, other):
return self.__class__(lambda x:Function(other)(x)+Function(self)(x))
# ...
class Functional(Function):
'''
>>> c = [1, 2, 3]
>>> f = Functional(lambda x : x + 1)
>>> f(c)
[2, 3, 4]
>>> g = Functional(lambda x : x ** 2)
>>> h = f + g
>>> h(c)
[3, 7, 13]
'''
def __call__(self, container):
return type(container)(self.func(c) for c in container)

__add__ all elements of a list

I'd like to combine a list of class instances of a class for which the __add__ method is defined.
i.e., I have a list of class instances L=[A,B,C,D] and I want their sum E = A+B+C+D, but generalized so that instead of the + syntax I could do something like E = sum(L).
What function should I use to do that? Is the __add__ method adequate, or do I need to define a different class method (e.g. __iadd__) in order to accomplish this?
(if this turns out to be a duplicate, how should I be asking the question?)
import operator
reduce(operator.add, L)
sum may want to add numerical values to instances of your class. Define __radd__ so for example int + Foo(1) will be defined:
class Foo(object):
def __init__(self, val):
self.val = val
def __add__(self, other):
return self.val + other.val
def __radd__(self, other):
return other + self.val
A = Foo(1)
B = Foo(2)
L = [A,B]
print(A+B)
# 3
print(sum(L))
# 3
Ignore my previous answer, it was wrong.
The reduce function allows you to apply any binary function or method to all the elements of a sequence. So, you could write:
reduce(YourClass.__add__, sequence)
If not all objects in the sequence are instances of the same class, then instead use this:
import operator
reduce(operator.add, sequence)
Or this:
reduce(lambda x, y: x + y, sequence)

Categories

Resources