Python сильный/слабый язык динамического/статического типа?

Я узнал, что Python — это сильно-динамический типизированный язык.
динамический: тип переменной определяется при выполнении время НЕ время компиляции. В этой части я могу понять, что тип определяется, когда значение (тип, конечно) присваивается переменной.

strong: вы НЕ можете изменить тип переменной. Но это не реальный случай:

>>> a = 1
>>> type(a)
<type 'int'>
>>> a = 's'
>>> type(a)
<type 'str'> 

В приведенном выше коде я могу изменить тип переменной a с int на str.
Как это может произойти? Могу ли я сказать, что Python — язык со слабой типизацией?


ИЗМЕНИТЬ:

Если вы можете дать мне фрагмент кода, показывающий, как строгая динамическая типизация влияет на программирование на Python, я был бы вам очень признателен! Во время моего обычного написания кода меня никогда не волновали проблемы строгой динамической типизации. Это также редко влияет на мою функцию кода. Странный!


EDIT:
Вывод из ответов:

  1. Только объект/значение имеет атрибут типа. Переменная не имеет типа.
  2. (Сильный) Тип определяет, какие операции можно выполнять над/между объектами/значениями (возможно, переменными, ссылающимися на них).
  3. (Динамический) Тип означает переменную просто метку (ссылка на объект/значение). Эта метка может относиться к любому объекту/значению любого типа.

person Zachary    schedule 15.01.2014    source источник
comment
строгая (или слабая) типизация не связана с типом переменной [или выражения], а скорее с операциями [и неявными преобразованиями], разрешенными в или между ними. значения   -  person user2864740    schedule 15.01.2014
comment
вики. python.org/moin/   -  person Alexander Mihailov    schedule 15.01.2014


Ответы (4)


Суть в том, что объект сохраняет свой тип независимо от того, что вы с ним делаете. Int есть int есть int; ул есть ул; поплавок есть поплавок. На слабо типизированном языке вы можете сделать что-то вроде

i = "1" 
j = i + 2

и получить j == 3. В питоне вы получаете

TypeError: cannot concatenate 'str' and 'int' objects

Строка всегда является строкой и не может рассматриваться как целое число, даже если строка содержит число.

Попробуй это:

for a in {1, 'abc', 3.14159}:
    print a
    print type(a)

который будет производить

3.14159
<type 'float'>
1
<type 'int'>
abc
<type 'str'>

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

person Erik Johnson    schedule 15.01.2014
comment
Объект JavaScript также сохраняет свой тип. Тем не менее, JavaScript считается слабо типизированным: таким образом, строгая/слабая типизация не означает просто то, что х есть х. (Выражение "1" + 2 не изменяет тип какого-либо значения ни в Python, ни в JavaScript.) - person user2864740; 15.01.2014
comment
Пример ошибочного кода правильный (и я бы сказал, что отсутствие неявных преобразований является краеугольным камнем), но большая часть остального — плохой аргумент в пользу строгой типизации. В JavaScript [1,"foo",{}].map(function (v) { return typeof v; }) дает ["number","string","object"], что полностью отрицает вспомогательный аргумент. - person user2864740; 15.01.2014
comment
Вопрос был о Питоне. У меня есть только тривиальный опыт работы с Javascript, поэтому я не пытался описать или сослаться на него. - person Erik Johnson; 15.01.2014

Вы не столько меняете тип переменной, сколько переназначаете a, которая была int, новой переменной с тем же именем, которая является str.

person mhlester    schedule 15.01.2014

Когда вы переназначаете новое значение переменной, я бы не сказал, что это «та же самая» переменная, поскольку ее идентификатор изменится. Посмотрите на этот пример:

a = 1
print id(a)
a = 2
print id(a)
a = "asd"
print id(a)

печатает на моей машине:

30925512
30925488
37467840

это означает, что a больше не тот же объект. Из документов Python:

id(object) Возвращает «идентификатор» объекта. Это целое (или длинное целое), которое гарантированно будет уникальным и постоянным для данного объекта в течение всего времени его жизни.

person Christian    schedule 15.01.2014
comment
Я никогда раньше не использовал оператор id(object). Ваше объяснение несколько убедительно с другой точки зрения. - person Zachary; 15.01.2014
comment
@Zachary Это та же самая переменная (до сих пор единственный способ получить доступ к переменной - это имя в определенной области). Он просто возвращает другое значение. id относится к значению/объекту (которое является результатом оценки выражения-переменной) и, таким образом, не может использоваться, чтобы сказать что-либо о переменной иначе. - person user2864740; 15.01.2014
comment
Вы имеете в виду, что эта функция id() бесполезна в коде? Как это можно использовать? - person Zachary; 15.01.2014
comment
@Zachary Это редко бывает полезно в обычном коде. Возвращаемое значение является непрозрачным идентификатором объекта. Это не имеет ничего общего с печатанием. - person user2864740; 15.01.2014

Было бы точнее сказать, что Python строго типизирован, потому что вы не можете изменить тип объекта. Переменные Python несколько отличаются от переменных во многих других языках, потому что они представляют собой не что иное, как имена, указывающие на объекты. Сами имена не содержат информации о типе, ее содержат только объекты.

В языке со слабой типизацией, таком как JavaScript, вы можете сделать что-то вроде 1 == "1" и получить истинный результат, или сделать 3 - "2" и получить 1, потому что объекты неявно выполняют принудительное преобразование между целым числом и строкой; тип объекта не является «частью его личности», и объекты ведут себя как разные типы в зависимости от контекста. В Python вы не можете делать такие вещи; если вы хотите, чтобы один тип действовал как другой, вы должны фактически создать новый объект нового типа, потому что тип объекта присущ объекту.

person BrenBarn    schedule 15.01.2014
comment
Итак, переменные в Python подобны большинству других языков, потому что переменные [типов, которые не представлены как непосредственные значения] не что иное, как имена, указывающие на объекты.. :) Python просто избегает некоторого багажа имен и реализация-разговор. - person user2864740; 15.01.2014
comment
@ user2864740: Я не знаю, как бы вы оценили большинство, но я не совсем согласен с тем, что вы там говорите. В таком языке, как C++, переменная — это не просто метка для объекта, она также представляет собой хранилище этого объекта, поэтому в C++ выполнение чего-то вроде a = b может скопировать b. В Python выполнение a = b просто добавляет a в качестве метки, указывающей на объект, на который указывает b, и ничего не копируется. Кроме того, в таких языках типы связаны с именами, а не только со значениями. - person BrenBarn; 15.01.2014
comment
BreBarn, это означает, что в Python мы не можем получить адрес переменной, как в C++ &a. - person Zachary; 15.01.2014
comment
Как только T* введено в C/C++/Obj-C (то есть, где переменная является не чем иным, как косвенным поиском), конечный результат простого имени вполне применим. Java, C#, Scala и т. д. эффективно неявно обрабатывают все ссылочные типы T как T*. Многие другие динамические языки, такие как JavaScript, Ruby и ST, возможно, имеют такое же определение переменных/привязок, что и Python. (Не имеет значения, связан ли тип с переменной, это всего лишь ограничение привязки: object v.) - person user2864740; 15.01.2014
comment
@ Закари Ты не можешь. Но вы не можете сделать это и на Java или C# (без unsafe). - person user2864740; 15.01.2014