-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overriding __eq__ does not set __hash__ to None #2191
Comments
Interesting. Pybind can check that the argument to |
Note that it should only do that if there is no
|
I agree in principle, but it seems quite horrible to do a string comparison with |
Is that really a concern? I mean it is all compile time and how big are bindings really going to be that this will increase will have a noticeable impact? |
Is it? Most of the time, it will be, indeed, but in principle, you could dynamically generate strings. So this can't be expected to have no effect on runtime, I think. I'm not against, but it's something to consider. There are talks about getting benchmarks (both for size and time), so that would make such a discussion a lot easier :-) |
Can this check & fixup be in |
Interesting idea, but I don't think there's anything stopping you from keeping the |
I agree, it might lead to nasty debug session. I've choose destructor as most closest approximation to "class bindings are complete" event. Would it be better to have dedicated |
I'm not entirely convinced of that either. Lots of existing project might depend on that not being there, currently? Actually, maybe the check with 7 chars in |
I meant explicit call to "finalize" method (if it was not clear from previous comment), smth like py::class_<DummyClass2>(m, "MyClass2")
.def(py::init())
.def("__eq__", [](py::object&) { return true; })
.done(); // checks, fix-ups, etc I don't think it would break any code (it might, but chances are very low). |
Yes. So once we start counting on that (for maybe more crucial things than |
Here's a potentially bad idea. Instead of My idea breaks if the user copies the string literal onto the stack and passes that pointer, or creates a
I don't like the idea of |
delNo, existing code would be as good as it is right now, not worse nor better. Such call will be required for some cases, but not every class. The check that required call was not made can go to module destructor ( @bstaletic I agree, for this issue |
Or, best of both worlds: |
That might be a good idea. I'd just be explicit regarding that |
Let's try tomorrow. Or do you want to make a PR, @ixje? |
In majority of cases |
I'm not sure if it makes sense to add code to |
I was under the impression that |
OK, then. We could also add it to the @ixje Do you have time to make a PR to add this to the docs somewhere? |
@YannickJadoul I took a stab |
Thanks! @sizmailov & @bstaletic, please have a look if #2287 looks good to you? :-) |
Issue description
The Python documentation states
Thus if we override
__eq__
but not__hash__
we should get an unhashable type (e.g. cannot be used in aset
container). Pybind however seems to always have a__hash__
implemented, regardless if we override__eq__
. The expected behaviour is that__hash__
is set toNone
Reproducible example code
In Python it exhibits the following behaviour
Using pybind
The workaround
A workaround is to manually add
.attr("__hash__") = py::none()
I'm assuming it should be possible to detect if there is a
__eq__
override without any__hash__
override and then set the attribute. This would resolve the deviating/unexpected behaviour.The text was updated successfully, but these errors were encountered: