Reputation: 4921
I found out that functools
module of Python 3 has two very similar methods: partial
and partialmethod
.
Can someone provide good examples of using each one?
Upvotes: 27
Views: 12489
Reputation: 681
partialmethod
is designed to take over the Python class
's self
argument which is different from partial
. And what is made from partialmethod
is actually partial
. here's code example
from functools import partial, partialmethod
class Cell:
def __init__(self):
self._alive = False
@property
def alive(self):
return self._alive
def set_state(self, state):
self._alive = state
partialmethod
class Cell:
...
set_alive = partialmethod(set_state, True)
>>> c = Cell()
>>> c.alive
False
>>> c.set_alive
functools.partial(<bound method Cell.set_state of <__main__.Cell object at 0x7f2a77bded90>>, True)
>>> c.set_alive()
>>> c.alive
True
partial
#1: it acts like 1. partialmethod
code.class Cell:
...
def set_alive(self):
partial(self.set_state, True)()
>>> c = Cell()
>>> c.alive
False
>>> c.set_alive
<bound method Cell.set_alive of <__main__.Cell object at 0x7f2a77b37850>>
>>> c.set_alive()
>>> c.alive
True
partial
#2: it returns same as the 1. partialmethod
's result. it called later at promptclass Cell:
...
def set_alive(self):
return partial(self.set_state, True)
>>> c = Cell()
>>> c.alive
False
>>> c.set_alive
<bound method Cell.set_alive of <__main__.Cell object at 0x7f2a77b37850>>
>>> c.set_alive()
functools.partial(<bound method Cell.set_state of <__main__.Cell object at 0x7f2a77b37850>>, True)
>>> c.set_alive()()
>>> c.alive
True
Upvotes: 2
Reputation: 662
I wasn't sure whether the c.get_partialmethod()()
call below would work or not, but as z33k mentioned in the comments, it doesn't:
import functools
class Cell:
def __init__(self):
pass
def foo(self, x):
print(x)
def get_partial(self):
return functools.partial(self.foo, True)
def get_partialmethod(self):
return functools.partialmethod(self.foo, True)
c = Cell()
print(c.get_partial()) # functools.partial(<bound method Cell.foo of <__main__.Cell object at 0x000001F3BF853AC0>>, True)
print(c.get_partialmethod()) # functools.partialmethod(<bound method Cell.foo of <__main__.Cell object at 0x000001F3BF853AC0>>, True, )
c.get_partial()() # Prints True
c.get_partialmethod()() # TypeError: 'partialmethod' object is not callable
Upvotes: 1
Reputation: 1032
partial
is used to freeze arguments and keywords. It creates a new callable object with partial application of the given arguments and keywords.
from functools import partial
from operator import add
# add(x,y) normally takes two argument, so here, we freeze one argument and create a partial function.
adding = partial(add, 4)
adding(10) # outcome will be add(4,10) where `4` is the freezed arguments.
This is useful when you want to map a list of numbers to a function but maintaining one argument frozen.
# [adding(4,3), adding(4,2), adding(4,5), adding(4,7)]
add_list = list(map(adding, [3,2,5,7]))
partialmethod
was introduced in python 3.4 and it is meant to be used in a class as a method definition rather than been directly callable
from functools import partialmethod
class Live:
def __init__(self):
self._live = False
def set_live(self,state:'bool'):
self._live = state
def __get_live(self):
return self._live
def __call__(self):
# enable this to be called when the object is made callable.
return self.__get_live()
# partial methods. Freezes the method `set_live` and `set_dead`
# with the specific arguments
set_alive = partialmethod(set_live, True)
set_dead = partialmethod(set_live, False)
live = Live() # create object
print(live()) # make the object callable. It calls `__call__` under the hood
live.set_alive() # Call the partial method
print(live())
Upvotes: 18
Reputation: 2698
As @HaiVu said in his comment partial called in a class definition will create a staticmethod, while partialmethod will create a new bound method which when called will be passed self as the first argument.
Upvotes: 6