ChatGPT解决这个技术问题 Extra ChatGPT

静态类型语言和动态类型语言有什么区别?

当我们说一种语言是动态类型与静态类型时是什么意思?

@EricLeschinski 我认为单元测试现在可以帮助解决这个问题,并且可以放心地对 JavaScript 等动态类型语言进行编码,从而确保它能够支持企业软件开发,你不觉得吗?
最好的情况是,这些单元测试会随着时间的推移而恶化,并被试图提高工作安全性的同事关闭,最坏的情况是,它们从一开始就没有被编写出来。这就像建议专业机械师在客户的汽车上使用胶带。是的,初级,在这个传输工作中使用胶带是个好主意……对你来说。
android.jlelse.eu/… 也可能有用

E
Elijah Lynn

静态类型语言

如果变量的类型在编译时已知,则语言是静态类型的。对于某些语言,这意味着您作为程序员必须指定每个变量的类型;其他语言(例如:Java、C、C++)提供某种形式的类型推断,即类型系统推断变量类型的能力(例如:OCaml、Haskell、Scala、Kotlin)。

这里的主要优点是编译器可以完成各种检查,因此在很早的阶段就发现了很多琐碎的错误。

示例:C、C++、Java、Rust、Go、Scala

动态类型语言

如果类型与运行时值相关联,而不是命名变量/字段/等,则该语言是动态类型的。这意味着您作为程序员可以写得更快一些,因为您不必每次都指定类型(除非使用带有类型推断的静态类型语言)。

示例:Perl、Ruby、Python、PHP、JavaScript、Erlang

大多数脚本语言都具有此功能,因为无论如何都没有编译器来进行静态类型检查,但是您可能会发现自己正在寻找由于解释器误解变量类型而导致的错误。幸运的是,脚本往往很小,所以 bug 没有太多可以隐藏的地方。

大多数动态类型语言确实允许您提供类型信息,但不需要它。当前正在开发的一种语言 Rascal 采用混合方法,允许在函数内进行动态类型化,但对函数签名强制执行静态类型化。


@NomeN 你能说出任何实现 HM 类型推断的动态类型语言吗?
“如果在运行时解释变量的类型,则语言是动态类型的”:否。如果类型与运行时值相关联,而不是命名变量/字段/等,则语言是动态类型的。
不正确,静态类型意味着“引用值明显(与编译时不同)受限于它可以表示的值的类型,以及语言实现,无论是编译器还是解释器,都尽可能地执行和使用这些约束。”引用自:c2.com/cgi/wiki?StaticTyping,据我所知,这是正确的。
Java、C、C++、Pascal 和许多其他广泛使用的“工业”语言的类型系统最明显的一点不是它们是静态类型的,而是它们是显式类型的。换句话说,它们需要大量类型声明。 (在非显式类型语言的世界中,这些声明是可选的,它们通常被称为“类型注释”。)这与静态类型无关。继续..
第一种静态类型语言是根据需要显式类型化的。然而,类型推断算法——在根本没有类型声明的情况下查看源代码并确定其变量类型的技术已经存在多年了。使用它的 ML 语言。 Haskell 对其进行了改进,现在已经有 15 年的历史了。甚至 C# 现在也采用了这个想法,这会引起很多人的注意,并且无疑会引起人们声称它是“弱类型化”的说法。继续...
M
Mateen Ulhaq

类型检查是验证和执行类型约束的过程。

静态类型的编程语言在编译时进行类型检查。示例:Java、C、C++。

动态类型编程语言在运行时进行类型检查。示例:Perl、Ruby、Python、PHP、JavaScript。


我认为这是最好的答案。特别是,接受的答案在很大程度上实际上是不正确的。
@JonHarrop 具体以什么方式?
@thomas:“这意味着您作为程序员可以写得更快一点,因为您不必每次都指定类型”。如果您有类型推断,则不必每次都使用静态类型指定类型。参见 SML、OCaml、F#、Haskell...
在静态类型的 prog 语言中,类型检查是在运行前完成的,但不完全是在编译时完成的。
让我更加困惑:从 Java 10 开始,引入了 var 关键字,让 Java 开发人员体验动态类型,但 Java 仍然是静态类型。
N
Neuron

下面是一个对比 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(不匹配的类型字符串和整数)


感谢您提供整洁的示例。所以我推断所有的脚本语言都是动态类型的,因为它们没有被编译?
是的。所有脚本语言都是动态类型的,因为它们无论如何都没有编译器来进行静态类型检查。这篇文章sitepoint.com/typing-versus-dynamic-typing已经说明了这一点。
Scala 可以用作脚本语言,它是静态类型的! #讨论@Shashi
@Shashi 编译并不意味着静态类型。例如,Haskell 可以用 runhaskell 解释。
此外,脚本语言并不意味着解释语言。 TypeScript 是静态类型的、编译/转译的,但是是脚本语言。
b
bobbyz

简单地说:在静态类型语言中,变量的类型是静态的,这意味着一旦将变量设置为类型,就无法更改它。这是因为类型与变量相关联,而不是它所引用的值。

例如在 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 变体,它们通常不是语言的核心,可用于要求。

在技术选择方面,双方都没有内在的优势。您是否想要更多的控制或灵活性只是一个偏好问题。只需为工作选择正确的工具,并确保在考虑转换之前检查可用的相反工具。


这很有意义。我认为它至少比这里的其他答案更好地解释了名称背后的原因。
Lucas,与此相反,该文档不断重复 Python 既是强类型又是动态类型。你在哪里看到的?可以报价吗?
我认为这个答案最能以最简单的方式传达这个概念。许多其他答案试图抽象地描述这个概念,但在某些细节上失败了。我宁愿在列表顶部看到这个答案。
大多数其他答案在我脑海中产生了更多问题。这一个清除了所有这些。这个答案真的应该在恕我直言
我认为“打字”这个词会妨碍清晰度。你的回答让我明白了:) 每次我过去听到这个,我都在考虑在键盘上打字,就像你声明或不声明变量的方式有关;我从来没有想过数据类型。所以“类型化”是指变量的数据类型改变状态的能力,无论变量的数据类型是静态的还是动态的。前任。动态(Str -> int -> 布尔值)
C
Community

http://en.wikipedia.org/wiki/Type_system

静态类型 当在编译时而不是运行时执行类型检查时,一种编程语言被称为使用静态类型。在静态类型中,类型与变量而不是值相关联。静态类型语言包括 Ada、C、C++、C#、JADE、Java、Fortran、Haskell、ML、Pascal、Perl(关于区分标量、数组、散列和子例程)和 Scala。静态类型是程序验证的一种有限形式(参见类型安全):因此,它允许在开发周期的早期发现许多类型错误。静态类型检查器仅评估可以在编译时确定的类型信息,但能够验证检查的条件是否适用于程序的所有可能执行,这消除了每次执行程序时重复类型检查的需要。通过省略运行时类型检查并启用其他优化,也可以使程序执行更高效(即更快或减少内存)。因为它们在编译期间评估类型信息,因此缺少仅在运行时可用的类型信息,所以静态类型检查器是保守的。他们会拒绝一些在运行时表现良好但不能静态确定为良好类型的程序。例如,即使一个表达式在运行时总是计算为真,包含代码 if then 42 else 的程序将被拒绝为类型错误,因为静态分析无法确定 else分支不会被占用。[1]静态类型检查器的保守行为在不经常评估为 false 时是有利的:静态类型检查器可以检测很少使用的代码路径中的类型错误。如果没有静态类型检查,即使是 100% 代码覆盖率的代码覆盖率测试也可能无法发现此类类型错误。代码覆盖测试可能无法检测到此类类型错误,因为必须考虑所有创建值的位置和使用某个值的所有位置的组合。最广泛使用的静态类型语言在形式上不是类型安全的。它们在编程语言规范中存在“漏洞”,使程序员能够编写代码绕过静态类型检查器执行的验证,从而解决更广泛的问题。例如,Java 和大多数 C 风格的语言都有类型双关语,而 Haskell 具有诸如 unsafePerformIO 之类的特性:此类操作在运行时可能是不安全的,因为它们可能在程序运行时由于不正确键入值而导致不希望的行为。动态类型 一种编程语言被称为是动态类型的,或者只是“动态的”,当它的大部分类型检查是在运行时而不是在编译时执行时。在动态类型中,类型与值而非变量相关联。动态类型语言包括 Groovy、JavaScript、Lisp、Lua、Objective-C、Perl(关于用户定义类型但不包括内置类型)、PHP、Prolog、Python、Ruby、Smalltalk 和 Tcl。与静态类型相比,动态类型可以更灵活(例如,通过允许程序基于运行时数据生成类型和功能),尽管以较少的先验保证为代价。这是因为动态类型语言接受并尝试执行一些可能被静态类型检查器判定为无效的程序。动态类型可能会导致运行时类型错误——也就是说,在运行时,一个值可能具有意外的类型,并且应用了对该类型无意义的操作。此操作可能在发生编程错误的地方很久之后发生 - 即错误类型的数据传递到它不应该有的地方的地方。这使得该错误难以定位。动态类型的语言系统,与其静态类型的表亲相比,对源代码进行更少的“编译时”检查(但会检查,例如,程序在语法上是否正确)。运行时检查可能更复杂,因为它们可以使用动态信息以及编译期间存在的任何信息。另一方面,运行时检查仅断言条件在程序的特定执行中成立,并且对于程序的每次执行都重复这些检查。动态类型语言的开发通常受到单元测试等编程实践的支持。测试是专业软件开发的关键实践,在动态类型语言中尤为重要。在实践中,为确保正确的程序运行而进行的测试可以检测到比静态类型检查更广泛的错误,但相反,无法全面搜索测试和静态类型检查都能够检测到的错误。测试可以合并到软件构建周期中,在这种情况下,可以将其视为“编译时”检查,因为程序用户不必手动运行此类测试。参考 Pierce, Benjamin (2002)。类型和编程语言。麻省理工学院出版社。国际标准书号 0-262-16209-1。


它似乎是多余的,因为它是指向维基百科的链接,而不是一些临时网站,但我下次会记住这一点。
不知何故,我仍然无法想到动态类型语言中的示例,其中类型在编译时不清楚,但必须在运行时弄清楚。你能给我一些吗?
@Novellizator 旧评论,但想象一下从远程服务器获取一些数据然后该数据用于从对象中获取属性的场景。例如:myObject[remoteDataName]。那么就无法知道它会选择哪个属性,甚至根本无法知道它是否是有效属性。
佚名

不幸的是,术语“动态类型”具有误导性。所有语言都是静态类型的,类型是表达式的属性(而不是某些人认为的值)。但是,有些语言只有一种类型。这些被称为单类型语言。这种语言的一个例子是无类型的 lambda 演算。

在无类型 lambda 演算中,所有项都是 lambda 项,唯一可以对项执行的操作是将其应用于另一个项。因此,所有操作总是导致无限递归或 lambda 项,但绝不会发出错误信号。

然而,如果我们用原始数字和算术运算来扩充无类型的 lambda 演算,那么我们可以执行无意义的操作,例如将两个 lambda 项加在一起:(λx.x) + (λy.y)。有人可能会争辩说,唯一明智的做法是在发生这种情况时发出错误信号,但为了能够做到这一点,每个值都必须用一个指示符标记,指示该术语是 lambda 术语还是数字。然后,加法运算符将检查两个参数是否确实被标记为数字,如果不是,则发出错误信号。请注意,这些标签是 not 类型,因为类型是程序的属性,而不是那些程序产生的值。

执行此操作的单类型语言称为动态类型。

JavaScript、Python 和 Ruby 等语言都是单一类型的。同样,JavaScript 中的 typeof 运算符和 Python 中的 type 函数具有误导性名称;它们返回与操作数关联的标签,而不是它们的类型。同样,C++ 中的 dynamic_cast 和 Java 中的 instanceof进行类型检查。


想象一下用一个让我们再问十个问题的回答来回答这个问题......
J
JBallin

编译与解释

“翻译源代码时”

源代码:原始代码(通常由人输入计算机)

翻译:将源代码转换成计算机可以读取的东西(即机器代码)

运行时间:程序执行命令的时间段(编译后,如果已编译)

编译语言:在运行时之前翻译的代码

解释语言:在执行期间动态翻译的代码

打字

“检查类型时”

5 + '3' 是 Go 和 Python 等 强类型 语言中的类型错误示例,因为它们不允许“类型强制” ->值在某些上下文中更改类型的能力,例如合并两种类型。 弱类型语言,例如 JavaScript,不会引发类型错误(导致 '53')。

静态:在运行时检查的类型

动态:在执行期间动态检查类型

“静态和编译”和“动态和解释”的定义非常相似......但请记住它是“检查类型时”与“翻译源代码时”。

无论该语言是编译还是解释,您都会得到相同类型的错误!您需要在概念上区分这些术语。

Python 示例

动态的,解释的

def silly(a):
    if a > 0:
        print 'Hi'
    else:
        print 5 + '3'

silly(2)

因为 Python 既是解释型的又是动态类型的,它只翻译和类型检查它正在执行的代码。 else 块永远不会执行,因此 5 + '3' 甚至都不会被查看!

如果它是静态类型的呢?

甚至在代码运行之前就会引发类型错误。即使它被解释,它仍然在运行时之前执行类型检查。

如果编译了呢?

else 块将在运行时之前被翻译/查看,但因为它是动态类型的,所以不会引发错误!动态类型语言在执行之前不会检查类型,并且该行永远不会执行。

去示例

静态,已编译

package main

import ("fmt"
)

func silly(a int) {
  if (a > 0) {
      fmt.Println("Hi")
  } else {
      fmt.Println("3" + 5)
  }
}

func main() {
  silly(2)
}

在运行(静态)之前检查类型并立即捕获类型错误!如果类型被解释,仍然会在运行时之前检查类型,结果相同。如果它是动态的,即使在编译期间会查看代码,它也不会抛出任何错误。

表现

如果编译语言是静态类型的(相对于动态类型),则编译语言在运行时将具有更好的性能;类型的知识允许机器代码优化。

静态类型语言本质上在运行时具有更好的性能,因为在执行时不需要动态检查类型(它在运行前检查)。

同样,编译语言在运行时速度更快,因为代码已经被翻译,而不是需要即时“解释”/翻译它。

请注意,编译语言和静态类型语言在分别运行翻译和类型检查之前都会有延迟。

更多差异

静态类型会及早发现错误,而不是在执行期间发现它们(对于长程序特别有用)。它更“严格”,因为它不允许在程序中的任何地方出现类型错误,并且通常会阻止变量更改类型,从而进一步防止意外错误。

num = 2
num = '3' // ERROR

动态类型更灵活,有些人对此表示赞赏。它通常允许变量更改类型,这可能导致意外错误。


“因为 Python 既是解释型的又是动态类型的,它只翻译和类型检查它正在执行的代码”——事实并非如此。 Python(至少是参考实现)在导入时编译所有代码(您也可以在导入模块之前/不导入它们)。编译器引入了各种优化(至少在 Python 的动态特性允许的范围内)。
P
Pang

静态类型语言:每个变量和表达式在编译时都是已知的。

int a; a 在运行时只能采用整数类型值)

示例:C、C++、Java

动态类型语言:变量可以在运行时接收不同的值,并且它们的类型是在运行时定义的。

var a; a 可以在运行时采用任何类型的值)

示例:Ruby、Python。


S
SuB

静态类型语言在编译时进行类型检查,并且类型不能更改。 (不要对类型转换注释变得可爱,会创建一个新变量/引用)。

动态类型语言在运行时进行类型检查,变量的类型可以在运行时更改。


u
user3627021

甜蜜而简单的定义,但符合需要:静态类型语言将类型绑定到其整个范围的变量(例如:SCALA) 动态类型语言将类型绑定到变量引用的实际值。


C
Chudong

在静态类型语言中,变量与编译时已知的类型相关联,并且该类型在整个程序执行过程中保持不变。等效地,只能为变量分配一个值,该值是已知/指定类型的实例。

在动态类型语言中,变量没有类型,在执行期间它的值可以是任何形状和形式的任何东西。


M
MagGGG

静态类型语言(编译器解析方法调用和编译引用):

通常性能更好

更快的编译错误反馈

更好的 IDE 支持

不适合使用未定义的数据格式

当模型未定义时,更难开始开发

更长的编译时间

在很多情况下需要编写更多代码

动态类型语言(在运行程序时做出的决定):

较低的性能

更快的发展

某些错误可能仅在运行时后期才被检测到

适用于未定义的数据格式(元编程)


h
haccks

静态类型:在编译时执行类型检查。

静态类型语言的实际含义:

必须指定变量的类型

变量只能引用特定类型的对象*

值的类型检查将在编译时执行,任何类型检查都将在那时报告

内存将在编译时分配以存储该特定类型的值

静态类型语言的示例是 C、C++、Java。

动态类型:在运行时执行类型检查。

动态类型语言的实际含义:

无需指定变量的类型

同一个变量可以引用不同类型的对象

Python、Ruby 都是动态类型语言的例子。

* 一些对象可以通过类型转换分配给不同类型的变量(在 C 和 C++ 等语言中非常常见的做法)


A
Akash sharma

静态类型语言(如 C++、Java)和动态类型语言(如 Python)仅在变量类型的执行方面有所不同。静态类型语言具有变量的静态数据类型,这里在编译期间检查数据类型,因此调试更简单......而动态类型语言不做同样的事情,检查执行程序的数据类型,因此调试有点困难。

此外,它们的差异非常小,可以与强类型和弱类型语言相关。强类型语言不允许您将一种类型用作另一种类型,例如。 C 和 C++ ...而弱类型语言允许 eg.python


T
Tom Zych

静态类型

在运行时检查类型,因此可以更早地发现错误。

示例 = C++

动态类型

在执行期间检查类型。

示例 = Python


这并没有真正添加其他答案尚未涵盖的任何内容,是吗?
是的,但大多数答案都不是很清楚,所以我想要一个易于理解的答案。
Y
Yash Zade

动态类型编程,允许程序在运行时更改变量的类型。

https://i.stack.imgur.com/x5XCH.png

静态类型,意味着如果您尝试将字符串存储在整数变量中,它不会接受它。

https://i.stack.imgur.com/hLMYa.png


请始终将代码作为文本嵌入到帖子中,而不是作为屏幕截图图像。另外,这个答案比以前的答案增加了什么?它实际上有一些问题: 1. 一种语言可能是静态类型的,但仍然允许像您的 Python 示例这样的东西:一个数字可以通过将其作为十进制表示形式读取来转换为字符串,更不用说在例如 C字符串变量只是一个指针,弱类型系统可能允许将其视为 int。 2. 在函数式编程中(狭义)你根本不改变变量,但语言仍然可能是动态的。
P
Pavan Kanajar

动态类型语言有助于快速原型化算法概念,而无需考虑需要使用哪些变量类型(这在静态类型语言中是必需的)。


P
Prakhyat

静态类型:Java 和 Scala 等语言是静态类型的。

变量在代码中使用之前必须定义和初始化。

例如。诠释 x; x = 10;

System.out.println(x);

动态类型:Perl 是一种动态类型语言。

变量在代码中使用之前不需要初始化。

y=10;在后面的代码中使用这个变量


好吧,这个答案并不完全正确。在这两种语言中,变量必须在使用之前进行初始化。但是,在动态类型语言中,您可以选择省略使用它的类型。
看起来您在滥用术语“变量”,您应该改用“类型”。
我认为 Perl 是静态类型的:它有 3 种类型,标量 ($)、数组 (@) 和散列 (%)。 Perl 中变量的类型在编译时是已知的,并且在变量的其余生命周期内保持不变。