What do these mean?
def f(a: {int, float}):
pass
I've seen this syntax used in some standard Python modules when fetching documentation via PyCharm, and I have no idea what it means. What's the hinted type for a in my example? What types can I pass to this function?
The particular example where I've seen this is in tkinter's Frame __init__ method, where the master parameter is of type {tk, _w}.
It's a hint telling you it wants an object with the named attributes 'int' and 'float' -- or more specifically for tkinter 'tk' and '_w'
I coded up a minimal example in pycharm:
Inpecting the python library sources -- You can see that there are attempted accesses to master.tk and master._w. That's all that pycharm was able to infer about the type of the parameter master so it floated it up to the IDE in this manner.
Related
I am defining a function that gets pdf in bytes, so I wrote:
def documents_extractos(pdf_bytes: bytes):
pass
When I call the function and unfortunately pass a wrong type, instead of bytes let's say an int, why I don't get an error? I have read the documentation regarding typing but I don't get it. Why is the purpose of telling the function that the variable shoudl be bytes but when you pass and int there is no error? This could be handle by a isinstance(var, <class_type>) right? I don't understand it =(
Type hints are ignored at runtime.
At the top of the page, the documentation that you've linked contains a note that states (emphasis mine):
The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc.
The purpose of type hints is for static typechecking tools (e.g. mypy), which use static analysis to verify that your code respects the written type hints. These tools must be run as a separate process. Their primary use is to ensure that new changes in large codebases do not introduce potential typing issues (which can eventually become latent bugs that are difficult to resolve).
If you want explicit runtime type checks (e.g. to raise an Exception if a value of a wrong type is passed into a function), use isinstance().
By default python ignores type hints at runtime, however python preserves the type information when the code is executed. Thanks to this library authors can implement runtime type checking packages such as typeguard, pydantic or beartype.
If you don't want to use isinstance checks yourself, you can use one of those libraries.
Typeguard example:
main.py:
from typeguard import importhook
importhook.install_import_hook('mypack')
import mypack
mypack.documents_extractos("test")
mypack.py
def documents_extractos(pdf_bytes: bytes):
pass
When you run python3 main.py you will get error TypeError: type of argument "pdf_bytes" must be bytes-like; got str instead
EDIT: Type[X] does type hint to the class itself. The repl now has an example of that, too. PyCharm just doesn't use the __init__ information within the class to type hint an initialization elsewhere. If anyone knows why that is, I'll accept that answer. The below question is now just for context:
Let's say I have the following code:
from typing import NamedTuple, Type
class SubTuple(NamedTuple):
a: str
b: int
def get_tuple_type() -> Type[SubTuple]:
return SubTuple
test_tuple = get_tuple_type()
test_tuple_instance = test_tuple('test', 1)
Is there a way to type hint so that PyCharm will give me argument hints? Right now it gives me this:
which is rather useless. Hilariously, it does know the arguments, because when I type:
test_tuple.
it recommends all of the fields in the SubTuple. It just won't recommend them to me when I go to create an instance of the thing.
Also, https://repl.it/repls/BurdensomeInnocentKnowledge just so that you can see that the above code actually does work. The repl IDE also has no idea what to do with this thing, and is recommending that I call .a and .b on the class itself, which leads me to believe this might just be a general issue with what I'm trying to do in Python?
EDIT: I'm using Python 3.7; updated code to include what I've tried. It has the same result. Will update the repl, too.
This is a bug in PyCharm's static type checker, there are a few open bugs about NamedTuple on JetBrains bugtracker. The most up-to-date thread on the NamedTuple datatype is PY-18246. Fixes have been rolled out during 2020 but this specific case of correctly inferring the NamedTuple members after typing a class object has neither been reported nor solved.
The warning has also changed, if you try the same code with PyCharm 2020.3.3 Pro you'll get a different hint.
I tried checking the code with Mypy and it works correctly without any warnings. If you try causing an error by changing the types:
variable = test_tuple(1, 'test')
Mypy warns and correctly hints you about it:
error: Argument 1 to "SubTuple" has incompatible type "int"; expected "str"
error: Argument 2 to "SubTuple" has incompatible type "str"; expected "int"
Found 2 errors in 1 file (checked 1 source file)
Is there a way to type hint so that PyCharm will give me argument hints?
You are already type hinting correctly as PEP 484 recommends. If you use the Mypy static type checker it works, as for PyCharm it's a matter of waiting for a bug fix. There's nothing wrong with your type hinting and it shouldn't be changed in this case.
I'm trying to figure out what to put in my type annotation at the top of this function.
I have the following trivial example:
import curses
def main(stdscr):
stdscr.clear()
stdscr.addstr(2, 0, "What is the type of stdscr?")
stdscr.addstr(5, 0, "It is: {}".format(type(stdscr)))
stdscr.refresh()
stdscr.getkey()
curses.wrapper(main)
This returns <type '_curses.curses window'>. This doesn't seem like it will work with Type hinting as it has a space in it. The expected result would be WindowObject listed in the documentation. I can't find a path to WindowObject in the curses module itself. EDIT: The documentation is incorrect here.
How do I write main with accurate type annotation?
Unfortunately, the curses module does not appear to be fully typed within typeshed. There was some preliminary work done a few months ago, but the Windows object has not been added yet. You can check the Python 3 'curses' stubs for yourself here and here.
Currently, the stubs default to typing curses.wrapper as:
def wrapper(func, *args, **kwds): ...
...which, in turn, is equivalent to:
def wrapper(func: Callable[..., Any], *args: Any, **kwds: Any): ...
So, that means that there really is no suitable type to assign to your main function's parameter at the moment, apart from Any.
That said, if you're up for it, you might be able to contribute some stubs to complete the curses module yourself! It doesn't seem like the Window object is that terribly complex and should hopefully be relatively straightforward to type.
The main complication might be hammering out where exactly the 'Window' object should be imported from, if it doesn't exist within the curses module itself. You might perhaps want to stick the 'Windows' object within the typing module itself, just like typing.re.Pattern and typing.re.Match.
Your problem is that the type you spect is just not the real type of the object, the method type() always tells you the type correctly, so by sure the doc. is wrong.
I'm wanting to go through a list of objects so that my PyCharm IDE knows what type each list item is:
For example, say I know that each item in a list is an class instance of type 'myClass' - how do I use this to cast my objects so that my ide can help with code completion?
for i in range(len(myList)):
myClass(myList[i]).myClassProperty .....
I know how to do it in Delphi (something like the above) but not in python.
Thanks
In PyCharm, you can use Type Hinting:
class Bar:
def __init__(self,bar):
self.bar = bar
def do_bar(self):
return self.bar
def foo(x):
for el in x: # type: Bar
el.do_bar()
bars = [Bar('hello'), Bar('World')]
foo(bars)
You can't get code completion similar to Java or C++ in dynamically typed, interpreted language.There is no casting, because you don't need it in python. A function works for a given object if it has needed methods implemented, type is irrelevant to the language at this point. It is good practice though to leave some runtime checks using isinstance, if you expect your argument to be e.g. a dict. Otherwise you will end up with many difficult bugs.
As for code completion in python there are two solutions I find useful. The best IDEs around here are probably PyCharm https://www.jetbrains.com/pycharm/ and PyDev the Eclipse Plugin http://www.pydev.org/manual_101_install.html. They provide some code completion.
The other is interactive console Jupyter http://jupyter.org/. As you write your code, you could execute it in chunks (cells) and easily see object methods or fields, using not the type information, but the object itself existing in memory. This is very good for data analysis or playing with framework you don't know well.
So, PEP 484 has the section "The type of class objects".
On this section, it is stated that the following should be possible:
U = TypeVar('U', bound=User)
def new_user(user_class: Type[U]) -> U:
user = user_class()
# (Here we could write the user object to a database)
return user
I'm just getting started on using the typing module. My problem is that when trying to find the Type hint, I just couldn't find it. It is nowhere in the source code or in the documentation.
The release notes indicate that the typing module implements PEP 484. There is no indication of an incomplete implementation. Is there a way to make this kind of type hint on the current version? Or is it simply impossible for now?
Thanks.