Live data from Hacker News

Opaque Types in Python

blog.glyph.im

51–60 of 61 posts

Re: Opaque Types in Python

#51
post #50
post #46

Earlier quoted context omitted.

> 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…

> the option to litter side effects throughout the file and having those side effects execute automatically on import.

You can actually do that in Java too with static initialisation blocks.

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

Maybe. 3.0 already came damn close to killing the language. If they'd made the changes any more radical it could easily have been another Perl 6.

Re: Opaque Types in Python

#52
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 generally agree with you (and disagree with the parent comment) that I think this seems like a useful technique. But just note that if someone really wants to break the contract, they can just use the "private" class. Just like "private" members, it is only private by convention.

Re: Opaque Types in Python

#53
post #8
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.

"Glyph" knows. He has been in the Python inner circle for decades back to when the circle promoted "spam and eggs" and "consenting adults". Like the rest of that circle, he moves with the times, supports public shaming of Tim Peters and others and now promotes poorly implemented information hiding so Python ticks a few more boxes for the industry. Information hiding in a language that allows changing the values of sm…

I don't know who any of these people are. This seems very gossipy.

Re: Opaque Types in Python

#54

Funny, I ran into the same pattern just a few months ago! In practice, I found it difficult for coworkers to read and understand so I dropped the idea. Another limitation I found is that it breaks down when you start using inheritance. For example: ``` class _A: pass A = NewType("A", _A) class _B(_A): pass B = NewType("B", _B) def foo(a: A) -> None: pass b = B(_B()) foo(b) # Mypy is not happy: Argument 1 to "foo" has…

Just use a generic and make it bound to (A, B) : from typing import * class _A: pass class _B(_A): pass A = NewType("A", _A) B = NewType("B", _B) def foo[T: (A, B)](val: T) -> T: return val a = A(_A()) b = B(_B()) _a = foo(a) _b = foo(b) reveal_type(_a) reveal_type(_b) Playground here: https://mypy-play.net/?mypy=latest&python=3.12&gist=36573363...

This does seem like an abstraction leak though.

Re: Opaque Types in Python

#55

The main problem with such approach is that `class _RealShipOpts:` is very ugly to write unit tests for. You need to import a private entity in tests. I would slightly change the presented approach, and move the "public" `ShippingOptions`, `shipFast`, etc., into a new module that is a public API, for my users to use something like `from my_lib.shipping.api import ShippingOptions`. That way, I can use "normal" naming…

Why wouldn't you just write the tests against the public api?

Re: Opaque Types in Python

#58

Earlier quoted context omitted.

Just use a generic and make it bound to (A, B) : from typing import * class _A: pass class _B(_A): pass A = NewType("A", _A) B = NewType("B", _B) def foo[T: (A, B)](val: T) -> T: return val a = A(_A()) b = B(_B()) _a = foo(a) _b = foo(b) reveal_type(_a) reveal_type(_b) Playground here: https://mypy-play.net/?mypy=latest&python=3.12&gist=36573363...

This does seem like an abstraction leak though.

The abstraction gets leaky once you expect the distinct NewTypes to adhere to the original inheritance property. I think that's a wrong assumption from the get-go.

OP could just do:

    def foo(val: _A) -> None:
        pass
...and it'll accept both NewTypes just fine. I guess it depends on whether foo is designed to be public or private.

Re: Opaque Types in Python

#59

Earlier quoted context omitted.

This does seem like an abstraction leak though.

The abstraction gets leaky once you expect the distinct NewType s to adhere to the original inheritance property. I think that's a wrong assumption from the get-go. OP could just do: def foo(val: _A) -> None: pass ...and it'll accept both NewType s just fine. I guess it depends on whether foo is designed to be public or private.

This works but it does not let other modules define such methods.

Re: Opaque Types in Python

#60
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…

> Then I started working on a library at $WORK with dozens of downstream users abusing the hell out of my idiomatic underscore usage [...]. When I’d “break” their test suite [...] I’d get all kinds of shit

I can understand this happening once. But, after that, management should have been involved and addressed the root problem. It would be no longer a technical or communication issue, but a project management one.

Post reply on HN