I have been looking at writing typings for sklearn and am wondering if there is a good solution for https://scikit-learn.org/stable/modules/generated/sklearn.utils.Bunch.html
Clearly it can be typed as just the class itself; however, there are many examples with sklearn that start with loading a sample dataset, in which case the specific members are useful to specify. For example:
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data
y = iris.target
NamedDictionary seems about the closest but its not ideal. Protocols might be another option. Wondering if there is a better solution.
This might be useful at some point in doing dynamic typing of things like pandas DataFrames where columns could be treated in a similar way (e.g. in a live environment like a Jupyter notebook).
I want to start off by thanking everyone that gave feedback on the first round of review of PEP 612. Your feedback illuminated a lot of things that I think have made this PEP a lot better.
Over the past few weeks I have had the time to rewrite much of that document to integrate all of that feedback.
Notably, this included integrating `typing.type_variable_operators.Concatenate` to support decorators that modify a finite number of positional parameters.
With that being said, I'd appreciate another round of feedback from all of you to determine whether this form of the PEP is ready to move on to the Steering Council.
Does anyone know if there has been any existing discussion on providing an equivalent of `typing.Protocol` but for modules instead of classes?
For example, a use case coming up in the numeric world is a function like `np.get_array_module(x)` which should return a a module that "behaves like" the base `numpy` module. See NEP 0037 for the details: https://numpy.org/neps/nep-0037-array-module.html#how-to-use-get-array-modu…
Currently, this type of function isn't statically typed, but we are working to create a standard array API which would be some version of a slimmed down NumPy API. If we did provide a function like `get_array_module()` to return some module which implements, I am unclear how to type it currently.
Should we type it as a protocol? Are modules considered instances of a protocol?
Ideally, I could imagine wanting to write a module like this:
from typing_extensions import Protocol
def arange(x: int) -> Array:
def __add__(self, Union[Array, int]) -> Array:
And then ideally we would be able to annotate a function like `get_array_module()` to say "You must return a module or object that has the `arange` function that returns an object that follow the Array protocol."
Next week we'll be holding our next tensor typing meeting.
WHEN? Monday 3rd August, 9:30am SF time.
WHERE? Google Meet. We'll post the link on the day itself.
1. Status updates. What have folks been working on over the past month?
2. What should symbols mean? Jörg and I would like to make a second attempt
at making the case that symbols should by default refer to semantic axis
types (e.g. `Batch` => a batch-like axis) rather than actual shapes
(`Batch` => a concrete value of '32'). We'll have a short presentation and
then we'll open it up for discussion.
3. Other. Is there anything else folks would like to talk about?
I was excited to learn about SupportsInt, SupportsFloat, and
SupportsComplex protocols decorated with @runtime_checkable because I
thought they bridged the gap between ABCs and typing protocol classes,
allowing consistent type checks by static tools and at runtime.
However, I am unable to see how to use those classes in practice.
For example, SupportsComplex: I understand at runtime the
@runtime_checkable decorator merely checks whether __complex__ exists
in the type, but that is not a good predictor of how to use a numeric
Types that actually can be converted to complex fail the insinstance
check with SupportsComplex. That's the case of built-in int and float,
as well as NumPy integer and float types like float16 and uint8.
On the other hand, SupportsInt suggests that I can convert a complex
to int, but in fact the int and float types implement __complex__ only
to provide a better error message, according to Guido van Rossum in an
earlier thread here.
>>> isinstance(1+0j, SupportsInt)
Traceback (most recent call last):
TypeError: can't convert complex to int
The issue with SupportsInt also happens with SupportsFloat.
In addition, the way Mypy interprets these protocol classes is not the
same as what we can see at runtime.
Given the above, what are recommended use cases for the runtime
checkable SupportsInt, SupportsFloat, and SupportsComplex?
| Author of Fluent Python (O'Reilly, 2015)
| Technical Principal at ThoughtWorks
| Twitter: @ramalhoorg