Live data from Hacker News

Opaque Types in Python

blog.glyph.im

41–50 of 61 posts

Re: Opaque Types in Python

#41
post #26

Earlier quoted context omitted.

I agree that these are implemented "worse" than Java but that's because Python wants these things to be optional! You can complain about it as much as you want but that just means it's the wrong language for you, if that's important to you.

(I'd like to note that I wrote a lot of code in Java and Python, and continue to use each language in its respective strong areas. This isn't meant as a drive-by attack of "Java r00lz, Python sux"; this is an experienced take.) My real problem with the evolution of Python is that initially, the language and the community was positioned as anti-Java, anti-big-OOP-like-C++, and then it changed into the thing that it wa…

> Why go through the ceremony of `public static void main(String[] args)` when Python just executes the script line by line at the top level? Oh wait, now you have things like `import` actually executing code instead of simply being a compile-time namespace convenience, and you need weird techniques like `if __name__ == "__main__"`.

I don't think this is a fair criticism. Python is a scripting language, it makes sense that the code is executed line by line at the top level. This is also how other programming languages from its time like Perl or Bash does it. Even newer scripting languages like Ruby does something similar.

> Why `System.out.println()` when `print()` is so much more concise? But now you're polluting the global namespace, and `print(file=sys.stderr)` isn't that elegant either.

Another criticism that I don't think it is fair. Lots of other languages "polutes" the global namespace. I actually can't think another language other than Java that doesn't. Python at least still allow you to manually `import builtins`, but Go for example AFAIK has no mechanism for you to reference builtins if you end up shadowing them.

Also I find `print(file=sys.stderr)` pretty much elegant, it works exactly how I would expect, it also means I can open a file and write to it using `print`.

> And so Python 3 enabled static type hints... which, like I said before, Java had from day zero.

Again, I don't think this is fair. I find Python 3 type-hints much more powerful than whatever type system Java has, especially because Python has Option types that actually make the type system useful (Java is infamous for its NullPointerException for a reason).

Re: Opaque Types in Python

#42
post #4
post #3

You're holding it (Python) wrong. Python OO was a counter reaction to the bondage and discipline that languages like C++ had with private members and protected inheritance. If you have members that users probably shouldn't touch, you prepend them with an underscore. This is just a hint; It doesn't actually change anything. We're all adults here and we know the consequences of reaching into implementation details.

I agreed with this 100% for a long time. Then I started working on a library at $WORK with dozens of downstream users abusing the hell out of my idiomatic underscore usage, especially in the context of lazy tests with folks writing endless mocks. When I’d “break” their test suite (blocking some time sensitive release) I’d get all kinds of shit. But _they_ were breaking the contract. Unfortunately I had little (if any…

I'm torn. On the one hand, this is not too uncommon of a problem to run into. On the other, poor practices from coworkers are not going to go away thanks to a language filter.

So, the question will come down to which causes more grief, people abusing this convention, or people that overly use the language features that combat it? It is the standard optimization question between poor practices and enforcement that you have in any question of enforcement.

I would be delighted if we could get some empirical data on this.

Re: Opaque Types in Python

#43
post #13
post #4

Earlier quoted context omitted.

I agreed with this 100% for a long time. Then I started working on a library at $WORK with dozens of downstream users abusing the hell out of my idiomatic underscore usage, especially in the context of lazy tests with folks writing endless mocks. When I’d “break” their test suite (blocking some time sensitive release) I’d get all kinds of shit. But _they_ were breaking the contract. Unfortunately I had little (if any…

There’s always the extra idiomatic __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED for coworkers that can’t take a hint. https://github.com/reactjs/react.dev/issues/3896

You can technically "enforce" this at runtime with __getattribute__ or decorators[1].

Maybe be evil and add 1000 "Private access not allowed: {name}" with 1 second delays between each.

Aaaand, this flexibility is exactly why python is slow.

[1] https://pypi.org/project/accessify/

Re: Opaque Types in Python

#44

Earlier quoted context omitted.

> so I'm pretty sure the new preferred way is to explicitly use abstract superclasses... just like Java did all along (and is mandatory). typing.Protocol is a good fit for this use case from typing import Protocol class HasMessage(Protocol): def get_message(self) -> str: ... class A: """Implicit (duck-typed)""" def get_message(self) -> str: return "A" class B(HasMessage): """Explicit""" def get_message(self) -> str:…

Are you ever supposed to inherit from the protocol though(unless you’re defining another protocol)? One of the great things about protocols is that your class doesn’t even have to know about the protocol explicitly. What this code looks closer to doing (style wise) is an abstract base class

"To explicitly declare that a certain class implements a given protocol, it can be used as a regular base class. In this case a class could use default implementations of protocol members. Static analysis tools are expected to automatically detect that a class implements a given protocol. So while it’s possible to subclass a protocol explicitly, it’s not necessary to do so for the sake of type-checking."

https://peps.python.org/pep-0544/#explicitly-declaring-imple...

Re: Opaque Types in Python

#46
post #26

Earlier quoted context omitted.

I agree that these are implemented "worse" than Java but that's because Python wants these things to be optional! You can complain about it as much as you want but that just means it's the wrong language for you, if that's important to you.

(I'd like to note that I wrote a lot of code in Java and Python, and continue to use each language in its respective strong areas. This isn't meant as a drive-by attack of "Java r00lz, Python sux"; this is an experienced take.) My real problem with the evolution of Python is that initially, the language and the community was positioned as anti-Java, anti-big-OOP-like-C++, and then it changed into the thing that it wa…

> Why go through the ceremony of `public static void main(String[] args)` when Python just executes the script line by line at the top level? Oh wait, now you have things like `import` actually executing code instead of simply being a compile-time namespace convenience, and you need weird techniques like `if __name__ == "__main__"`.

You'll note that even Java now recognises that "public static void main(String[] args)" was pointless ceremony.

> Python scripts were meant to be lightweight and free of the tyranny of enterprise OOP which was epitomized by Java. But people found out that keeping track of types in your head is laborious and error-prone, and getting a compiler to check {that the shape of your objects and function calls match} is a huge productivity boost. And so Python 3 enabled static type hints... which, like I said before, Java had from day zero.

Java didn't have "hints", it had mandatory types everywhere. Which, again, they've now recognised was a bad idea and gradually removed. Having a type system is a good idea, and maybe if Python had taken more inspiration from OCaml (or more people had used OCaml instead of either Java or Python) we'd all be better off, but the early-2000s-Java cure of mandatory types everywhere was worse than the disease.

> To make matters worse, static type hint features were introduced progressively over the years, leading to things getting deprecated from the `typing` module and moved to things like `T|None` and `list[T]` and `collections.abc`.

Which happens in any language that evolves over time. Java, despite having a type system built into the language from day 1, now has about ten different deprecated sets of nullness annotations with overlapping functionality.

> I really don't think having top-level (module) variables and functions in Python is a good thing, especially because then they are duplicated as fields and methods in classes. In Java, fields and methods (whether static or instance) can only be placed in classes, and I think this particular straitjacket is a good thing.

Nah. No other language has adopted Java's approach, for good reason. Functions and values are easier than classes and the language shouldn't force you to complicate your code when there's no need to.

> Probably the most tragic example is the ways to build up strings in Python: `+` and str(), `%` operator, `str.format()`, f-string.

It sucks, but what's the alternative? Either a language dies young or it lives long enough to have a bunch of deprecated crap in it.

Re: Opaque Types in Python

#47
post #11
post #9

I'm sorry but if you write Python functions/methods in camel case I can't take you seriously.

Just fyi, the author is https://en.wikipedia.org/wiki/Glyph_Lefkowitz , creator of Twisted.

Wow, that's a much better reason to not take them seriously.

Re: Opaque Types in Python

#48
post #26

Earlier quoted context omitted.

I agree that these are implemented "worse" than Java but that's because Python wants these things to be optional! You can complain about it as much as you want but that just means it's the wrong language for you, if that's important to you.

(I'd like to note that I wrote a lot of code in Java and Python, and continue to use each language in its respective strong areas. This isn't meant as a drive-by attack of "Java r00lz, Python sux"; this is an experienced take.) My real problem with the evolution of Python is that initially, the language and the community was positioned as anti-Java, anti-big-OOP-like-C++, and then it changed into the thing that it wa…

> My real problem with the evolution of Python is that initially, the language and the community was positioned as anti-Java, anti-big-OOP-like-C++, and then it changed into the thing that it was against, but in a roundabout and suboptimal way. To me, the initial vibe of Python was, "write a 100-line script, don't worry about explicitly documenting types, don't worry about grand architecture, don't worry about creating custom classes, don't worry about encapsulation and public/private". I've been with Python since year 2007 in the 2.x days, and Java since 2002.

It really wasn't that anti-Java. Late 90s / early 2000s had a huge branch that was very dedicated to Java-style OOP. E.g. anything to do with Zope, and GvR himself worked on that at the time. Zope even has had its own ABC / interface system, specifically modeled after Java interfaces. stdlib logging is a reimplementation of log4j in Python and so on.

Re: Opaque Types in Python

#50
post #46
post #26

Earlier quoted context omitted.

(I'd like to note that I wrote a lot of code in Java and Python, and continue to use each language in its respective strong areas. This isn't meant as a drive-by attack of "Java r00lz, Python sux"; this is an experienced take.) My real problem with the evolution of Python is that initially, the language and the community was positioned as anti-Java, anti-big-OOP-like-C++, and then it changed into the thing that it wa…

> Why go through the ceremony of `public static void main(String[] args)` when Python just executes the script line by line at the top level? Oh wait, now you have things like `import` actually executing code instead of simply being a compile-time namespace convenience, and you need weird techniques like `if __name__ == "__main__"`. You'll note that even Java now recognises that "public static void main(String[] args…

> You'll note that even Java now recognises that "public static void main(String[] args)" was pointless ceremony.

There is still the part of the ceremony that actually mattered: having a single entrypoint instead of the option to litter side effects throughout the file and having those side effects execute automatically on import.

> It sucks, but what's the alternative?

3.0 was a big missed opportunity to kill a lot of the deprecated cruft.

Post reply on HN