3 ms·
I don't understand how this works: https://github.com/xrudelis/pytrait/blob/master/examples/basics.py https://github.com/xrudelis/pytrait/blob/master/examples/b
by _dain_ 5y ago
I don't understand how this works: https://github.com/xrudelis/pytrait/blob/master/examples/basics.py 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?
- aldanor 5y agoSome pretty horrible string / 'registry' metaclass hackery: https://github.com/xrudelis/pytrait/blob/master/pytrait/impl.py#L41 https://github.com/xrudelis/pytrait/blob/master/pytrait/impl...
- xrudelis 5y agoThat'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 5y agoThat'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 5y agoI 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. EDIT2: I have updated the code to allow for another syntax: class AnyImplNameIWant(MyTrait, metaclass=Impl, target="MyStruct"): ... It would certainly be nicer if `MyStruct` didn't need to be a string of course. I really think these options are mostly down to taste, so I'll just have to trust that this alternative reads sufficiently more nicely.
- aldanor 5y agoCorrection: 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 5y agoI'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.
- OJFord 5y agoWhy not use a decorator for that? @impl(Sheep, Animal) class ImplAnimalForSheep: ... or something? It probably needn't even be a separate class - just decorate the relevant methods (or the `Sheep` class itself) `@impl(Animal)` and check the necessary ones are implemented on instantiation.
- homarp 5y agoit'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."