I would use types.FunctionType to represent a function:
>>> import types
>>> types.FunctionType
<class 'function'>
>>>
>>> def func():
... pass
...
>>> type(func)
<class 'function'>
>>> isinstance(func, types.FunctionType)
True
>>>
You could also use a string literal such as 'function', but it looks like you want an actual type object.
I would use types.FunctionType to represent a function:
>>> import types
>>> types.FunctionType
<class 'function'>
>>>
>>> def func():
... pass
...
>>> type(func)
<class 'function'>
>>> isinstance(func, types.FunctionType)
True
>>>
You could also use a string literal such as 'function', but it looks like you want an actual type object.
use Typing.Callable:
https://docs.python.org/3/library/typing.html
Frameworks expecting callback functions of specific signatures might be type hinted using
Callable[[Arg1Type, Arg2Type], ReturnType].For example:
from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # BodyIt is possible to declare the return type of a callable without specifying the call signature by substituting a literal ellipsis for the list of arguments in the type hint:
Callable[..., ReturnType].
Anyone knows of a PL in which a variable can be declared/defined with a function pointer type, the function pointer type having a return type that is the function pointer type itself?
In C, it would look something like:
typedef X (*workflow_step)();
What I am looking for is that X is a function pointer to the type being defined by the typedef.
How is this syntax problem even called? Anyone knows?
I have looked into C, python (callable type hint), rust, D, F#... And no luck. They all seem to lack this.
ctypes POINTER(c_type) is not allowed as function arg type
Implement __class_getitem__ for ctypes.pointer - Ideas - Discussions on Python.org
How to specify the type signature of funtion pointers to jitclass member function
How to pass a python function to a C function as a function pointer in Cython
You could use a different definition specifically when running type checking:
import ctypes
from typing import TYPE_CHECKING
import numpy as np # type: ignore # (no stubs for numpy)
if TYPE_CHECKING:
IntPointer = ctypes._Pointer[ctypes.c_int]
else:
IntPointer = ctypes.POINTER(ctypes.c_int)
def np_to_c(arr: np.ndarray) -> tuple[IntPointer, ctypes.c_int]:
return arr.ctypes.data_as(IntPointer), ctypes.c_int(len(arr))
Try me on mypy-play
ctypes.POINTER is a constructor that creates an object (a pointer) for the ctypes data type (c_int) passed as its argument. So your linter most likely rejects ctypes.POINTER(ctypes.c_int) as a type hint because it is actually a function call.
All objects returned by ctypes.POINTER are derived from ctypes._Pointer, so my bet would be to use
def np_to_c(arr: np.ndarray) -> tuple[ctypes._Pointer, ctypes.c_int]:
return arr.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), ctypes.c_int(len(arr))
This, however, doesn't really convey that the returned pointer is specifically for a c_int array. Would also be interested in hearing a more informed opinion on this matter!
For me it's :
from typing import Self
class Foo:
def __init__(self: Self) -> None:
...The second example is acceptable in my opinion, as the parameter are one type and the type hint for the actual attributes is for their entire lifetimes within the instance :
class Foo:
def __init__(self, par1: int, par2: tuple[float, float]):
self.par1: int = par1
self.par2: tuple[float, float] | None = par2Edit: changed the method in the first example from bar to __init__
You should use the typing module, which was introduced in Python 3.5:
typing.TextIO fits best in this case.
Generic type
IO[AnyStr]and its subclassesTextIO(IO[str])andBinaryIO(IO[bytes])represent the types of I/O streams such as returned byopen().
In your example:
from typing import TextIO
def write_some_stuff(fp: TextIO):
...
If you want to be a little more generic and allow any file object that is in text mode (i.e. read() returns Unicode strings), you probably want to hint that you take an io.TextIOBase argument. That will allow instances of io.StringIO in addition to the more common io.TextIOWrapper instances.
You also don't need the underscore on the io module's name, even if you stick with TextIOWrapper. The regular io module imports all relevant types from the _io module into its own namespace.
I think you can use something like:
if TYPE_CHECKING: # valid for mypy
c_useable_c_str = pointer[c_char] # the problematic line
else: # valid at run time
c_useable_c_str = pointer
I found an imperfect (but good enough) solution, based on what I found here: https://github.com/python/mypy/issues/7540 (comment by thijsmie, commented on May 21, 2021).
if not TYPE_CHECKING:
# Monkeypatch typed pointer from typeshed into ctypes
# NB: files that wish to import ctypes.pointer should all import `pointer` from this file instead
class pointer_fix:
@classmethod
def __class_getitem__(cls, item):
return POINTER(item)
pointer = pointer_fix
It does solve MyPy's complaints concerning c_useable_c_str, and functions that use c_useable_c_str still get proper typing errors when the argument provided isn't of a compatible type, so that's good.
Well, EXCEPT for the following case:
class t_string(c_useable_c_str):
pass
class t_string_p(pointer[t_string]):
pass
where MyPy does not seem to be able to understand that t_string_p is compatible with the type pointer[pointer[c_char]]. For these cases, I used a type union; not ideal, but it got the job done.
I'll be leaving this question unanswered for now, in case someone, someday, can find a better solution.