4 ms·
Even since the start of python typing, it was recommended to use a more generic type like Iterable instead of List. The author claims that List is too specific
by jerrygenser 4y ago
Even since the start of python typing, it was recommended to use a more generic type like Iterable instead of List. The author claims that List is too specific -- this seems like a straw man argument against typing that doesn't acknowledge python's own advice.
Also, mypy has gotten really good in recent years and I can vouch that on projects that have typing I catch bugs much much sooner. Previously I would only catch bugs when unit testing, now they are much more commonly type errors.
The other thing typing does is allow for refactoring code. If anything, high code quality relates to the ability to refactor code confidently and typing helps this. Therefore I would put it at the top of the list above all the tooling presented (exception I agree with ci/cd)
- whalesalad 4y ago> Even since the start of python typing, it was recommended to use a more generic type like Iterable instead of List. The author claims that List is too specific These statements contradict themselves? List is too specific, and Sequence[item] is preferred. Sometimes you are dealing with a tuple, or a generator, and so it makes more sense to annotate that it is a generic iterable versus a concrete list.
- jerrygenser 4y agoFrom the original article: > For example, you basically never care whether something is exactly of type list, you care about things like whether you can iterate over it or index into it. Yet the Python type-annotation ecosystem was strongly oriented around nominal typing (i.e., caring that something is exactly a list) from the beginning. I'm saying that this quote is a straw man and that contrary to what is claimed in the quote, instead, the ecosystem would go with/recommend Iterable[Item] or Sequence[Item] and not List[Item] if applicable. I think we both agree, not sure which part of my comment you think is contradictory.
- hbrn 4y agoWhether something is generic/specific depends on the context. As an argument type, Iterable is permissive (generic). As a return type, Iterable is restrictive (specific).
- hbrn 4y agoIterable is an import away, while list is already at my fingers. There's zero harm in using list in private interfaces: I know I'm the only one passing the value, I know it is always a list. As an argument type, Iterable is compatible with list, so it's benefits are minimal (with rare exceptions). Lists are easier to inspect in a debugging session. Iterable can be useful as return type, because it limits the interface. Iterable is useful if you are actually making use of generators because of memory implications, but in this case you already know to use it, because your interfaces are incompatible with lists. I can count on fingers of my hands when using Iterable instead of list actually made a difference.
- craftkiller 4y ago> Iterable is an import away, while list is already at my fingers. `list` might be but `List` isn't. Are you not defining the type of the contents of the list?
- hbrn 4y agotyping.List is deprecated. https://docs.python.org/3/library/typing.html#typing.List https://docs.python.org/3/library/typing.html#typing.List > Deprecated since version 3.9: builtins.list now supports subscripting ([]). See PEP 585 and Generic Alias Type.
- dragonwriter 4y ago> As an argument type, Iterable is compatible with list, so it’s benefits are minimal (with rare exceptions). Iterable is not compatible with list, but list is compatible with iterable. As the more general type, Iterable is better as an argument type unless you have a reason to force consumers to use lists. Even in private interfaces, I tend to prefer it, because I often end up wanting to pass something constructed on the fly, and creating an extra list for that rather than using a genexp just seems wasteful.
- hbrn 4y agoWhat I meant is argument marked as Iterable is compatible with list being passed. > Iterable is better as an argument type unless you have a reason to force consumers to use lists See, I feel the exact opposite: I use Iterable only if I have a reason to force consumers to use Iterable. When you're marking argument as Iterable, how confident do you feel that you will never query collection size or access it by index? I understand the desire to limit the interface and YAGNI, but since lists are more familiar and ubiquitous, using Iterable feels more complicated and unnecessarily pedantic.
- liendolucas 4y ago> The other thing typing does is allow for refactoring code. No. What allows you confident refactoring code are automated tests. I honestly can't understand why people are so obsessed about types, especially in languages like Python or Javascript.
- nomel 4y ago> I honestly can't understand why people are so obsessed about types It's a very powerful sanity check that lets me write correct code faster, avoiding stupid bugs that the unit tests will also, eventually, find. And, to me, reading the code is much much nicer. Types provide additional context to what's going on, at first glance, so I don't have to try to guess what something is, based on its name: results: list[SomeAPIResult] = some_api.get_results() is much easier to grock.
- hbrn 4y ago> I don't have to try to guess what something is, based on its name It's probably just a bad example, but in case it isn't: Sounds like you ended up at the same place. You went from guessing what is some_api.get_results(), based on it's name, to guessing what is SomeAPIResult, also based on it's name. If some_api is your library, then you could have just added type hints to get_results() and let type inference do it's job. If it's a third party library, then using your custom SomeAPIResult means that code is becoming alien to other engineers that worked with that library in the past. It might be worth it, but it's definitely controversial. You probably should've done it with stubs anyway.
- nomel 4y ago> guessing what is SomeAPIResult I disagree. It’s not a guess, it is precisely what it is, where the variable name is free to betray me. A sane IDE/linter will tell me if my local assumption is incorrect, where a variable called result_SomeAPIResult relies on an assumed, possibly ancient, state of reality.
- 4y ago
- spappal 4y agoI got good use of the run-time type checking of typeguard [0] when I recently invoked it via its pytest plugin [2]. For all code visited in the test suite, you get a failing test whenever an actual type differs from an annotated type. [0]: https://github.com/agronholm/typeguard/ https://github.com/agronholm/typeguard/ [1]: https://typeguard.readthedocs.io/en/latest/userguide.html#using-the-pytest-plugin https://typeguard.readthedocs.io/en/latest/userguide.html#us...