我正在编写一个库,其中我有一个应该被用户子类化的类。我已经为该类添加了类型提示,希望它们也会影响子类,以便用户不必自己添加类型提示。
但是,它不起作用:
# Class from the library
class A:
def a(self, d: dict):
raise NotImplementedError()
# User-defined subclass
class B(A):
def a(self, d):
...
d
中的变量B.d
的推断类型为Any
,但我希望它为dict
。有没有办法告诉pycharm它没有写另一个类型提示dict
?这种情况有没有常见做法?
答案 0 :(得分:1)
这不是C ++,其中超类定义了签名,子类实现了它。在python中,一切都是明确的...... A.a
和B.a
具有不同的签名并且具有完全不同的参数列表是不好的形式,但实际上并不允许它:
In [7]: class A(object):
...: def a(self, x, y, z):
...: print (x, y, z)
...:
In [8]: class B(A):
...: def a(self, m, n, o):
...: print (m + n + o)
...:
In [9]: b = B()
In [10]: b.a(1,2,3)
6
In [11]: a = A()
In [12]: a.a(1,2,3)
1 2 3
现在,在现实世界中,如果你真的用你期望人们使用的类来做这样的事情,那么他们会正确地尖叫并将你踢出项目...可预测的API是继承的核心部分。
这是可能的,因为与C ++不同,函数查找是通过多态的签名完成的(例如,您可以编写int f(int a);
和int f(float f);
,它们是两个具有相同名称的独立函数,编译器知道哪一个调用调用者使用的参数类型,Python函数查找仅在名称上。
但即使假设签名与超类相同,技术上错误,因为PyCharm将很难证明你确实意味着同样的事情,在实践中,大多数人都会使用它,所以选择这样做会很有用。
最后一件事......今天,函数注释只是' fyi',但是有些项目试图将它们用于实际的东西......装饰者会在调用之前检查参数类型例如,功能。即使PyCharm可以推断注释,代码本身在运行时也不会胜任,如果你想要它们用于任何功能,你可能必须继续明确地包含它们。