Live data from Hacker News

Advanced Python Features

blog.edward-li.com

41–50 of 183 posts

Re: Advanced Python Features

#41
post #18
post #17

Working in the ML field, I can't hate Python. But the type system (pre-3.12, of course) cost me a lot of nerves. Hoping for a better post-3.12 experience once all libraries are usable in 3.12+. After that experience, I’ve come to truly appreciate TypeScript’s type system. Never thought I’d say that.

Same experience here, Python’s typing experience is awful compared to TypeScript, even post-3.12. Mypy’s type inference is so dumb you have to write arguments like `i: int = 0`; `TypedDict`s seems promisable at first and then end up as a nightmare where you have to `cast` everything. I miss TypeScript’s `unknown` as well.

I'm just waiting for the astral's people (uv, ruff) type checker at this point. On large projects mypy is often unreliable and slow.

Re: Advanced Python Features

#42
Python has evolved into quite a complex language considering the amount of features that come built-in. The documentation, while complete, does not facilitate discovery of many of those features.

Re: Advanced Python Features

#44
post #42

Python has evolved into quite a complex language considering the amount of features that come built-in. The documentation, while complete, does not facilitate discovery of many of those features.

The quality of documentation is a known, highlighted concern in the community. There is particular interest in adopting Diataxis principles to improve documentation, both for Python itself and for packaging (see e.g. the user guide at https://packaging.python.org/en/latest/ , or the PyPA main site https://www.pypa.io/en/latest/ ).

If you want to help, there's a section on the Python forum (https://discuss.python.org/c/documentation/26) and a Discord server, and issues with documentation can also be reported on the main Python GitHub issue tracker (https://github.com/python/cpython/labels/docs).

Re: Advanced Python Features

#45
post #2

TFA's use-case for for/else does not convince me: for server in servers: if server.check_availability(): primary_server = server break else: primary_server = backup_server deploy_application(primary_server) As it is shorter to do this: primary_server = backup_server for server in servers: if server.check_availability(): primary_server = server break deploy_application(primary_server)

This kind of search can be done a variety of different ways, and is worth abstracting, e.g.:

  def first(candidates, predicate, default):
      try:
          return next(c for c in candidates if predicate(c))
      except StopIteration:
          return default

  deploy_application(first(servers, Server.check_availability, backup_server))

Re: Advanced Python Features

#47
post #20
post #2

TFA's use-case for for/else does not convince me: for server in servers: if server.check_availability(): primary_server = server break else: primary_server = backup_server deploy_application(primary_server) As it is shorter to do this: primary_server = backup_server for server in servers: if server.check_availability(): primary_server = server break deploy_application(primary_server)

What about this? for server in servers: if server.check_availability(): primary_server = server break else: logger.warning("Cannot find a valid server") #

Yes, that might be a better example.

Re: Advanced Python Features

#48

This sounds fun if you have 10x programmers or at least IQ > 140 programmers in charge. Last place I worked, I was told never use "smart" tricks if you can do the same thing in a simpler way. For-else and f-strings and := sound like harmless enough (though the last one is controversial); "with" is useful for resources that need to be deallocated but "yield"? Really? "more readable" when you slap a decorator on the th…

The simple contextlib.contextmanager example doesn't really sell the benefits.

The main one is that it makes error handling and clean-up simpler, because you can just wrap the yield with a normal try/catch/finally, whereas to do this with __enter__ and __exit__ you have to work out what to do with the exception information in __exit__, which is easy to get wrong:

https://docs.python.org/3/reference/datamodel.html#object.__...

Suppressing or passing the exception is also mysterious, whereas with contextlib you just raise it as normal.

Another is that it makes managing state more obvious. If data is passed into the context manager, and needs to be saved between __enter__ and __exit__, that ends up in instance variables, whereas with contextlib you just use function parameters and local variables.

Finally, it makes it much easier to use other context managers, which also makes it look more like normal code.

Here's a more real-world-like example in both styles:

https://gist.github.com/tomjnixon/e84c9254ab6d00542a22b7d799...

I think the first is much more obvious.

You can describe it in english as "open a file, then try to write a header, run the code inside the with statement, write a footer, and if anything fails truncate the file and pass the exception to the caller". This maps exactly to the lines in the contextlib version, whereas this logic is all spread out in the other one.

It's also more correct, as the file will be closed if any operation on it fails -- you'd need to add two more try/catch/finally blocks to the second example to make it as good.

Re: Advanced Python Features

#49
post #18
post #17

Working in the ML field, I can't hate Python. But the type system (pre-3.12, of course) cost me a lot of nerves. Hoping for a better post-3.12 experience once all libraries are usable in 3.12+. After that experience, I’ve come to truly appreciate TypeScript’s type system. Never thought I’d say that.

Same experience here, Python’s typing experience is awful compared to TypeScript, even post-3.12. Mypy’s type inference is so dumb you have to write arguments like `i: int = 0`; `TypedDict`s seems promisable at first and then end up as a nightmare where you have to `cast` everything. I miss TypeScript’s `unknown` as well.

Mypy was designed to enable gradual adoption. There is definitely Python code out there with `def f(i=0)` where `i` could be any numeric type including floats, complex, numpy etc.. This is called duck typing. It's wrong for a type checker to assume `i: int` in such a case.

Pyright probably works if you use it for a new project from the start or invest a lot of time "fixing" an existing project. But it's a totally different tool and it's silly to criticise mypy without understanding its use case.

Re: Advanced Python Features

#50

Good 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 library.

> the time package has functions for monotonic clocks and others not just time()

There's quite a bit in there, but I question how many people need it.

Anyway, it's always surprising to me how when other people make these lists, such a large fraction is taken up by tricks with type annotations. I was skeptical of the functionality when the `typing` standard library was introduced; I've only grown more and more wary of it, even as people continue to insist to me that it's somehow necessary.

Post reply on HN