В чем разница между статически типизированными и динамически типизированными языками?

StackOverflow https://stackoverflow.com/questions/1517582

Вопрос

Я много слышу о том, что новые языки программирования являются динамически типизированными, но что на самом деле означает, когда мы говорим, что язык является динамически типизированным, а не динамически типизированным?статически типизированный?

Это было полезно?

Решение

Статически типизированные языки

Язык является статически типизированным, если тип переменной известен во время компиляции.Для некоторых языков это означает, что вы, как программист, должны указать тип каждой переменной (например:Java, С, С++);другие языки предлагают ту или иную форму вывод типа, способность системы типов определять тип переменной (например:OCaml, Haskell, Scala, Kotlin)

Основным преимуществом здесь является то, что компилятор может выполнять все виды проверок, и поэтому множество тривиальных ошибок выявляется на очень ранней стадии.

Примеры:C, C++, Java, Rust, Go, Scala

Динамически типизированные языки

Язык является динамически типизированным, если тип связан со значениями времени выполнения, а не с именованными переменными/полями/и т.д.Это означает, что вы, как программист, можете писать немного быстрее, поскольку вам не нужно каждый раз указывать типы (если только вы не используете статически типизированный язык с вывод типа).

Примеры:Перл, Руби, Питон, PHP, JavaScript

Большинство языков сценариев имеют эту функцию, поскольку в любом случае нет компилятора, который бы выполнял статическую проверку типов, но вы можете обнаружить, что ищете ошибку, связанную с неправильной интерпретацией интерпретатором типа переменной.К счастью, скрипты, как правило, небольшие, поэтому ошибкам не так уж много мест, где можно спрятаться.

Большинство динамически типизированных языков позволяют предоставлять информацию о типе, но не требуют ее.Один язык, который в настоящее время разрабатывается, Мошенник, использует гибридный подход, позволяющий динамическую типизацию внутри функций, но обеспечивающий статическую типизацию сигнатуры функции.

Другие советы

Статически типизированные языки программирования выполняют проверку типов (т.процесс проверки и обеспечения соблюдения ограничений типов) на время компиляции в отличие от время выполнения.

В динамически типизированных языках программирования проверка типов выполняется на время выполнения в отличие от время компиляции.

Вот пример, контрастирующий с тем, как Python (динамически типизированный) и Go (статически типизированный) обрабатывают ошибку типа:

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

Python выполняет проверку типов во время выполнения, поэтому:

silly(2)

Работает отлично и выдает ожидаемый результат Hi.Ошибка возникает только в случае попадания в проблемную строку:

silly(-1)

Производит

TypeError: unsupported operand type(s) for +: 'int' and '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)
}

Вышеупомянутое не скомпилируется со следующей ошибкой:

invalid operation: "3" + 5 (mismatched types string and 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:

str = "Hello" # variable str is linked to a string value
str = 5       # now it is linked to an integer value; perfectly OK

Итак, лучше всего думать о переменных в динамически типизированных языках как о просто общие указатели к введенным значениям.

Подводить итоги, тип описывает (или должен был описать) переменные языка, а не сам язык.Его можно было бы лучше использовать в качестве язык со статически типизированными переменными против язык с динамически типизированными переменными ИМХО.

Статически типизированные языки обычно являются компилируемыми языками, поэтому компиляторы проверяют типы (это совершенно логично, не так ли?поскольку типы не могут быть изменены позже во время выполнения).

Динамически типизированные языки обычно интерпретируются, поэтому проверка типов (если таковая имеется) происходит во время выполнения, когда они используются.Это, конечно, приводит к некоторому снижению производительности и является одной из причин, по которой динамические языки (например, Python, Ruby, php) не масштабируются так хорошо, как типизированные (Java, C# и т. д.).С другой стороны, статически типизированные языки требуют больших стартовых затрат:заставляет вас обычно писать больше кода, более сложный код.Но это окупается позже.

Хорошо, что обе стороны заимствуют черты другой стороны.Типизированные языки включают в себя больше динамических функций, например, дженерики и динамические библиотеки в C#, а динамические языки включают больше проверок типов, например, аннотации типов в Python или вариант HACK PHP, которые обычно не являются ядром языка и могут использоваться на требовать.

Когда дело доходит до выбора технологий, ни одна из сторон не имеет явного превосходства над другой.Это просто вопрос предпочтений, хотите ли вы большего контроля или гибкости.просто выберите правильный инструмент для работы и обязательно проверьте, что доступно с точки зрения противоположности, прежде чем рассматривать возможность замены.

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

Статическая типизация

Говорят, что язык программирования использует статическое типирование, когда проверка типов выполняется во время компиляции, в отличие от времени выполнения.При статическом типировании типы связаны с переменными, а не значениями.Статически напечатанные языки включают ADA, C, C ++, C#, Jade, Java, Fortran, Haskell, ML, Pascal, Perl (по отношению к отличительным скаляциям, массивам, хэшам и подпрограммам) и Scala.Статическое типирование является ограниченной формой проверки программы (см. Безопасность типа):Соответственно, это позволяет ловить множество ошибок типа в начале цикла разработки.Шеккеры статического типа оценивают только информацию о типе, которая может быть определена во время компиляции, но способны убедиться, что проверенные условия содержится для всех возможных выполнений программы, что устраняет необходимость повторять чеки типа каждый раз, когда выполняется программа.Выполнение программы также может быть сделано более эффективным (т.е.быстрее или пониженная память), пропуская проверки типа выполнения и обеспечивая другие оптимизации.

Поскольку они оценивают информацию типа во время компиляции и, следовательно, отсутствуют информацию типа, которая доступна только во время выполнения, статические шашки типа являются консервативными.Они отклонят некоторые программы, которые могут быть хорошо подготовлены во время выполнения, но это не может быть статически определено как благополучие.Например, даже если выражение всегда оценивается в True во время выполнения, программа, содержащая код

if <complex test> then 42 else <type error>

будет отклонен как плохой, потому что статический анализ не может определить, что ветвь других не будет принята. [1] Консервативное поведение статических контролеров типа выгодно при редкости:Проверка статического типа может обнаружить ошибки типа в редко используемых путях кода.Без проверки статического типа даже тесты покрытия кода со 100% покрытием кода могут быть не в состоянии найти такие ошибки типа.Тесты покрытия кода могут не обнаружить такие ошибки типа, потому что комбинация всех мест, где создаются значения, и все места, где используется определенное значение, должна быть принята во внимание.

Наиболее широко используемые статически напечатанные языки не являются формально не безопасными.У них есть «лазейки» в спецификации языка программирования, позволяющая программистам писать код, который обходит проверку, выполняемую статическим контролированием типа, и поэтому решают более широкий диапазон задач.Например, Java и большинство языков в стиле C имеют тип наказания, и Haskell имеет такие функции, как Unceseperforformio:Такие операции могут быть небезопасными во время выполнения, поскольку они могут вызвать нежелательное поведение из -за неправильного набора значений при запуске программы.

Динамическая типизация

Говорят, что язык программирования динамически напечатан или просто «динамический», когда большая часть его проверки типа выполняется во время выполнения, в отличие от времени компиляции.При динамическом типировании типы связаны со значениями, а не переменными.Динамически напечатанные языки включают Groovy, JavaScript, LISP, LUA, Objective-C, Perl (по отношению к определяемым пользователям типам, но не встроенным типам), PHP, Prolog, Python, Ruby, SmallTalk и TCL.По сравнению со статическим набором, динамическое типирование может быть более гибким (например,Позволяя программам генерировать типы и функциональность на основе данных времени выполнения), хотя за счет меньших априорных гарантий.Это связано с тем, что динамически напечатанный язык принимает и пытается выполнить некоторые программы, которые могут быть признаны недействительными статическими контролированием типа.

Динамическое типирование может привести к ошибкам типа времени выполнения - то есть во время выполнения, значение может иметь неожиданный тип, и применяется операция, несенурическая для этого типа.Эта операция может произойти еще долго после того, как была проведена ошибка программирования, то есть место, где неправильный тип данных передается в место, которое он не должен иметь.Это затрудняет местонахождение.

Динамически напечатанные языковые системы, по сравнению с их статически напечатанными кузенами, сделают меньше проверок «время компиляции» на исходном коде (но, например, проверяют, что программа является синтаксически правильной).Проверки времени выполнения могут быть более сложными, поскольку они могут использовать динамическую информацию, а также любую информацию, которая присутствовала во время компиляции.С другой стороны, проверки времени выполнения утверждают, что условия удерживаются при конкретном выполнении программы, и эти проверки повторяются для каждого выполнения программы.

Разработка на динамически напечатанных языках часто поддерживается такими методами программирования, как модульное тестирование.Тестирование является ключевой практикой в ​​разработке профессионального программного обеспечения и особенно важно на динамически напечатанных языках.На практике тестирование, проведенное для обеспечения правильной операции программы, может обнаружить гораздо более широкий диапазон ошибок, чем статическая проверка типов, но, наоборот, не может искать в соответствии с ошибками, которые могут обнаружить как тестирование, так и проверка статического типа.Тестирование может быть включено в цикл сборки программного обеспечения, и в этом случае его можно рассматривать как проверку «время компиляции», так как пользователю программы не придется вручную запускать такие тесты.

Рекомендации

  1. Пирс, Бенджамин (2002).Типы и языки программирования.МТИ Пресс.ISBN 0-262-16209-1.

Терминология «динамически типизированный», к сожалению, вводит в заблуждение.Все языки статически типизированы, а типы — это свойства выражений (а не значений, как некоторые думают).Однако некоторые языки имеют только один тип.Такие языки называются однотипизированными.Одним из примеров такого языка является нетипизированное лямбда-исчисление.

В нетипизированном лямбда-исчислении все термины являются лямбда-термами, и единственная операция, которую можно выполнить над термином, — это применить его к другому термину.Следовательно, все операции всегда приводят либо к бесконечной рекурсии, либо к лямбда-члену, но никогда не сигнализируют об ошибке.

Однако если бы мы дополнили нетипизированное лямбда-исчисление примитивными числами и арифметическими операциями, то мы могли бы выполнять бессмысленные операции, такие как сложение двух лямбда-членов вместе: (λx.x) + (λy.y).Можно возразить, что единственное разумное решение — это сигнализировать об ошибке, когда это происходит, но чтобы иметь возможность сделать это, каждое значение должно быть помечено индикатором, который указывает, является ли термин лямбда-термином или числом.Затем оператор сложения проверит, действительно ли оба аргумента помечены как числа, и если это не так, сигнализирует об ошибке.Обратите внимание, что эти теги нет типы, поскольку типы — это свойства программ, а не значений, создаваемых этими программами.

Однотипизированный язык, который делает это, называется динамически типизированным.

Такие языки, как JavaScript, Python и Ruby, являются однотипизированными.Опять же, typeof оператор в JavaScript и type функции в Python имеют вводящие в заблуждение имена;они возвращают теги, связанные с операндами, а не их типы.Сходным образом, dynamic_cast на С++ и instanceof на Яве делаю нет делайте проверки типов.

Скомпилировано против.Интерпретировано

«Когда исходный код переведен»

  • Исходный код:Исходный код (обычно вводится человеком в компьютер)
  • Перевод:Преобразование исходного кода во что-то, что может прочитать компьютер (т.е.Машинный код)
  • Время выполнения:Период выполнения команд программой (после компиляции, если она скомпилирована)
  • Скомпилированный язык:Код переведен перед выполнением
  • Интерпретируемый язык:Код транслируется на лету, во время выполнения

Ввод текста

«Когда проверяются типы»

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

Динамическая типизация более гибкая, что некоторые ценят.Обычно это позволяет переменным изменять типы, что может привести к непредвиденным ошибкам.

Статически типизированные языки проверяют тип во время компиляции, и тип НЕ может измениться.(Не будьте любезны с комментариями о приведении типов, создается новая переменная/ссылка).

В динамически типизированных языках проверка типов выполняется во время выполнения, а тип переменной МОЖЕТ быть изменен во время выполнения.

Статически типизированные языки:каждая переменная и выражение уже известны во время компиляции.

(int a; a может принимать только значения целочисленного типа во время выполнения)

Примеры:С, С++, Ява

Динамически типизированные языки:переменные могут принимать разные значения во время выполнения, и их тип определяется во время выполнения.

(var a; a может принимать любые значения во время выполнения)

Примеры:Руби, Питон.

Симпатичные и простые определения, но соответствующие потребностям:Статически типизированные языки привязывают тип к переменной во всей ее области действия (например:Scala) Динамически напечатанные языки связывают тип с фактическим значением, на которую ссылается переменная.

  • В статически типизированном языке переменная связана с типом, который известен во время компиляции, и этот тип остается неизменным на протяжении всего выполнения программы.Аналогично, переменной можно присвоить только значение, которое является экземпляром известного/указанного типа.
  • В динамически типизированном языке переменная не имеет типа, и ее значение во время выполнения может быть любым и иметь любую форму.

Статически типизированные языки, такие как C++, Java, и динамически типизированные языки, такие как Python, отличаются только с точки зрения выполнения типа переменной. Статически типизированный языки имеют статический тип данных для переменной, здесь тип данных проверяется во время компиляции, поэтому отладка намного проще... тогда как Динамически типизированный языки не делают то же самое, проверяется тип данных, при котором выполняется программа, и, следовательно, отладка немного затруднена.

Более того, они имеют очень небольшую разницу и могут быть связаны с строго типизированный и слабо типизированный языки.Строго типизированный язык не позволяет использовать один тип как другой, например.C и C++... тогда как слабо типизированные языки позволяют, например, .python

динамически типизированный язык помогает быстро создавать прототипы концепций алгоритмов без необходимости думать о том, какие типы переменных необходимо использовать (что является необходимостью в статически типизированный языке).

Статически типизированные языки (компилятор разрешает вызовы методов и компилирует ссылки):

  • обычно лучшая производительность
  • быстрее компилировать обратную связь об ошибках
  • лучшая поддержка IDE
  • не подходит для работы с неопределенными форматами данных
  • труднее начать разработку, когда модель не определена, когда
  • больше времени компиляции
  • во многих случаях требуется написать больше кода

Динамические типизированные языки (решения принимаются в работающей программе):

  • более низкая производительность
  • более быстрое развитие
  • некоторые ошибки могут быть обнаружены только позже во время выполнения
  • хорошо для неопределенных форматов данных (метапрограммирование)

Статическая типизация: Такие языки, как Java и Scala, являются статически типизированными.

Переменные должны быть определены и инициализированы, прежде чем они будут использоваться в коде.

напримеринтервал х;х = 10;

System.out.println(x);

Динамическая типизация:Perl — динамически типизированный язык.

Переменные не нужно инициализировать перед использованием в коде.

у=10;используйте эту переменную в более поздней части кода

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top