我来自Java世界,我想知道Python中动态类型的优点是什么,除了在编译代码时遗漏错误?
你喜欢Python的打字吗?你有一个例子,它在一个大项目中有所帮助吗?是不是有点容易出错?
答案 0 :(得分:18)
在一般情况下,静态类型检查是不可判定的。这意味着有些程序是静态类型安全的,但类型检查程序不能证明它们是静态类型安全的,因此类型检查器必须拒绝这些程序。
换句话说:类型检查程序不允许您编写类型安全程序。或者,更简洁:静态类型阻止您编写某些程序。
这一般适用于所有静态类型,而不仅仅适用于Java。
至于Java:它有一个相当糟糕的类型系统。它的类型系统表达能力甚至不足以表达 very 简单属性。例如:在static void java.util.Arrays.sort(Object[] a)
的类型中,它实际上说结果必须是,你知道,排序了吗?或者数组元素必须部分排序?
Java的另一个问题是它的类型系统有很大的洞,你可以驾驶卡车通过:
String[] a = new String[1];
Object[] b = a;
b[0] = 1; // ArrayStoreException
这种特殊情况下的问题是协变数组。数组根本不可能是协变的和类型安全的。
Java结合了静态类型的所有麻烦,没有任何优势。所以,你也可以摆脱麻烦。
然而,请注意,这不是普遍的。还有其他语言有更好的类型系统,这些系统的权衡不太清楚。
例如,这是Python中有史以来最愚蠢的语言基准(Fibonacci):
def fib(n):
if n < 2: return n
return fib(n-2) + fib(n-1)
和Java:
int fib(int n) {
if (n < 2) return n;
return fib(n-2) + fib(n-1);
}
请注意,那里存在更多混乱,这与静态类型有关。为了使比较更公平,让我们想象一下使用Python语法和Java语义的语言:
def fib(n: int) -> int:
if n < 2: return n
return fib(n-2) + fib(n-1)
[有趣的注意:在Python 3.x中添加了可选的静态类型注释, 实际上也是有效的Python代码,尽管它显然仍然不是静态类型安全的,因为注释只是:注释。它们实际上从未在任何地方进行过检查。]
那里有一些明确的混乱。但是,在Haskell中它看起来像这样:
fib n
| n < 2 = n
| otherwise = fib (n-2) + fib (n-1)
与Python版本不同,这个 完全是静态类型安全的,但没有与类型相关的混乱。
在这种特殊情况下,静态和动态类型的好处之间的问题不太清楚。
顺便说一句,更惯用的Haskell版本可能看起来像这样:
fib 0 = 0
fib 1 = 1
fib n = fib (n-2) + fib (n-1)
或者这个:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
实际上,Java和Python之间更重要的区别并不在于Java是静态类型的,而是动态类型化的Python,而是Java不是一种优秀的编程语言,而Python 是。所以,Java总是会失败,不是因为它是静态类型的,而是因为它是垃圾。比较BASIC和Haskell,Haskell明显胜出,但同样,不是因为它是静态类型的,而是因为BASIC是垃圾。
更有趣的比较是Java vs. BASIC或Python vs. Haskell。
答案 1 :(得分:12)
我怀疑绝大多数非平凡的Java程序都有动态类型。
每次在Java中,您都要从Object转换为显式类型,而您正在进行动态类型检查 - 这包括在1.5中引入泛型之前对集合类的每次使用。实际上,Java泛型仍然可以将某些类型检查推迟到运行时。
每次使用Java反射时,都会进行动态类型检查。这包括从文本文件中的类或方法名称到真实类或方法的映射 - 例如每次使用Spring XML配置文件时。
这是否会使Java程序变得脆弱且容易出错? Java程序员是否花费大量时间来跟踪和修复错误动态类型的问题?可能不是 - 也不是Python程序员。
动态类型的一些优点:
答案 2 :(得分:5)
你喜欢Python吗?
它是Python的部分。喜欢 in Python是愚蠢的。
你有一个例子,它在一个大项目中有所帮助吗?
是。每一天我都高兴我可以做出改变 - 因为Duck打字 - 他们合理地本地化,通过所有单元测试,通过所有集成测试,没有在其他地方被打乱。 / p>
如果这是Java,那么更改将需要无休止的重构以从类中提取接口,以便我可以引入在Java的静态类型检查下仍然允许的变体。
是不是有点容易出错?
不仅仅是静态输入。简单的单元测试确认对象符合预期的特征。
用Java编写一个类很容易(a)通过编译时检查,(b)在运行时崩溃。演员阵容是一个很好的方法。未能满足 intent 类是常见的事情 - 类可以编译但仍然不能工作。
答案 3 :(得分:2)
许多模式(例如来自GoF)是不必要的,或者可以用具有功能性风格的动态类型语言中的较少努力来实现。实际上,很多模式都是“内置”到python中的,所以如果你编写短代码和“pythonic”代码,你将获得免费的所有好处。您不需要Iterator,Observer,Strategy,Factory Method,Abstract Factory以及Java或C ++中常见的一堆其他模式。
这意味着更少的代码可以编写,而且(更重要的是)更少的代码可供阅读,理解和支持。我认为这是像python这样的语言的主要好处。在我看来,这大大超过了静态类型的缺失。类型相关的错误通常不在python代码中,并且很容易用简单的功能测试来捕获(这样的测试在python中比在java中更容易编写)。
答案 4 :(得分:0)
这是你的想法。您可以将红色视为“红色”(常量)为“255,0,0”(元组)或“#FF0000”(字符串):三种不同的格式,需要三种不同的类型,或复杂的查找和Java中的转换方法。
它使代码更简单。
答案 5 :(得分:0)
例如,您可以编写函数 您可以将整数传递给 以及字符串或列表或 字典或其他任何东西,它 将能够透明地处理 所有这些都以适当的方式(或 如果它无法处理则抛出异常 类型)。你可以做那样的事情 在其他语言中,但通常 你必须诉诸(ab)使用东西 像指针,引用或 类型转换,打开漏洞 编程错误,它只是 简单丑陋。
答案 6 :(得分:0)
当你来自Java世界时,显而易见的答案是,不要强迫你写下你被迫编写的所有东西,只是为了让Java的类型系统感到高兴。
当然,还有其他静态类型检查的语言不会强迫你写出Java强迫你写的所有内容。
即使是C#也会对本地方法变量进行类型推断!
还有其他静态类型检查语言提供比Java提供的更多编译时错误检查。
(不太明显的答案 - 在Python中动态类型的优点是什么? - 可能需要更多地了解Python才能理解。)