I am using Python 3.6 with PyCharm and it's kind of frustrating that there's no support for code completion for special cases of dictionary objects (with fixed key schema).
Say for example I create and try to access a simple dictionary object like this:
inventory = {'name': 'hammer', 'price': 2.3}
inventory['']
When I position my cursor inside the quotes ' ' and hit Ctrl + Space
i get code completion and the IDE correctly suggests all the possible keys in the dictionary object. That's great!
But if i try to build it as a utility function that returns this same dict object, say with values that the user provide but with the same dict keys - then I don't get code completion anymore!
def get_inventory(name: str, price: float):
return {'name': name, 'price': price}
inventory = get_inventory('hammer', 2.3)
inventory[''] # <- Pycharm can't offer any suggestions!
Any workaround or solution for this? I searched already for similar solutions but I didn't find anything that works. I know I can just convert it into a class Inventory
and access the properties that way but I don't want to do it for a couple of reasons:
dict
objects are the easiest for this purposeAny help or solution for how I can get my IDE to assist in code completion by recognizing the possible keys in such a dict
object would be greatly appreciated!
It is now mid-2023, and still no ways for PyCharm to detect dynamic dict
keys returned from a function def
exist.
However, there is a "sort" of workaround that is now possible. I realized that I forgot to mention it, so including it here.
Note that I say it's kind of a workaround, because this approach only works for static dict keys, rather than dynamic keys populated within a function scope. But hey, it's better than nothing.
dict
In Python 3.8+, this can now be achieved using TypedDict
, as shown below. Also added a __future__
import to account for annotations that could potentially be undefined at runtime, based on usage below.
from __future__ import annotations
from typing import TYPE_CHECKING, TypedDict
# To avoid creating a class at runtime, for type-hinting alone.
if TYPE_CHECKING:
# Map the `dict` fields here
class Inventory(TypedDict):
name: str
price: float
def get_inventory(name: str, price: float) -> Inventory:
return {'name': name, 'price': price}
inventory = get_inventory('hammer', 2.3)
inventory[''] # <- suggestions now work in PyCharm!
If dot or attribute access is desirable -- such as a.b.c
instead of a['b']['c']
-- then I have created a helper library dotwiz
to achieve this, as shown below:
import dotwiz
from typing import TYPE_CHECKING
# To avoid creating a class at runtime, for type-hinting alone.
if TYPE_CHECKING:
from dataclasses import dataclass
# Map the `dict` fields here
@dataclass
class Inventory:
name: str
price: float
else:
Inventory = dotwiz.DotWiz
def get_inventory(name: str, price: float) -> Inventory:
return Inventory(name=name, price=price)
inventory = get_inventory('hammer', 2.3)
print(inventory)
assert inventory.price == 2.3
inventory. # <- suggestions now work in PyCharm!