【问题标题】:Pythonic way vs common sense. Type checkingPythonic 方式与常识。类型检查
【发布时间】:2018-03-11 20:48:32
【问题描述】:

我见过很多问题,比如以下一个:What's the canonical way to check for type in Python?

而且总是有人这样回答:“检查类型的 Pythonic 方法不是检查它们。这里还有一段关于鸭子类型的文章。”

首先,我确实了解鸭式打字的优点,而且我确实经常使用它。但是不检查类型真的值得吗?

假设我有以下代码:

class DuckA:
    def quack():
        print("QuackA")

class DuckB:
    def quack():
        print("QuackB")

def duck_creator():
    return DuckA()

def duck_client(duck):
    duck.quack()

if __name__ is "__main__":
    duck_client(DuckA())           #ok
    duck_client(DuckB())           #ok
    duck_client(duck_creator())    #ok

    #totally fine untill you actually call it,
    #which might be quite tricky to check in 
    #relatively big project
    duck_client(duck_creator)     

    #one more typo, which is pretty hard to spot
    #from first sight
    duck_client(DuckB)

是的,我确实意识到我们都是工程师,因此,我们支持编写足够的结构,但是各种拼写错误怎么办?

我是 python 的初学者,我来自 c/c++ 人群。基本上,所有这些涉及鸭子打字的答案对我来说听起来有点像“如果你不想在调试器上花费数小时,你只需要编写没有错误的代码”。

那么,python 大师们,是否有任何有效的/pythonic/公认的技术来克服这样的事情?

我见过各种各样的类型检查器,它们已经足够好了,尽管我不喜欢将项目绑定到其中一个 ide 的想法。

从我的角度来看,函数开头的断言确实看起来很有希望。

还有其他想法吗?

【问题讨论】:

  • 如果您非常担心拼写错误,请养成在 IDE 中使用 python3.6 的打字检查的习惯。
  • 如果您有拼写错误,您的代码将因 NameError 或 AttributeError 或其他一些容易诊断的故障而失败。一个简单的测试就足以暴露这一点。
  • python 3.6 并不总是可用的问题。现在,假设几个团队成员更喜欢使用 vim 或类似的东西。是的,正如@DanielRoseman 指出的那样,它会失败。问题是它可能在编写代码几个月后失败(假设有人进行了导致回归的更改)。当然,这可能会被自动测试覆盖,但在实际项目中,您可能无法提供 100% 的覆盖率。
  • 这里的论点部分确实是一个主观问题,但是……根据我的经验,您计划为其编写断言的类型检查不会捕捉到您遇到的错误实际上要做。你得到的只是相对弱的类型系统(如 C++ 或 Java,而不是 Rust 或 Haskell)中的静态类型给你的那种错误的安全感:你的代码可以编译,但它仍然充满了引用/线程/等.错误,这就是为什么 Java 中的空指针异常比 Python 中的 None 上的 AttributeErrors 更多。
  • 无论如何,如果 Python 3.6 不可用,为什么不能使用向后兼容的 MyPy 语法,将类型注释作为 cmets 或在 typesheds 中?当然,它有点难看,但是“我想使用 Python 2.7 或 3.4,它使 Python 3.6 的功能有点难看”是使用 Python 3.6 的论据,而不是讨厌这些功能的论据。

标签: python types duck-typing


【解决方案1】:

我认为您正在寻找的是Mypy,它是 Python 2.7+/3.4+ 的静态类型检查器。它是 Python 3.6 的注释系统围绕它设计的类型检查器,但他们一直小心翼翼地确保它可以与旧版本的 Python 一起使用。 (事实上​​,类型提示的部分动机首先是 Guido 希望使用 Mypy 来帮助指导将大型代码库从 2.7 升级到 3.5。)

当然,您不能在旧版本的 Python 中使用 3.6 语法。在 3.5 中,参数可以被注解,但不能被本地化。在 3.4 中,注释是有限的。在 2.7 中,注释根本不存在。

如果您阅读文档,有几种方法可以解决这个问题,但基本思想是您将所有注释放入“公共”代码中的 cmets,同时编写充满外线的“typeshed”文件“内部”代码的注释。

好消息是,由于 Mypy 得到了核心语言的支持,其他静态类型检查器以及相关工具(如 IDE 索引器或更深层次的静态分析器)正在适应以同样的方式做事,所以无论您使用什么2.7 或 3.4 代码可能会与您最喜欢的 IDE 或 vim 插件或分析器或其他任何东西一起使用(如果不是今天,那么很快)。

【讨论】:

    猜你喜欢
    • 2014-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    相关资源
    最近更新 更多