In Python, how do I indicate I'm overriding a method?

前端 未结 10 1866
长情又很酷
长情又很酷 2020-11-29 15:43

In Java, for example, the @Override annotation not only provides compile-time checking of an override but makes for excellent self-documenting code.

I\

相关标签:
10条回答
  • 2020-11-29 16:23

    Based on @mkorpela's great answer, I've written a similar package (ipromise pypi github) that does many more checks:

    Suppose A inherits from B and C, B inherits from C.

    Module ipromise checks that:

    • If A.f overrides B.f, B.f must exist, and A must inherit from B. (This is the check from the overrides package).

    • You don't have the pattern A.f declares that it overrides B.f, which then declares that it overrides C.f. A should say that it overrides from C.f since B might decide to stop overriding this method, and that should not result in downstream updates.

    • You don't have the pattern A.f declares that it overrides C.f, but B.f does not declare its override.

    • You don't have the pattern A.f declares that it overrides C.f, but B.f declares that it overrides from some D.f.

    It also has various features for marking and checking implementing an abstract method.

    0 讨论(0)
  • 2020-11-29 16:27

    Python ain't Java. There's of course no such thing really as compile-time checking.

    I think a comment in the docstring is plenty. This allows any user of your method to type help(obj.method) and see that the method is an override.

    You can also explicitly extend an interface with class Foo(Interface), which will allow users to type help(Interface.method) to get an idea about the functionality your method is intended to provide.

    0 讨论(0)
  • 2020-11-29 16:32

    Not only did the decorator I made check if the name of the overriding attribute in is any superclass of the class the attribute is in without having to specify a superclass, this decorator also check to ensure the overriding attribute must be the same type as the overridden attribute. Class Methods are treated like methods and Static Methods are treated like functions. This decorator works for callables, class methods, static methods, and properties.

    For source code see: https://github.com/fireuser909/override

    This decorator only works for classes that are instances of override.OverridesMeta but if your class is an instance of a custom metaclass use the create_custom_overrides_meta function to create a metaclass that is compatible with the override decorator. For tests, run the override.__init__ module.

    0 讨论(0)
  • 2020-11-29 16:33

    Here's an implementation that doesn't require specification of the interface_class name.

    import inspect
    import re
    
    def overrides(method):
        # actually can't do this because a method is really just a function while inside a class def'n  
        #assert(inspect.ismethod(method))
    
        stack = inspect.stack()
        base_classes = re.search(r'class.+\((.+)\)\s*\:', stack[2][4][0]).group(1)
    
        # handle multiple inheritance
        base_classes = [s.strip() for s in base_classes.split(',')]
        if not base_classes:
            raise ValueError('overrides decorator: unable to determine base class') 
    
        # stack[0]=overrides, stack[1]=inside class def'n, stack[2]=outside class def'n
        derived_class_locals = stack[2][0].f_locals
    
        # replace each class name in base_classes with the actual class type
        for i, base_class in enumerate(base_classes):
    
            if '.' not in base_class:
                base_classes[i] = derived_class_locals[base_class]
    
            else:
                components = base_class.split('.')
    
                # obj is either a module or a class
                obj = derived_class_locals[components[0]]
    
                for c in components[1:]:
                    assert(inspect.ismodule(obj) or inspect.isclass(obj))
                    obj = getattr(obj, c)
    
                base_classes[i] = obj
    
    
        assert( any( hasattr(cls, method.__name__) for cls in base_classes ) )
        return method
    
    0 讨论(0)
  • 2020-11-29 16:33

    Like others have said unlike Java there is not @Overide tag however above you can create your own using decorators however I would suggest using the getattrib() global method instead of using the internal dict so you get something like the following:

    def Override(superClass):
        def method(func)
            getattr(superClass,method.__name__)
        return method
    

    If you wanted to you could catch getattr() in your own try catch raise your own error but I think getattr method is better in this case.

    Also this catches all items bound to a class including class methods and vairables

    0 讨论(0)
  • 2020-11-29 16:34

    Hear is simplest and working under Jython with Java classes:

    class MyClass(SomeJavaClass):
         def __init__(self):
             setattr(self, "name_of_method_to_override", __method_override__)
    
         def __method_override__(self, some_args):
             some_thing_to_do()
    
    0 讨论(0)
提交回复
热议问题