代码之家  ›  专栏  ›  技术社区  ›  Kiv

Python中字段的NotImplementedError等价物

  •  57
  • Kiv  · 技术社区  · 17 年前

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

    起初我以为我可以将该字段设置为NotImplemented,但当我查看它的实际用途(丰富的比较)时,它似乎是滥用的。

    8 回复  |  直到 17 年前
        1
  •  45
  •   Evan Fosmark    17 年前

    是的,你可以。使用 @property 装饰师。例如,如果你有一个名为“example”的字段,那么你不能这样做吗:

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

    运行以下命令会产生 NotImplementedError 正如你所愿。

    b = Base()
    print b.example
    
        2
  •  30
  •   Glenn Maynard    17 年前

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

    这类似于Evan的,但简洁且廉价——你只会得到一个NotImplementedField的实例。

        3
  •  2
  •   Glenn Maynard    17 年前

    更好的方法是使用 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
    

    请注意,您仍然应该 raise NotImplementedError 而不是类似的东西 pass super().demo_method() demo_method 只是 通过 ,这将悄无声息地失败。

        4
  •  2
  •   ostrokach    9 年前
    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()
    

    注意将类类型传递到 require_abstract_fields

        5
  •  0
  •   fwyzard    10 年前

    这个问题似乎对实例属性和类属性都开放,我将只关注第一个主题。

    因此,例如属性,一个替代答案 Evan's 是使用定义必填字段 pyfields :

    from pyfields import field
    
    class Base(object):
        example = field(doc="This should contain an example.")
    
    b = Base()
    b.example
    

    pyfields.core.MandatoryFieldInitError: 
       Mandatory field 'example' has not been initialized yet 
       on instance <__main__.Base object at 0x000002C1000C0C18>.
    

    当然,它不能通过讨论子类来编辑错误消息。但在某种程度上,不谈论子类更现实——事实上,在python中,属性 基类的一部分,而不仅仅是子类。

    注:我是《 皮菲尔德 。参见 documentation 了解详情。

        6
  •  0
  •   moppag    8 年前

    class Base:
        requires = ('foo', 'bar')
    
        def __init_subclass__(cls, **kwargs):
            for requirement in cls.requires:
                if not hasattr(cls, requirement):
                    raise NotImplementedError(
                            f'"{cls.__name__}" must have "{requirement}".')
            super().__init_subclass__(**kwargs)