我试图理解 Python 中的 OOP,但我遇到了“非 Python 思维方式”的问题。我想为我的类提供一个方法来验证参数的类型并在参数类型不正确时引发异常(例如 ValueError
)。我得到的最接近我的愿望的是:
class Tee(object):
def __init__(self):
self.x = 0
def copy(self, Q : '__main__.Tee'):
self.x = Q.x
def __str__(self):
return str(self.x)
a = Tee()
b = Tee()
print(type(a)) # <class '__main__.Tee'>
print(isinstance(a, Tee)) # True
b.x = 255
a.copy(b)
print(a) # 255
a.copy('abc') # Traceback (most recent call last): [...]
# AttributeError: 'str' object has no attribute 'x'
因此,即使我试图确保我的 copy
方法中的参数 Q
的类型属于同一类,解释器也只是通过它并引发当它试图从字符串中获取 x
成员时出现 AttributeError
。
我知道我可以做这样的事情:
[...]
def copy(self, Q):
if isinstance(Q, Tee):
self.x = Q.x
else:
raise ValueError("Trying to copy from a non-Tee object")
[...]
a = Tee()
a.copy('abc') # Traceback (most recent call last): [...]
# ValueError: Trying to copy from a non-Tee object
但是围绕类到处实现听起来工作量很大,即使我做了一个专门的函数、方法或装饰器。所以,我的问题是:对此是否有更“pythonic”的方法?
顺便说一下,我使用的是 Python 3.6.5。
最佳答案
在运行时不强制执行类型注释。时期。它们目前仅供 IDE 或静态分析器使用,如 mypy ,或通过您自己编写的任何反省这些注释的代码。但由于 Python 主要基于 duck typing ,运行时不会也不会实际强制执行类型。
如果您在开发期间使用静态类型检查器来捕获此类错误,这通常就足够了。如果你想进行实际的运行时检查,你可以使用 assertions :
assert isinstance(Q, Tee), f'Expected instance of Tee, got {type(Q)}'
但它们也主要用于调试,因为可以关闭断言。要拥有强类型断言,您需要明确:
if not isinstance(Q, Tee):
raise TypeError(f'Expected instance of Tee, got {type(Q)}')
但同样,这可以防止鸭子打字,这并不总是可取的。
顺便说一句,你的类型注释应该只是 def copy(self, Q: 'Tee')
,不要包括 '__main__'
;另见 https://docs.python.org/3/whatsnew/3.7.html#whatsnew37-pep563 .
关于Python OOP,方法/类中参数的类型验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52741293/