Earlier quoted context omitted.
Try: def f(i=0) -> None: reveal_type(i) The inferred type is not `float` nor `int`, but `Any`. Mypy will happily let you call `f("some string")`.
`Any` is the correct call. It could be: def f(i=0) -> None: if i is None: do_something() else: do_something_else() Yeah, I know it's retarded. I don't expect high quality code in a code base missing type annotation like that. Assuming `i` is `int` or `float` just makes incrementally adoption of a type checker harder.
Advanced Python Features
171–180 of 183 posts
Re: Advanced Python Features
#172My own opinion is that Python shall remain Python, and golang, Rust and Typescript each should be whichever they are with their unique philosophy and design. I am coding in all 4, with some roughly 28 years now, and I don't like what is becoming of Python There is a reason why python become that popular and widely adapted and used, and it is not the extra layers of type checking, annotations and the likes. this looks…
With the type system my opinion on that has changed. We have a pretty large tooling codebase with protocol stacks, GUI, test automation etc. and it's all very maintainable with the type checking.
Re: Advanced Python Features
#173Earlier quoted context omitted.
1) the code you wrote isn’t Python. 2) inferring the type is int isn’t guaranteed to be correct in this case
I was merely giving an example that strong typing has nothing to do with having to write the types. (and, obviously, the inferred type (int -> int) is correct. )
No it’s not. It’s Optional[int] -> int at minimum. There are other completely valid signatures beyond that too.
Re: Advanced Python Features
#174Earlier quoted context omitted.
Because it shouldn’t in function arguments. The one defining the function should be responsible enough to know what input they want and actually properly type it. Assuming an int or number type here is wrong (it could be optional int for example).
In TypeScript arguments with a default value "inherit" the type of that value, unless you explicitely mark it otherwise. I believe this is how Pyright works as well.
int -> int
Is wrong. At minimum it’s:
Optional[int] -> int
Because you provided a default value so clearly it’s not required to provide an input parameter. It’s also wrong to assume `0` is an int. There’s other valid types it could be. If the default was say `42`, I’d be pushing back a little less (outside of the Optional part), but this contrived example from GP had 0, which is ambiguous on what the inferred typing must be.
Re: Advanced Python Features
#175Earlier quoted context omitted.
How would a typing system know if the right type is `int` or `Optional[int]` or `Union[int, str]` or something else? The only right thing is to type the argument as `Any` in the absence of a type declaration.
The typing system should use the most specific valid type, and the code author can broaden it with explicit typing if needed. No good typing system should ever infer a variable as `Any`: "I don’t know the type of this" (`unknown` in TypeScript) is not the same thing as "This function accepts anything". Conflating these things is one of the main reasons why Mypy is so annoying.
Re: Advanced Python Features
#176Earlier quoted context omitted.
The "truthy" operator is bool(); the problem here is that empty strings are falsy. For myself, I settled on these patterns for various kinds of tests: # check for None if x is not None: ... # check for empty string if x != "": ... # check for empty collection other than string if not len(x): ... In this last case I rely on 0 being falsy to make this idiom distinct from checking length for a specific value via equalit…
bool( thing ) is overly verbose. It would be nice to have a unary operator. I don't think the problem is that empty strings are falsy per say (although that might not be to your personal preference). Rather I think the problem is the implicit coercion to bool, hence my desire for a unary operator. I think this is yet another entry in the (extremely) long list of examples of why implicit type conversions are a bad thi…
Let me correct that. The problem isn't so much that they are falsy per se, but rather that they share this property with so many unrelated things - and this is then combined with dynamic typing, so any given `x` can be any of those things. None/'' in particular is exceedingly common because None is the standard way to report absence of a value in Python.
As far as having a symbolic unary operator for such checks, I think that would go stylistically contrary to the overall feel of Python syntax - I mean, this is a language in which you have to spell out things like "not", and len() is also a function unlike say Lua. It feels like the most Pythonic interface for this would be as an instance property with a descriptive name.
Re: Advanced Python Features
#177Earlier quoted context omitted.
That's exactly my point. Having to search for the meaning of the operator at all makes the code less readable. I recommend reading the Zen of Python, which covers the design principles of the language.
I don’t write code to the level of someone who has just finished Hello, World. This isn’t something esoteric, it’s an extremely basic and useful part of the language. I’ve seen this argument used against multiple languages, and it has never made sense to me. “I don’t want to use windowing functions in SQL, because most people don’t know what they are.” So you’d rather give up an incredibly powerful part of your RDBMS…
Re: Advanced Python Features
#178Good list, its one of these things you either never heard of, or used for years and think everyone knew that. I'll add a few: * did you know __init__.py is optional nowadays? * you can do relative imports with things like "from ..other import foo" * since 3.13 there is a @deprecated decorator that does what you think it does * the new generics syntax also works on methods/functions: "def method[T](...)" very cool * y…
> did you know __init__.py is optional nowadays? It's not optional. Omitting it gets you a namespace package, which is probably not what you want. > TypeVar supports binding to enforce subtypes: "TypeVar['T', bound=X]", Using the new generics syntax you mentioned above you can now do: def method[T: X](...)
Re: Advanced Python Features
#179Good list, its one of these things you either never heard of, or used for years and think everyone knew that. I'll add a few: * did you know __init__.py is optional nowadays? * you can do relative imports with things like "from ..other import foo" * since 3.13 there is a @deprecated decorator that does what you think it does * the new generics syntax also works on methods/functions: "def method[T](...)" very cool * y…
> did you know __init__.py is optional nowadays? It has an effect, and is usually worth including anyway. I used to omit it by default; now I include it by default. Also, you say "nowadays" but it's been almost 13 years now ( https://peps.python.org/pep-0420/ ). > since 3.13 there is a @deprecated decorator that does what you think it does Nice find. Probably worth mentioning it comes from the `warnings` standard lib…