This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: making partial functions comparable
Type: enhancement Stage:
Components: Library (Lib) Versions: Python 3.0, Python 2.5
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: erickt, mgiuca, pitrou, terry.reedy
Priority: normal Keywords:

Created on 2008-08-16 07:05 by erickt, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (4)
msg71200 - (view) Author: Erick Tryzelaar (erickt) Date: 2008-08-16 07:05
functools.partial functions are not comparable, in both python 2.5 and 
3.0:

>>> def foo(): pass
>>> functools.partial(foo) == functools.partial(foo)
False

It can be worked around by comparing the func, args, and keywords, but 
this means that if a partial function is stored in some structure, such 
as:

>>> def foo(): pass
>>> f1=functools.partial(foo)
>>> f2=functools.partial(foo)
>>> (1,'a',f1) == (1,'a',f2)
False

Which complicates things when I'm comparing things in a function that 
works with generic data structures. Would it be possible to extend 
partial to support comparisons?
msg71208 - (view) Author: Matt Giuca (mgiuca) Date: 2008-08-16 10:59
It's highly debatable whether these should compare true. (Note: saying
"they aren't comparable" is a misnomer -- they are comparable, they just
don't compare equal).

From a mathematical standpoint, they *are* equal, but it's impossible
(undecidable) to get pure equality of higher order values (functions) in
a programming language (because strictly, any two functions which give
the same results for the same input are equal, but it's undecidable
whether any two functions will give the same results for all inputs). So
we have to be conservative (false negatives, but no false positives).

In other words, should these compare equal?

>>> (lambda x: x + 1) == (lambda x: x + 1)
False (even though technically they describe the same function)

I would argue that if you call functools.partial twice, separately, then
you are creating two function objects which are not equal.

I would also argue that functools.partial(f, arg1, ..., argn) should be
equivalent to lambda *rest: f(arg1, ..., argn, *rest). Hence your example:
>>> def foo(): pass
>>> f1=functools.partial(foo)
>>> f2=functools.partial(foo)

Is basically equivalent to doing this:

>>> def foo(): pass
>>> f1 = lambda: foo()
>>> f2 = lambda: foo()

Now f1 and f2 are not equal, because they are two separately defined
functions.

I think you should raise this on Python-ideas, instead of as a bug report:
http://mail.python.org/pipermail/python-ideas/

But with two identical functions comparing INEQUAL if they were created
separately, I see no reason for partial functions to behave differently.
msg71225 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2008-08-16 16:32
I would add that making the comparison "right" for partial would be
trickier than it seems:

>>> from functools import partial
>>> type == type
True
>>> 1 == 1.0
True
>>> partial(type, 1)() == partial(type, 1.0)()
False

If partial(type, 1) and partial(type, 1.0) were to compare equal, it
would break the expectation, stated by Matt, that two equal function
objects produce the same results when given the same inputs.


PS: 
>>> partial(type, 1)()
<type 'int'>
>>> partial(type, 1.0)()
<type 'float'>
msg71780 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2008-08-22 21:32
The default equality comparison of Python objects is by id.
Some classes override this, others, in particular, functions, do not.
I also agree that partial functions should not either.

However, you can subclass functools.partial (I checked in 3.0b2) and add
__eq__ and __ne__ methods that implement the definition *you* need, even
if it gives the 'wrong' result of Antoine example.
History
Date User Action Args
2022-04-11 14:56:37adminsetgithub: 47814
2008-08-22 21:32:48terry.reedysetstatus: open -> closed
resolution: rejected
messages: + msg71780
nosy: + terry.reedy
2008-08-16 16:32:53pitrousetnosy: + pitrou
messages: + msg71225
2008-08-16 10:59:01mgiucasetnosy: + mgiuca
messages: + msg71208
2008-08-16 07:05:10ericktcreate