4 ms·
Not a word though about the elephant in the room: circular imports. It is absurdly easy in Python to end up with a circular import situtation, where no real ci
by m000 4y ago
Not a word though about the elephant in the room: circular imports.
It is absurdly easy in Python to end up with a circular import situtation, where no real circular dependency exists. E.g. you can't have A.a1 -> B.b1 and B.b2 -> A.a2. So, you are forced to layout your code in some quite awkward ways.
- capableweb 4y agoIsn't having circular dependencies more awkward? Conceptually, it makes things more intertwined when instead you can build a better and more separated architecture.
- marius_k 4y agoIs there an elegant way to import type hints without circular imports?
- lopz 4y agoSomething like this does the trick: if TYPE_CHECKING: import WhateverClass https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING https://docs.python.org/3/library/typing.html#typing.TYPE_CH...
- nomel 4y agoI’m a fan of having a single state, used for everything. Splitting the code up into two states, one for the linter and one for the execution, seems like a recipe for incorrectness and confusion. I would hate to refactor something like that.
- closed 4y agoThe issue is that sometimes a function can take a type that is an optional dependency, so you don't want to import it unless you are type checking. (And some types are defined in the typeshed so only exist to be imported during type checking; eg the type checker lib itself is a dependency in this case)
- deleted 4y ago[deleted]
- int_19h 4y agoIt's hardly elegant, though.
- Spivak 4y agoYeah if you’re like just put what is essentially if False: import blah unironically as good design and more than a necessary evil until a long-term solution emerges then we’ve jumped the shark.
- deleted 4y ago[deleted]
- mdaniel 4y agoType hints can also be strings, which at least PyCharm resolves as if they were real type references from typing import List class Alpha: @staticmethod def doit(b: "Beta") -> List["Beta"]: return [b] class Beta: @staticmethod def doit(a: "Alpha") -> List["Alpha"]: return [a]
- squeaky-clean 4y agoThis only works if they're in the same file, or Alpha imports Beta later in the file and vice versa. Once you split these into separate files (say for example adding a gamma.py file and Gamma class that uses Alpha and Beta) you get Unresolved reference 'Alpha' and Unresolved reference 'Beta', and typechecking calls to Alpha.doit and Beta.doit from Gamma does not work.
- mdaniel 4y agoI thought it also accepted fully qualified type names but I just tried it and you're right. Relevant to this submission's title, if your packages are side-effect free, just importing the namespace then allows referencing the type names without touching the "actual" type import gamma def doit(bar: "gamma.Gamma"): ... In Java my answer to circular deps is the introduction of an interface that the concrete types can implement but then breaks the cycle
- overgard 4y agoThe only way to really fix that is to disallow code running outside of functions, IE, basically a whole new language.
- EdwardDiego 4y agoYeah the module thing is my biggest irk with Python - merely importing a module for symbols executes all the top level code.