Live data from Hacker News

I'm switching to Python and actually liking it

cesarsotovalero.net

311–320 of 718 posts

Re: I'm switching to Python and actually liking it

#311
post #298
post #276

Earlier quoted context omitted.

I don't think that the talk has been released on public YouTube yet (and they made it clear to not share the unlisted links publicly), but here is the posting: [url-redacted] And the slides are available here: [url-redacted] I'm afraid that my humor isn't really reflected in the slides, but imagine everything here is said kind of snarkily. Java can be mostly as nice as Go, the BlockingQueues and Virtual Threads can g…

Github link is 404

Oops! Forgot to make the repo public!

Should be fixed now. Sorry about that.

Re: I'm switching to Python and actually liking it

#312

Earlier quoted context omitted.

That's kind of the point. These methods are never meant to be called directly. They're used to desugar. I think it's fairly short sighted to criticize these. FWIW, I also did that the first time I wrote Python. Other languages that do similar things provide a useful transparency.

I don’t think anyone is criticizing its utility, just that the syntax of 2-5(?) underscores in a row isn’t something that is DX friendly.

The ugliness is intentional. Nobody wants to name their cool new variable __hot__singleton__in__your__area__.

Re: I'm switching to Python and actually liking it

#313
post #67

Earlier quoted context omitted.

I like that magic method names generally all follow the same form so it's obvious that they are magic methods and not intended to be part of the public API. Whether that form uses double underscores or something else doesn't really matter to me as they are not being called directly.

Would you consider a constructor magic though?

Yes, it is magic the same way other magic methods are, that is, because it is syntactically special and callable (and primarily called by) a syntax other than .(...) or .(instance, ...)

Specifically, in the case of constructors, via (...).

Re: I'm switching to Python and actually liking it

#314
post #305

Earlier quoted context omitted.

The funniest thing for me is that you can use uv in mise to install Python cli programs in a surprisingly elegant manner.

Just curious: how?

They may be referring to uvx: https://docs.astral.sh/uv/guides/tools/

Or it could be something else, not sure.

Re: I'm switching to Python and actually liking it

#315

Out of curiosity, why would I use Dataclass vs a Pydantic Basemodel. If we did not have a PyDantic dependency I could imagine wanting to use Dataclass. But if I have it, why not use everywhere?

Performance hit from data validation at construction time. I like msgspec which is much leaner and faster.

Re: I'm switching to Python and actually liking it

#316
post #274
post #248

Earlier quoted context omitted.

That is general take as well. A lot of small apps/simulators are in python. Ops scripts tend to be python. Java for the core/data. Refactoring/tooling is easier in Java when you are dealing with a 100k codebase imo. Typescript always. Seen plenty of coding horrors in both ecosystems...

Algorithms are a lot easier to understand when they are written in Python. I'm actually right now documenting medium size Java codebase by writing pseudocode, which looks like Python. Just by doing that, I've already discovered multiple bugs, which I didn't catch by looking at the Java code.

That might be the big thing that I think gets glossed over in a lot of these discussions. I agree that I wouldn't want to maintain 100kloc of Python. But, I don't really view that as a realistic hypothetical for a business application. Idiomatic Python tends to require a fraction as much code as idiomatic Java to accomplish the same task. The only time it even gets close is when you have code written by people who go out of their way to make things look like old-school enterprisey Java. So it ends up accumulating a bunch of stuff like

  class IWantToBeABean:
    def init(self, arg1: int, arg2: str, arg4: str) -> None:
      self._field1: int = arg1
      self._field2: str = arg2
      self._field3: str = arg3

    def get_field1(self) -> int:
      return self._field1

    def set_field1(self, value: int) -> None:
      self._field1 = value
    
    def get_field2(self) -> str:
      return self._field2

    def set_field2(self, value: str) -> None:
      self._field2 = value

    def get_field3(self) -> str:
      return self._field3

    def set_field3(self, value: str) -> None:
      self._field3 = value

when it could have just been:

  @dataclass
  class IDontWantToBeABean:
    field1: int
    field2: str
    field3: str

The worse case for Python is when you get people doing the oldschool Python thing of acting like dynamic and duck typing means it's OK to be a type anarchist. Scikit-learn's a good one to put on blast here, with the way that the type and structure of various functions' return values, or even the type and structure of data they can handle, can vary quite a bit depending on the function's arguments. And often in ways that are not clearly documented. Sometimes the rules even change without fanfare on minor version upgrades.

The reason why large Python codebases are particularly scary isn't necessarily the size itself. It's that for a codebase to even get that large in the first place it's very likely to have been around so long that the probability of it having had at least one major contributor who likes to do cute tricks like this is close to 1. And I'd take overly verbose like the Java example above over that kind of thing any day.

Re: I'm switching to Python and actually liking it

#317

Earlier quoted context omitted.

Because sometimes I want to have logic that spans multiple lines and I don't want to assign it a name. An easy example might be something with a `map` or a filter. For example, in JavaScript [1,2,3,4].filter(x => { let z = x * 2; let y = x * 3; let a = x / 2; return (z + x * a) % 27 == 2; }); Obviously I know I could name this function and feed it in, but for one-off logic like this I feel a lambda is descriptive eno…

> Obviously I know I could name this function and feed it in, but for one-off logic like this I feel a lambda is descriptive enough and I like that it can be done in-place. FWIW, you'd also have the benefit of being able to unit test your logic.

I mean, maybe, that's why your lambdas shouldn't be too long.

I have done a lot of Haskell and F#, and I'm very familiar with the concept of "lifting", and yeah being able to individually test the components is nice, but even within Haskell it's not too uncommon to use a lambda if the logic doesn't really need to be reused or is only a couple lines.

If you have a huge function, or you think there's any chance of the logic being reused, of course don't use a lambda, use a named function. I'm just saying that sometimes stuff that has 2-4 lines is still not worthy of having a name.

Re: I'm switching to Python and actually liking it

#318

I make projects following almost identical patterns. It's a little uncanny. Maybe the people in the python developer ecosystem are converging on a pretty uniform way to do most things? I though some of my choices were maybe "my own", it seeing such consistency makes me question my own free will. It's like when people pick a "unique" name for their baby along with almost everyone else. What you thought was a unique na…

This sort of architecture has been in favor with python for at least 10 years or so, but I think you're right — the structure just makes sense, so many reasonable engineers converge on using it.

Re: I'm switching to Python and actually liking it

#319
post #172

Earlier quoted context omitted.

I write a decent amount of Python, but find the walrus operator unintuitive. It's a little funky that API_KEY is available outside of the `if`, perhaps because I had first seen the walrus operator in golang, which restricts the scope to the block.

This isn't really unique to the walrus operator, it's just a general python quirk (albeit one I find incredibly annoying). `for i in range(5): ...` will leave `i` bound to 4 after the loop.

Oddly enough, "except" variables don't remain bound!

    try:
        x = int('cat')
    except Exception as e:
        pass
    print(e)  # 
So, it appears Python actually has three variable scopes (global, local, exception block)?

Re: I'm switching to Python and actually liking it

#320

Earlier quoted context omitted.

Because sometimes I want to have logic that spans multiple lines and I don't want to assign it a name. An easy example might be something with a `map` or a filter. For example, in JavaScript [1,2,3,4].filter(x => { let z = x * 2; let y = x * 3; let a = x / 2; return (z + x * a) % 27 == 2; }); Obviously I know I could name this function and feed it in, but for one-off logic like this I feel a lambda is descriptive eno…

Honestly, I don't really see the appeal of unnamed functions in general. I so rarely use lambdas that I wouldn't really miss them if they were gone. Just occasionally as a sort key, or in a comprehension. I have seen people do this in JavaScript quite often, but I always assumed there was some kind of underlying performance benefit that I didn't know about. As I think about it I guess it makes sense if you're passing…

Obviously it's totally fine to have a difference of opinion for something like this.

> I have seen people do this in JavaScript quite often, but I always assumed there was some kind of underlying performance benefit that I didn't know about.

I don't think so, at least I haven't heard of it if there is.

I tend to have a rule of thumb of "if it's more than 6-7 lines, give it a name". That's not a strict rule, but it's something I try and force myself to do.

Like in Python, most lambdas can be done in one line, but that also kind of gets into a separate bit of gross logic, because you might try and cram as much into an expression as possible.

Like, in my example, it could be written like this:

    [1,2,3,4].filter(x =>((x * 2) + x * (x/2)) % 27 == 2);
But now I have one giant-ass expression because I put it all into one line. Now where previously I had two extra names for the variables, I have the ad-hoc logic shoved in there because I wanted to squeeze it into a lambda.
Post reply on HN