当我们说一种语言是动态类型和静态类型时,这意味着什么?
当前回答
下面是一个对比Python(动态类型)和Go(静态类型)如何处理类型错误的例子:
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
Python在运行时执行类型检查,因此:
silly(2)
运行完全正常,并产生预期的输出Hi。只有当有问题的行被击中时才会引发错误:
silly(-1)
生产
不支持'int'和'str'的操作数类型
因为相关的行已经被执行了。
另一方面,Go在编译时进行类型检查:
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
上述文件将无法编译,并出现以下错误:
无效的操作:"3" + 5(不匹配的类型字符串和int)
其他回答
简单地说:在静态类型语言中,变量的类型是静态的,这意味着一旦将变量设置为类型,就不能更改它。这是因为类型是与变量而不是它所引用的值相关联的。
例如,在Java中:
String str = "Hello"; // variable str statically typed as string
str = 5; // would throw an error since str is
// supposed to be a string only
另一方面:在动态类型语言中,变量的类型是动态的,这意味着在你将变量设置为类型后,你可以更改它。这是因为输入与它假设的值相关,而不是变量本身。
例如,在Python中:
some_str = "Hello" # variable some_str is linked to a string value
some_str = 5 # now it is linked to an integer value; perfectly OK
因此,最好将动态类型语言中的变量视为指向类型值的泛型指针。
总而言之,类型描述(或应该描述)语言中的变量,而不是语言本身。恕我直言,它本可以更好地用作带有静态类型变量的语言,而不是带有动态类型变量的语言。
静态类型语言通常是编译语言,因此,编译器检查类型(这很有意义,对吧?因为类型不允许稍后在运行时更改)。
动态类型语言通常是解释型的,因此类型检查(如果有的话)发生在使用它们时的运行时。这当然会带来一些性能损失,也是动态语言(例如python、ruby、php)伸缩性不如类型化语言(java、c#等)的原因之一。从另一个角度来看,静态类型语言的启动成本更高:通常会让你编写更多、更难的代码。但这在以后是有回报的。
好在双方都在借鉴对方的特点。类型语言融合了更多的动态特性,例如c#中的泛型和动态库,而动态语言则包含了更多的类型检查,例如python中的类型注释,或PHP的HACK变体,这些通常不是语言的核心,可按需使用。
在技术选择方面,任何一方都没有内在的优势。这只是一个偏好的问题,你想要更多的控制或灵活性。只要为工作选择合适的工具,并确保在考虑转换之前检查相反的可用工具。
静态类型语言(编译器解析方法调用和编译引用):
通常表现更好 更快的编译错误反馈 更好的IDE支持 不适合使用未定义的数据格式 当没有定义模型时,很难开始开发 更长的编译时间 在很多情况下需要编写更多的代码
动态类型语言(在运行程序中做出的决定):
较低的性能 更快的发展 有些bug可能只在稍后的运行时才会被检测到 适用于未定义的数据格式(元编程)
允许程序在运行时更改变量类型的动态类型编程。
动态类型语言:Perl、Ruby、Python、PHP、JavaScript、Erlang
静态类型,意味着如果你试图在一个整数变量中存储一个字符串,它将不会接受它。
静态类型语言:C、c++、Java、Rust、Go、Scala、Dart
静态类型语言(如c++、Java)和动态类型语言(如Python)的区别仅仅在于变量类型的执行。 静态类型语言对变量有静态数据类型,这里在编译期间检查数据类型,因此调试要简单得多……而动态类型语言则不这样做,它会检查执行程序的数据类型,因此调试有点困难。
此外,它们有一个非常小的区别,可以与强类型和弱类型语言相关联。强类型语言不允许将一种类型用作另一种类型。C和c++…而弱类型语言允许例如python
静态类型语言在编译时进行类型检查,并且类型不能更改。(不要用类型转换注释,会创建一个新的变量/引用)。
动态类型语言在运行时进行类型检查,变量的类型可以在运行时更改。