The prohibition overrides the class method

Hello, I want to apologize for my English. I propose to make an analogue of the final specifier in C ++. In class abc.ABCMeta has decorator abstractmethod, you can add decorator finalmethod. I have a sketch of implementation: def finalmethod(funcobj): funcobj.__isfinalmethod__ = True return funcobj class Override(ABCMeta): def __init__(cls, name, bases, namespace): super(Override, cls).__init__(name, bases, namespace) finals = {name for name, value in namespace.items() if getattr(value, "__isfinalmethod__", False) } for base in bases: for name in getattr(base, "__finalmethods__", set()): value = getattr(cls, name, None) if getattr(value, "__isfinalmethod__", False): finals.add(name) else: raise TypeError("function '" + str(value.__name__) + "' in class '" + str(cls.__name__) + "' is final") cls.__finalmethods__ = frozenset(finals)

On Tue, Nov 17, 2015 at 2:03 AM, Иван Спиненко <spinenkoia@gmail.com> wrote:
Hello, I want to apologize for my English.
It's fine - and a lot better than my Russian! (Or Ukrainian, or any of the other languages that use a Cyrillic script. See, I can't even tell one from another - all I know is which script you've used.)
I propose to make an analogue of the final specifier in C ++. In class abc.ABCMeta has decorator abstractmethod, you can add decorator finalmethod.
It's not common in Python to actually enforce this kind of thing. What's the advantage of stopping people from overriding some methods? In Java, as I understand it, the compiler optimizes calls to final methods; but in Python, you can even add methods to individual instances of a class:
Can you show an example of how this decorator would help your project? If so, it might make a useful recipe, rather than actually a part of the language or standard library - it can go into a collection of "here's some neat tricks you can do with function decorators" tips. ChrisA

On Mon, Nov 16, 2015 at 8:44 AM, Chris Angelico <rosuav@gmail.com> wrote:
I would add the point that while abstractmethod helps the programmer by warning when they've forgotten to implement a method, finalmethod is more likely to just get in the way when the programmer needs to override a method, but the class author has arbitrarily decided that they can't. Python usually tries to give the programmer what they need while staying out of their way as much as possible.

It's a well-known feature from other languages ("sealed"). Though, I tend to agree here that Python should not create barriers. What would a real-world example look like? I cannot imagine where people can decide *properly***when to place that modifier. Best, Sven

On Nov 16, 2015, at 07:03, Иван Спиненко <spinenkoia@gmail.com> wrote:
Hello, I want to apologize for my English. I propose to make an analogue of the final specifier in C ++. In class abc.ABCMeta has decorator abstractmethod, you can add decorator finalmethod.
Since the C++ standard is (mostly) written based on public proposals on open-std.org, presumably there's some discussion of the motivation behind adding this feature to C++11. It would be worth knowing what that motivation is, to see whether it applies to Python. For example, if it was proposed just to provide optimization opportunities, or to be closer to C++/CLI, then it probably isn't worth adding to Python (unless you have Python-specific use cases to offer, and it's just a coincidence that C++ and Python could use very similar features). On the other hand, if it solves a real problem with making some hierarchies easier to read, or removing opportunities for hard-to-diagnose errors, then it may be (assuming those problems have equivalents in Python). Sometimes there are also blog posts presenting the idea to C++ users instead of the C++ committee, which often get the motivation across better (e.g., explaining how rvalue references solve the forwarding and move problems that boost ran into with the previous version of C++). So, if you want to suggest a feature copied from C++11, it's probably worth searching for those references and providing links and summaries. I suspect that it's primarily for optimization. In C++, by default, methods can't be overridden, so if the compiler sees spam.cook() it can just compile in a direct call to Spam::cook. But if cook() is declared virtual in either Spam or any of its superclasses, it instead has to compile an indirect call to spam->vtable[1], which also means it will usually keep Spam::vtable in L2 cache whenever a Spam object is around, and so on, which can make a big difference. So, when the compiler can prove that spam really is a Spam, and not some subtype (e.g., because the function constructed it locally, or accepted it by value), it will optimize out the virtual call. What final adds is that if cook() is declared final in Spam or any of its superclasses, the compiler can optimize out the virtual call even if the value could actually be a subtype (e.g., because the function accepted it by reference), because it would be illegal for any such subtype to have overridden the method. So, that can be a huge benefit. Obviously, none of this applies in Python. Methods are always looked up by name in the value's dict, then the class and each of its bases at runtime; there's no concept of a variable's type to start the search at, and no way to record something that can be directly called at compile time (especially since type, function, and method objects are themselves constructed at runtime).

I'm not sure how this thread has gone on this long without anyone mentioning __methods. If you prefix a method with two underscores, it will transform the name of the method in order to make it difficult to accidentally override. So in other methods inside the base class that need to call your method, you can call the underscored version and subclasses won't override it (I think it's possible for them to e.g. class A: def __test(self): print("123") def test(self): return self.__internal_test() def other_function(self): ... self.__test() ... class B(A): def __test(self): print("456")
B().test() 123
B can still override test if it wants to, but it won't affect any calls to the __test method from A's other methods. If it *really* wants to, it can override _A__test(), but someone's not likely to do that by mistake.

2015-11-16 16:03 GMT+01:00 Иван Спиненко <spinenkoia@gmail.com>:
I propose to make an analogue of the final specifier in C ++. In class abc.ABCMeta has decorator abstractmethod, you can add decorator finalmethod.
Would it be allowed to override the method in the class where the method is defined using unittest.mock? Mocking looks popular and importang in the Python community to write unit tests. Victor

On Tue, Nov 17, 2015 at 2:03 AM, Иван Спиненко <spinenkoia@gmail.com> wrote:
Hello, I want to apologize for my English.
It's fine - and a lot better than my Russian! (Or Ukrainian, or any of the other languages that use a Cyrillic script. See, I can't even tell one from another - all I know is which script you've used.)
I propose to make an analogue of the final specifier in C ++. In class abc.ABCMeta has decorator abstractmethod, you can add decorator finalmethod.
It's not common in Python to actually enforce this kind of thing. What's the advantage of stopping people from overriding some methods? In Java, as I understand it, the compiler optimizes calls to final methods; but in Python, you can even add methods to individual instances of a class:
Can you show an example of how this decorator would help your project? If so, it might make a useful recipe, rather than actually a part of the language or standard library - it can go into a collection of "here's some neat tricks you can do with function decorators" tips. ChrisA

On Mon, Nov 16, 2015 at 8:44 AM, Chris Angelico <rosuav@gmail.com> wrote:
I would add the point that while abstractmethod helps the programmer by warning when they've forgotten to implement a method, finalmethod is more likely to just get in the way when the programmer needs to override a method, but the class author has arbitrarily decided that they can't. Python usually tries to give the programmer what they need while staying out of their way as much as possible.

It's a well-known feature from other languages ("sealed"). Though, I tend to agree here that Python should not create barriers. What would a real-world example look like? I cannot imagine where people can decide *properly***when to place that modifier. Best, Sven

On Nov 16, 2015, at 07:03, Иван Спиненко <spinenkoia@gmail.com> wrote:
Hello, I want to apologize for my English. I propose to make an analogue of the final specifier in C ++. In class abc.ABCMeta has decorator abstractmethod, you can add decorator finalmethod.
Since the C++ standard is (mostly) written based on public proposals on open-std.org, presumably there's some discussion of the motivation behind adding this feature to C++11. It would be worth knowing what that motivation is, to see whether it applies to Python. For example, if it was proposed just to provide optimization opportunities, or to be closer to C++/CLI, then it probably isn't worth adding to Python (unless you have Python-specific use cases to offer, and it's just a coincidence that C++ and Python could use very similar features). On the other hand, if it solves a real problem with making some hierarchies easier to read, or removing opportunities for hard-to-diagnose errors, then it may be (assuming those problems have equivalents in Python). Sometimes there are also blog posts presenting the idea to C++ users instead of the C++ committee, which often get the motivation across better (e.g., explaining how rvalue references solve the forwarding and move problems that boost ran into with the previous version of C++). So, if you want to suggest a feature copied from C++11, it's probably worth searching for those references and providing links and summaries. I suspect that it's primarily for optimization. In C++, by default, methods can't be overridden, so if the compiler sees spam.cook() it can just compile in a direct call to Spam::cook. But if cook() is declared virtual in either Spam or any of its superclasses, it instead has to compile an indirect call to spam->vtable[1], which also means it will usually keep Spam::vtable in L2 cache whenever a Spam object is around, and so on, which can make a big difference. So, when the compiler can prove that spam really is a Spam, and not some subtype (e.g., because the function constructed it locally, or accepted it by value), it will optimize out the virtual call. What final adds is that if cook() is declared final in Spam or any of its superclasses, the compiler can optimize out the virtual call even if the value could actually be a subtype (e.g., because the function accepted it by reference), because it would be illegal for any such subtype to have overridden the method. So, that can be a huge benefit. Obviously, none of this applies in Python. Methods are always looked up by name in the value's dict, then the class and each of its bases at runtime; there's no concept of a variable's type to start the search at, and no way to record something that can be directly called at compile time (especially since type, function, and method objects are themselves constructed at runtime).

I'm not sure how this thread has gone on this long without anyone mentioning __methods. If you prefix a method with two underscores, it will transform the name of the method in order to make it difficult to accidentally override. So in other methods inside the base class that need to call your method, you can call the underscored version and subclasses won't override it (I think it's possible for them to e.g. class A: def __test(self): print("123") def test(self): return self.__internal_test() def other_function(self): ... self.__test() ... class B(A): def __test(self): print("456")
B().test() 123
B can still override test if it wants to, but it won't affect any calls to the __test method from A's other methods. If it *really* wants to, it can override _A__test(), but someone's not likely to do that by mistake.

2015-11-16 16:03 GMT+01:00 Иван Спиненко <spinenkoia@gmail.com>:
I propose to make an analogue of the final specifier in C ++. In class abc.ABCMeta has decorator abstractmethod, you can add decorator finalmethod.
Would it be allowed to override the method in the class where the method is defined using unittest.mock? Mocking looks popular and importang in the Python community to write unit tests. Victor
participants (7)
-
Andrew Barnert
-
Chris Angelico
-
Ian Kelly
-
Random832
-
Sven R. Kunze
-
Victor Stinner
-
Иван Спиненко