-
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
[FEAT] Cannot implicitly convert from None. #2778
Comments
That's still constructing an |
I'm fairly certain (haven't tested; it's too late. I can poke around tomorrow) that this would stop |
I haven’t compiled the code here, I have made this change in my copy of pybind11 and have had it working on Python bindings to a library with a couple of thousand public symbols, including several hundred functions functions that take all different types of standard containers as arguments. I will try running the test cases tonight. Sure, |
Definitely.
But I completely disagree with this. Again,
I will agree that it's slightly weird that this implicit cast isn't working. But the whole However, exposing your function as |
I'm surprised by how little test breakage this change causes, but this is as minimal you can get to demonstrate: #include <pybind11/pybind11.h>
namespace py = pybind11;
struct Foo {};
PYBIND11_MODULE(example, m) {
py::class_<Foo>(m, "Foo")
.def(py::init<>());
m.def("bar", [](Foo *foo) { return 42; });
} Without your changes: Python 3.9.1 (default, Dec 8 2020, 03:24:52)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> example.bar(example.Foo())
42
>>> example.bar(None)
42 With your changes: Python 3.9.1 (default, Dec 8 2020, 03:24:52)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> example.bar(example.Foo())
42
>>> example.bar(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar(): incompatible function arguments. The following argument types are supported:
1. (arg0: example.Foo) -> int
Invoked with: None So, there's a world outside your several hundred functions. |
But you can say exactly the same thing about I don’t see anyone willing to write several hundred functions just to allow |
Oh, the test breaking is unfortunate. I’ll look a bit more into that, see if I understand why. There must be a solution. Thanks! |
That's true. I did say that the lack of possibility to have an implicit conversion is slightly weird.
It's not an easy thing, though, in the current design. pybind11 sees |
I am going to address this issue one more time. It was first brought up in #642, then again in #1382.
In short, we cannot make a custom type that implicitly converts from
None
. @bstaletic suggested a solution that doesn't work.Consider the following example code (paraphrased, might have typos):
I can now do in Python:
But I cannot do
However, if I edit
pybind11/cast.h
, at the top ofbool load_impl(handle src, bool convert)
, where it says:If I remove the
value = nullptr; return true;
lines, then the above all works correctly.I have not found any downsides to doing so. This means that the custom converter function gets a
py::none
object as input, it can choose to reject that or accept that. Any conversion function already tests what the type of the input object is, so this should not affect any existing code.I have been using this "fix" for some months now, but would prefer a solution that doesn't require patching pybind11.
In real life, the above example is for an image class where the default-constructed image has no pixels, and is used to signal "I don't need this input" to specific functions. In C++ one can use
{}
for a default-constructed object,None
is the most Pythonic substitution. See this other comment for details.Sure, I could write a function for
X(None)
, but this is for a large project with a lot of functions, and creating multiple versions of each for various inputs beingNone
is not doable.The text was updated successfully, but these errors were encountered: