Continuing the definition for a class feels to me like a strong anti-pattern for Python. If you absolutely must do this, I guess the presented decorator is available. It should be discouraged though, not be part of new syntax.
I believe that if you find yourself doing this you should detect a bad choice smell, and think about expressing your goal with inheritance, delegation, or encapsulation instead. On Sep 13, 2016 9:17 AM, "Pim Schellart" <p.schell...@princeton.edu> wrote: > Dear Python Developers, > > we have a potential idea for enhancing Python. > Below you will find what the PEP might look like. > A reference implementation has been written and will be posted in a follow > up message. > We are look forward to hearing your feedback and ideas. > > Kind regards, > > Pim Schellart & Nate Lust > > Abstract > ======== > > This PEP proposes the introduction of new syntax to create a community > standard, > readable way to continue a definition for classes which are already > defined. > > > Rationale > ========= > > Extending existing classes with new members currently requires the members > to be > defined outside of class scope and then assigned to the class, as in:: > > def foo(self): > pass > A.foo = foo > del foo > > This pattern frequently occurs when extending classes from extension > modules > written in other languages, but is also not uncommon in pure Python code. > > This syntax is however cumbersome and error prone for the following > reasons: > > 1. The name of the new member might clash with an existing name at module > scope. > 2. The developer might forget the assignment. > 3. The developer might forget to delete the temporary, leaving it at > module > scope where it is meaningless (or worse non functional as a stand > alone > function). > > Alternatives are to use inheritance, lambda or a decorator. > > Inheritance is not a good option for use with Python extension modules > (written > in for instance C / C++). The reason is that if in the other language the > inheritance relation is A<-B, and this is exposed to Python, we can't add > functionality to A in Python by subclassing A<-A' without also introducing > B' > that inherits from B and A'. Thus one change propagates all the way down > the > inheritance chain. Inheritance with pure Python classes exhibit the same > issue. > > It might be tempting to avoid (1) and (2) by subclassing, reusing the name > of > the base class. However this approach suffers from two issues. The first > issue, > like above, has to do with the inheritance relation. If A subclasses A > and B > subclasses A (A<-A<-B), then calls to super in B may have unexpected > behavior > (anything using the method resolution order may exhibit the same > unexpectedness). The second issue arises when class B inherits from class > A > before it is extended (A<-B) and then class A is extended though > inheritance > (A<-A). Class A will now have new methods and data members which are not > present in B, as it is a subclass only of the original A. This would be > confusing to anyone examining B as it would be apparently missing members > of > it's parent. > > Adding attributes to a class using lambda is not equivalent because it only > allows for expressions and not statements. > > A class decorator (say "@continue_class(A)" that takes methods and > attributes > from the class and attaches them to the wrapped type) works, but is > cumbersome > and requires a new class name to be introduced for each extended type. > Thus > suffering from the same problems numbered (1) and (2) above. > > A function decorator could extend a class, but also requires defining a > new name > and suffers from problems (1) and (2). > > This proposal adds the keyword combination "continue class" which > instructs the > interpreter to add members to an existing class. This syntax requires no > new > keywords and allows all existing Python code to continue to function with > no > modification. > > By combining existing keywords it avoids name clashes. Precedents for this > exists in "is not" and "yield from". > > Another big advantage of the "continue class" syntax is discoverability. > For > humans, the meaning of the syntax is evident, the class will be continued > with > the following block. Automated tools will also benefit from this syntax as > parsing a file to discover the complete definition of a class will be > easier > than trying to detect 'monkey patching'. > > > Semantics > ========= > > The following two snippets are semantically identical:: > > continue class A: > x = 5 > def foo(self): > pass > def bar(self): > pass > > def foo(self): > pass > def bar(self): > pass > A.x = 5 > A.foo = foo > A.bar = bar > del foo > del bar > > > Alternatives > ============ > > An alternative could be to allow a function definition to include a class > specifier as in:: > > def A.foo(self): > pass > > > Implementation > ============== > > Adapting Python's grammar to support the continue class keyword combination > requires modifying the grammar file to parse for the new keyword > combination. > Additional changes to Python.asdl, ast.c, compile.c, symtable.c will be > required > to process the parsed syntax to byte code. > > A reference implementation (already written and posted separately) parses > the > continue class line for the name of the class to be modified and loads > it. Next > the body of the block is compiled into a code object scoped by the name of > the > class. The class and the code are used as arguments to a new built-in > module, > called __continue_class__. This function evaluates the code block, > passing the > results to setattr on the supplied class. > _______________________________________________ > Python-ideas mailing list > Python-ideas@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/