[HN Gopher] Show HN: Rust-Like Traits in Python
___________________________________________________________________
Show HN: Rust-Like Traits in Python
Author : xrudelis
Score : 16 points
Date : 2021-11-21 20:03 UTC (2 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| xrudelis wrote:
| This is an idea I had while thinking about how flexible Python
| inheritance is. I decided to turn it into a weekend project, and
| now it is my first open-source package. I hope someone finds it
| useful!
| miohtama wrote:
| Something that fills the same need as traits have been available
| for Python in the form of zope.component architecture for some
| decades now
|
| https://zopecomponent.readthedocs.io/en/latest/narr.html
|
| However in the end abstract base classes and class decorators
| take you a long way. zope.component power is only useful for
| complex frameworks like Plone CMS and Pyramid.
| webmaven wrote:
| This reminds me of Python interfaces, which were inspired by Zope
| interfaces.
|
| Choosing among competing interfaces overriding the MRO was a
| runtime configuration option, often using adapters to wrap other
| objects. This turns out to be handy when implementing a CMS
| extended with 3rd-party plugins that aren't written with each
| other in mind. Fun times!
| orf wrote:
| How does this differ in practice from typing.Protocol?
| _dain_ wrote:
| I don't understand how this works:
| https://github.com/xrudelis/pytrait/blob/master/examples/bas...
|
| The "Sheep" class never inherits from "Animal" or
| "ImplAnimalForSheep", nor does its body reference them in any
| way, so how does it get the "talk" method?
| homarp wrote:
| it's the naming convention that does it.
|
| "Impls have a strict naming convention, like
| ImplMyTraitForMyStruct. This is used to automate the list of
| implementations for MyStruct; you don't need to explicitly list
| any superclasses of MyStruct, just based on the Impl name it
| will inherit from all relevant Impls."
| aldanor wrote:
| Some pretty horrible string / 'registry' metaclass hackery:
| https://github.com/xrudelis/pytrait/blob/master/pytrait/impl...
| xrudelis wrote:
| That's right. The reason for this is that it's a lot of
| boilerplate if you were to require listing every relevant
| Impl block as a superclass of your struct. I also, as a
| bonus, like enforcing a consistent class naming style.
| Diggsey wrote:
| That's not a great reason to use strings to identify
| classes though...
|
| Why not just give `Impls` a special attribute:
| class ExampleImpl(Foo, metaclass=Impl): target
| = Bar
|
| Or do the entire thing via a decorator:
| @impl_for(Bar) class ExampleImpl(Foo):
| pass ?
| xrudelis wrote:
| I think these are all equally good. The Impl's name
| should never need to be referred to, so ultimately the
| choice should be based on what's easiest to read.
|
| EDIT: actually, your examples wouldn't work as-is, since
| it would result in circular references (something Python
| isn't well-equipped to handle). Your target names would
| need to be strings instead of the actual class.
| aldanor wrote:
| Correction: what's easiest to read to someone who hasn't
| carefully read every single line of your library.
| Verbosity is not always bad, if it yields clarity.
| luoc wrote:
| I'd go for the decorator approach for its explicitness.
| It reads like plain English without having a deeper
| understanding of the concepts. Also, it does not pollute
| the implementors namespace. Even if one argues for the
| naming convention solution, one has to admit that it
| causes confusion for most people stumbling over it for
| the first time.
___________________________________________________________________
(page generated 2021-11-21 23:00 UTC)