Executive summary: I'm sorry so many people have not gotten much out of the parent thread. Despite my disagreements with the OP, I find traits to be an interesting concept, and I'll probably try out Simionato's strait library[1]. I agree with several posters that traits neither need nor are important enough to deserve special syntax.
In my previous post, I pointed out that traits conform to a slew of Zen that general multiple inheritance violates, and even mixins can only avoid with disciplined use. I think they're worth considering if you use mixins as they prevent foot-shooting in some reasonably frequent cases. Of course the flip side is that undisciplined use of mixins is not always going to put you on crutches, so YMMV. Some details follow, if I've piqued your interest. The point of traits as defined by Schärli et al is more or less that the support for traits respects the Zen: - Flat is better than nested. - Readability counts. - In the face of ambiguity, refuse the temptation to guess. - If the implementation is hard to explain, it's a bad idea. - Namespaces are one honking great idea -- let's do more of those! Unlike mixins, which are just a disciplined use of classes in Python, proper traits satisfy a "flattening" property: a class or trait composed from several traits behaves exactly the same as if all methods were defined directly in the class or composite trait, regardless of nesting of traits or order of addition. If you combine two traits, you get a new trait. You can still combine the new trait with either or both of the older ones, because the method implementations are the same. (I don't know if strait implements this check; it may do the easy thing and just check for name conflicts.) To extend this property to work with class inheritance, the only method resolution order (MRO) you need to know for traits is: a definition in a class overrides a definition in a trait used by the class which overrides a definition in a superclass of the class. Composite traits aren't actually flat, and so cost some readability, but at least you don't need to compute the MRO. Again, unlike mixins which invoke the MRO to disambiguate methods defined in multiple mixins in the class hierarchy, when multiple traits define methods for the same name, the class using those traits must "refuse the temptation to guess" (even if obvious!) and explicitly disambiguate. Traits improve "readability" by avoiding the MRO, which is "hard to explain." Everything you need to know about which methods will be invoked is in the class definition, although you may need to read trait documentation to know all the methods implemented. And as the OP points out, traits provide "namespaces" (so I guess we can count Uncle Tim as a vote for traits! ;-) The bottom line is that disciplined use of mixins likely provides most of the benefits of traits if that discipline includes a very flat class hierarchy and sufficient care in avoiding method name collisions. Finally, an aside on Simionato's blog post. He claims that although traits are a lot safer than general multiple inheritance or even mixins, generic functions are "better" than traits. I don't understand the interaction between generic functions and traits in Rust yet, but in that language they are evidently complementary features, not alternatives. Further reading: This tutorial on Rust (readable, although the examples are excessively verbose) http://gradebot.org/doc/ipur/trait.html indicates that in that language, interface definition is the primary purpose of a trait in (I don't take a tutorial as definitive, although the tutorial mirrors Soni's focus on interface), but traits are allowed to have default implementations of methods. zope.interface interfaces deliberately avoid that; they're "pure" interfaces (at least where I've used them). Nothing in any of the Rust documentation I looked at so far emphasizes code reuse or default implementations. I gather Rust also implements at least some "trait algebra," as Wikipedia describes: https://en.wikipedia.org/wiki/Trait_(computer_programming)#Characteristics After further research, I see that only "+" is implemented, and so far I have not been able to find documentation of whether it's disjoint or overriding. Soni's post implies that if there are multiple implementations, one will be chosen (but any others are still accessible to code that knows which trait it wants). See also Fisher and Reppy for an extended treatment of trait algebra http://newtraell.cs.uchicago.edu/files/tr_authentic/TR-2003-13.pdf which cites Schärli et al, but not vice versa. The Schärli et paper is here: http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf Footnotes: [1] Which I keep spelling as "Simionati", mea culpa. https://www.artima.com/weblogs/viewpost.jsp?thread=246488 -- Associate Professor Division of Policy and Planning Science http://turnbull/sk.tsukuba.ac.jp/ Faculty of Systems and Information Email: turnb...@sk.tsukuba.ac.jp University of Tsukuba Tel: 029-853-5175 Tennodai 1-1-1, Tsukuba 305-8573 JAPAN _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/TAKYHTLSSFIMAMYDMC6H5MZU6SF7UCPD/ Code of Conduct: http://python.org/psf/codeofconduct/