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

前端 未结 10 1880
长情又很酷
长情又很酷 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:42

    Improvising on @mkorpela great answer, here is a version with

    more precise checks, naming, and raised Error objects

    def overrides(interface_class):
        """
        Function override annotation.
        Corollary to @abc.abstractmethod where the override is not of an
        abstractmethod.
        Modified from answer https://stackoverflow.com/a/8313042/471376
        """
        def confirm_override(method):
            if method.__name__ not in dir(interface_class):
                raise NotImplementedError('function "%s" is an @override but that'
                                          ' function is not implemented in base'
                                          ' class %s'
                                          % (method.__name__,
                                             interface_class)
                                          )
    
            def func():
                pass
    
            attr = getattr(interface_class, method.__name__)
            if type(attr) is not type(func):
                raise NotImplementedError('function "%s" is an @override'
                                          ' but that is implemented as type %s'
                                          ' in base class %s, expected implemented'
                                          ' type %s'
                                          % (method.__name__,
                                             type(attr),
                                             interface_class,
                                             type(func))
                                          )
            return method
        return confirm_override
    


    Here is what it looks like in practice:

    NotImplementedError "not implemented in base class"

    class A(object):
        # ERROR: `a` is not a implemented!
        pass
    
    class B(A):
        @overrides(A)
        def a(self):
            pass
    

    results in more descriptive NotImplementedError error

    function "a" is an @override but that function is not implemented in base class 
    

    full stack

    Traceback (most recent call last):
      …
      File "C:/Users/user1/project.py", line 135, in 
        class B(A):
      File "C:/Users/user1/project.py", line 136, in B
        @overrides(A)
      File "C:/Users/user1/project.py", line 110, in confirm_override
        interface_class)
    NotImplementedError: function "a" is an @override but that function is not implemented in base class 
    


    NotImplementedError "expected implemented type"

    class A(object):
        # ERROR: `a` is not a function!
        a = ''
    
    class B(A):
        @overrides(A)
        def a(self):
            pass
    

    results in more descriptive NotImplementedError error

    function "a" is an @override but that is implemented as type  in base class , expected implemented type 
    

    full stack

    Traceback (most recent call last):
      …
      File "C:/Users/user1/project.py", line 135, in 
        class B(A):
      File "C:/Users/user1/project.py", line 136, in B
        @overrides(A)
      File "C:/Users/user1/project.py", line 125, in confirm_override
        type(func))
    NotImplementedError: function "a" is an @override but that is implemented as type  in base class , expected implemented type 
    




    The great thing about @mkorpela answer is the check happens during some initialization phase. The check does not need to be "run". Referring to the prior examples, class B is never initialized (B()) yet the NotImplementedError will still raise. This means overrides errors are caught sooner.

提交回复
热议问题