Equivalent NotImplementedError for fields in Python

In Python 2.x, when you want to mark a method as abstract, you can define it like this:

class Base: def foo(self): raise NotImplementedError("Subclasses should implement this!") 

Then, if you forget to override it, you will get a wonderful reminder. Is there an equivalent way to mark a field as abstract? Or you indicate that it is in the docstring class, what can you do?

At first I thought that I could set the NotImplemented field, but when I looked at what it really was (rich comparisons), it seemed offensive.
+46
python abstract-class
Jul 19 '09 at 23:48
source share
5 answers

Yes, you can. Use the @property decorator. For example, if you have a field called "example", you cannot do something like this:

 class Base(object): @property def example(self): raise NotImplementedError("Subclasses should implement this!") 

By running the following command, run NotImplementedError way you want.

 b = Base() print b.example 
+48
Jul 20 '09 at 0:08
source share

Alternative answer:

 @property def NotImplementedField(self): raise NotImplementedError class a(object): x = NotImplementedField class b(a): # x = 5 pass b().x a().x 

This is similar to Evan's, but concise and cheap - you get only one instance of NotImplementedField.

+33
Jul 20 '09 at 0:15
source share

The best way to do this is to use Abstract base classes :

 import abc class Foo(abc.ABC): @property @abc.abstractmethod def demo_attribute(self): raise NotImplementedError @abc.abstractmethod def demo_method(self): raise NotImplementedError class BadBar(Foo): pass class GoodBar(Foo): demo_attribute = 'yes' def demo_method(self): return self.demo_attribute bad_bar = BadBar() # TypeError: Can't instantiate abstract class BadBar \ # with abstract methods demo_attribute, demo_method good_bar = GoodBar() # OK 

Note that you should still have a raise NotImplementedError instead of pass , because there is nothing stopping the inheriting class from calling super().demo_method() , and if the abstract demo_method is pass , this will fail silently.

+4
Jan 09 '17 at 12:09 on
source share
 def require_abstract_fields(obj, cls): abstract_fields = getattr(cls, "abstract_fields", None) if abstract_fields is None: return for field in abstract_fields: if not hasattr(obj, field): raise RuntimeError, "object %s failed to define %s" % (obj, field) class a(object): abstract_fields = ("x", ) def __init__(self): require_abstract_fields(self, a) class b(a): abstract_fields = ("y", ) x = 5 def __init__(self): require_abstract_fields(self, b) super(b, self).__init__() b() a() 

Pay attention to the class type passing in require_abstract_fields , so if it is used by several inherited classes, they do not all check the fields of the derived class itself. You may be able to automate this with a metaclass, but I did not understand this. Field definition in None accepted.

+2
Jul 20 '09 at 0:08
source share

And here is my solution:

 def not_implemented_method(func): from functools import wraps from inspect import getargspec, formatargspec @wraps(func) def wrapper(self, *args, **kwargs): c = self.__class__.__name__ m = func.__name__ a = formatargspec(*getargspec(func)) raise NotImplementedError('\'%s\' object does not implement the method \'%s%s\'' % (c, m, a)) return wrapper def not_implemented_property(func): from functools import wraps from inspect import getargspec, formatargspec @wraps(func) def wrapper(self, *args, **kwargs): c = self.__class__.__name__ m = func.__name__ raise NotImplementedError('\'%s\' object does not implement the property \'%s\'' % (c, m)) return property(wrapper, wrapper, wrapper) 

It can be used as

 class AbstractBase(object): @not_implemented_method def test(self): pass @not_implemented_property def value(self): pass class Implementation(AbstractBase): value = None def __init__(self): self.value = 42 def test(self): return True 
0
Dec 30 '15 at 18:39
source share



All Articles