所以,我正在编写一个连接外部帐户提供程序(Twitter,Facebook等)的模块,我有一个单独使用的超类,但包含需要由子类调用以保持身份验证的泛型方法令牌,获取身份验证令牌和取消授权提供商。我的问题是,有没有办法让它不可安装,或者我应该遵循同意的成年人规则,只是让任何使用它的人在他们认为合适时犯错误?除了文档字符串之外,还有一种很好的方法可以表明某人不应该单独使用这个超类吗?
答案 0 :(得分:7)
class NoInstantiation: # "class NoInstantiation(object):" in Python 2.2+ or whatever
def __new__(cls):
"This class is not meant to be instantiated, so __new__ returns None."
return None
如果他们愿意,这不会阻止人们覆盖该功能,但它应该是一种防止意外实例化的相当不错的方法。如果有人不小心打电话给他们,他们就不能说你没有警告他们。
编辑:如果你真的想要变得更好,你也可以在__new__()
中向stderr发出警告,甚至抛出异常。
编辑2:如果你去了异常路由,你可能想要在超类的__init__()
方法中引发异常,因为用户可能会在子类中覆盖__init__()
。< / p>
编辑3:还可以选择将__new__
或__init__
设置为None
,但产生的错误信息不会很丰富。
答案 1 :(得分:7)
在JAB的答案基础上,像这样写__new__()
可能更方便:
class NoInstantiation(object):
def __new__(cls, *args, **kwargs):
if cls is NoInstantiation:
raise RuntimeError(
"NoInstantiation isn't meant to be instantiated")
else:
return super(NoInstantiation, cls).__new__(cls, *args, **kwargs)
这样,您不需要在派生类中覆盖__new__()
。
编辑:我发布此答案是对JAB答案的改进,但我建议不要实际使用上述代码。它在某种程度上故意使你的班级瘫痪。通常的Python方法是清楚地记录该类并不意味着实现。但也许有人找到了一种方法,无论如何这都是有用的 - 你永远不知道人们将以何种方式使用你的图书馆。
答案 2 :(得分:7)
我正在考虑Sven Marnach's edit:我认为你应该遵循“同意大人”的规则,并在文档字符串中提到该类不是要实例化的。
你问题中的关键词是“我有一个超级,它本身没用”。“实例化时不会调用cthulhu;它不会在你的程序中的其他地方造成某种灾难性的,难以调试的失败;这只是浪费时间。我认为,这不值得为这个课程造成严重损失。
答案 3 :(得分:4)
您可以使用abc
模块中的abstractmethod
decorator来标记所有派生类重写为抽象的方法之一。
In [1]: import abc
In [2]: class C:
...: __metaclass__ = abc.ABCMeta
...:
...: @abc.abstractmethod
...: def my_abstract_method(self, *args) :
...: pass
...:
...:
In [3]: c = C()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/afoglia/<ipython console> in <module>()
TypeError: Can't instantiate abstract class C with abstract methods my_abstract_method
我确实质疑班级组织。如果这个“超类”只是需要由子类调用的函数,为什么它不仅仅是一个不同机制可以使用的模块?如果它是派生类完全实现的接口的定义(可能作为模板方法模式),那么抽象方法表示需要由派生类给出实现的函数。在这种情况下,我甚至不打算使基础不可构造,并且让人们通过工厂方法得到必要的派生,或让用户在调用失败的函数时弄清楚它。 (尽管在文档字符串中发表评论。)