Live data from Hacker News

Advanced Python Features

blog.edward-li.com

161–170 of 183 posts

Re: Advanced Python Features

#161
post #34

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…

I don't fully disagree, but the yield context manager approach is very common when writing test fixtures, you do: # setup yield resource. # teardown Not that it makes it any less magical, but at least it's a consistent python pattern

Test fixtures as opposed to production code forgive a multitude of sins. Sometimes you have to mock up an object that could never exist in the real world, to assert that the main code doesn't just accept it and move on. Sometimes you poke at individual variables in an object that in the real world should only be accessed via the methods in its API. All in a day's work if you know what you're doing and never try that in the real code.

Re: Advanced Python Features

#162

Earlier quoted context omitted.

I've never had this behavior cause a bug.

The most common case is when people use `if not s` to test for None in an otherwise string value (e.g. from JSON) without realizing that empty strings are also false.

... thank you for informing me that the code I wrote the other day is buggy. This sort of BS is exactly why I avoid JS. Truly one of the worst convenience "features" ever.

We need a unary "truthy" operator so that code remains compact and readable without the surprising behavior.

Re: Advanced Python Features

#163

This is wild and something I didn't know about: https://blog.edward-li.com/tech/advanced-python-features/#2-... def bar(a, /, b): ... # == ALLOWED == bar(1, 2) # All positional bar(1, b=2) # Half positional, half keyword # == NOT ALLOWED == bar(a=1, b=2) # Cannot use keyword for positional-only parameter

Reference: https://peps.python.org/pep-0570/

Re: Advanced Python Features

#164

Earlier quoted context omitted.

+1 to itertools especially. Absurdly powerful, and the recipes at the bottom of the doc page are terrific. The only problem I’ve found is that for interviews, people often aren’t familiar with it, which can lead to you solving whatever puzzle they had in far less time than they intended, and without manually building whatever logic it was they assumed you would need.

> The only problem I’ve found is that for interviews, people often aren’t familiar with it, which can lead to you solving whatever puzzle they had in far less time than they intended, and without manually building whatever logic it was they assumed you would need. My favourite example of a similar thing happening to me was when I was asked to reverse the digits in a number. I somewhat jokingly asked if I was assuming…

>I didn't get the job.

Their loss. Expecting an arithmetic solution to be necessary is incongruous with accepting the overhead of Python. IIRC your approach will actually be faster; the string conversion implicitly number-crunches on the bare metal, whereas any arithmetic approach in Python code won't.

Unless they wanted you to convert back to int afterwards. Or wanted you to reverse the string with the slicing trick (which is, indeed, quite a bit faster yet).

Re: Advanced Python Features

#165

Earlier quoted context omitted.

The most common case is when people use `if not s` to test for None in an otherwise string value (e.g. from JSON) without realizing that empty strings are also false.

... thank you for informing me that the code I wrote the other day is buggy. This sort of BS is exactly why I avoid JS. Truly one of the worst convenience "features" ever. We need a unary "truthy" operator so that code remains compact and readable without the surprising behavior.

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 equality. So that when I'm scanning the code later and I see "not len", I know right away it's an empty check specifically.

But, of course, this only works if you're doing it consistently. And since the language doesn't enforce it, and there's no idiomatic Python standard for it, the footgun remains...

Re: Advanced Python Features

#166

Earlier quoted context omitted.

... thank you for informing me that the code I wrote the other day is buggy. This sort of BS is exactly why I avoid JS. Truly one of the worst convenience "features" ever. We need a unary "truthy" operator so that code remains compact and readable without the surprising behavior.

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…

Those seem like opinionated rules that are easily added to ruff or other checkers to beat you over the head about. I know there are a bunch of truthiness opinions in ruff's catalog already that help me catch goofs.

Re: Advanced Python Features

#167

Earlier quoted context omitted.

... thank you for informing me that the code I wrote the other day is buggy. This sort of BS is exactly why I avoid JS. Truly one of the worst convenience "features" ever. We need a unary "truthy" operator so that code remains compact and readable without the surprising behavior.

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 thing.

Re: Advanced Python Features

#168

Every time I try to use Python I get this mixed feeling of liking how few guard rails there are between me and the logic I am making and this lingering worry that my code looks like fools attempt to use Python. So much exists as convention or loosely followed rules. Whenever I read articles like this I am wowed by the depth of things I didn't know about Python or how much has changed. It makes something like Go feel…

pick up a book on how to program pythonically and it will feel better, I promise. A lot of people program in python like they do in c++ or rust or javascript and it doesn't feel "right" to them. If you follow the pythonistas take I think you'll appreciate it better.

Re: Advanced Python Features

#169
not sure whether to laugh or cry at this ... looks like over the years python has agglomerated some of the features raku has had from day 1 (2015) in sadly inconsistent ways, often via module includes:

  - multi subs & methods = "typing overloads"
  - named & positional args
  - stubs = "future annotations"
  - subsets = "Generics"
  - protocols
  - wrappers = "context managers"
  - given / when = "structural pattern matching"
  - my declaration = "walrus op"
  - short circuit evaluation
  - operator chaining
  - fmt
  - concurrency
 
If you are a Python coder and you feel the need for some of this, I humbly suggest you take a look at https://raku.org

Re: Advanced Python Features

#170
post #64
post #27

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")`.

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.
Post reply on HN