Python abstract classes - how to discourage instantiation?

后端 未结 5 1457
面向向阳花
面向向阳花 2021-02-07 04:58

I come from a C# background where the language has some built in \"protect the developer\" features. I understand that Python takes the \"we\'re all adults here\" approach and

相关标签:
5条回答
  • 2021-02-07 05:17

    Create your 'abstract' class and raise NotImplementedError() in the abstract methods.

    It won't stop people using the class and, in true duck-typing fashion, it will let you know if you neglect to implement the abstract method.

    0 讨论(0)
  • 2021-02-07 05:23

    Based on your last sentence, I would answer answer "just document it". Anyone who uses a class in a way that the documentation says not to must accept responsibility for any strange behavior.

    There is an abstract base class mechanism in Python, but I don't see any reason to use it if your only goal is to discourage instantiation.

    0 讨论(0)
  • 2021-02-07 05:34

    To enforce things is possible, but rather unpythonic. When I came to Python after many years of C++ programming I also tried to do the same, I suppose, most of people try doing so if they have an experience in more classical languages. Metaclasses would do the job, but anyway Python checks very few things at compilation time. Your check will still be performed at runtime. So, is the inability to create a certain class really that useful if discovered only at runtime? In C++ (and in C# as well) you can not even compile you code creating an abstract class, and that is the whole point -- to discover the problem as early as possible. If you have abstract methods, raising a NotImplementedError exception seems to be quite enough. NB: raising, not returning an error code! In Python errors usually should not be silent unless thay are silented explicitly. Documenting. Naming a class in a way that says it's abstract. That's all.

    Quality of Python code is ensured mostly with methods that are quite different from those used in languages with advanced compile-time type checking. Personally I consider that the most serious difference between dynamically typed lngauges and the others. Unit tests, coverage analysis etc. As a result, the design of code is quite different: everything is done not to enforce things, but to make testing them as easy as possible.

    0 讨论(0)
  • 2021-02-07 05:40

    I just name my abstract classes with the prefix 'Abstract'. E.g. AbstractDevice, AbstractPacket, etc.

    It's about as easy and to the point as it comes. If others choose to go ahead and instantiate and/or use a class that starts with the word 'Abstract', then they either know what they're doing or there was no hope for them anyway.

    Naming it thus, also serves as a reminder to myself not to go nuts with deep abstraction hierarchies, because putting 'Abstract' on the front of a whole lot of classes feels stupid too.

    0 讨论(0)
  • 2021-02-07 05:41

    If you're using Python 2.6 or higher, you can use the Abstract Base Class module from the standard library if you want to enforce abstractness. Here's an example:

    from abc import ABCMeta, abstractmethod
    
    class SomeAbstractClass(object):
        __metaclass__ = ABCMeta
    
        @abstractmethod
        def this_method_must_be_overridden(self):
            return "But it can have an implementation (callable via super)."
    
    class ConcreteSubclass(SomeAbstractClass):
        def this_method_must_be_overridden(self):
            s = super(ConcreteSubclass, self).this_method_must_be_overridden()
            return s.replace("can", "does").replace(" (callable via super)", "")
    

    Output:

    >>> a = SomeAbstractClass()
    Traceback (most recent call last):
      File "<pyshell#13>", line 1, in <module>
        a = SomeAbstractClass()
    TypeError: Can't instantiate abstract class SomeAbstractClass with abstract
    methods this_method_must_be_overridden
    >>> c = ConcreteSubclass()
    >>> c.this_method_must_be_overridden()
    'But it does have an implementation.'
    
    0 讨论(0)
提交回复
热议问题