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?
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?
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())
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.
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
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