我遇到过一些链接,上面说Python是一种强类型语言。

然而,我认为在强类型语言中你不能这样做:

bob = 1
bob = "bob"

我认为强类型语言在运行时不接受类型更改。也许我对强/弱类型的定义是错误的(或过于简单)。

那么,Python是强类型语言还是弱类型语言呢?


当前回答

Python是强动态类型的。

强类型意味着值的类型不会以意外的方式改变。只包含数字的字符串不会像Perl中那样神奇地变成数字。每次类型更改都需要显式转换。 动态类型意味着运行时对象(值)具有类型,而静态类型中变量具有类型。

至于你的例子

bob = 1
bob = "bob"

这是因为变量没有类型;它可以命名任何对象。在bob=1之后,你会发现type(bob)返回int,但在bob="bob"之后,它返回str。(注意,type是一个常规函数,所以它计算其参数,然后返回值的类型。)

与此相比,老式的C语言是弱静态类型的,因此指针和整数几乎是可以互换的。(现代ISO C在很多情况下需要转换,但我的编译器在默认情况下仍然很宽容。)

我必须补充一点,强类型和弱类型更多的是一个连续体,而不是一个布尔选择。c++具有比C更强的类型(需要更多的转换),但类型系统可以通过使用指针强制转换来颠覆。

在动态语言(如Python)中,类型系统的强度实际上取决于其原语和库函数对不同类型的响应方式。例如,+是重载的,所以它对两个数字或两个字符串有效,而不是一个字符串和一个数字。这是在实现+时做出的设计选择,但从语言的语义来看并不是必须的。事实上,当你在自定义类型上重载+时,你可以让它隐式地将任何东西转换为数字:

def to_number(x):
    """Try to convert function argument to float-type object."""
    try: 
        return float(x) 
    except (TypeError, ValueError): 
        return 0 

class Foo:
    def __init__(self, number): 
        self.number = number

    def __add__(self, other):
        return self.number + to_number(other)

类Foo的实例可以添加到其他对象:

>>> a = Foo(42)
>>> a + "1"
43.0
>>> a + Foo
42
>>> a + 1
43.0
>>> a + None
42

请注意,尽管强类型Python完全可以添加int和float类型的对象,并返回float类型的对象(例如,int(42) + float(1)返回43.0)。另一方面,由于类型之间的不匹配,如果尝试以下(42::Integer) + (1:: Float), Haskell会抱怨。这使得Haskell成为一种严格的类型语言,其中类型是完全不相连的,并且只能通过类型类进行受控的重载。

其他回答

我认为,这个简单的例子可以解释强类型和动态类型之间的区别:

>>> tup = ('1', 1, .1)
>>> for item in tup:
...     type(item)
...
<type 'str'>
<type 'int'>
<type 'float'>
>>>

java:

public static void main(String[] args) {
        int i = 1;
        i = "1"; //will be error
        i = '0.1'; // will be error
    }

TLDR;

Python类型是动态的,所以你可以将字符串变量更改为int(在静态语言中你不能)

x = 'somestring'
x = 50

Python类型是强的,所以你不能合并类型:

'foo' + 3 --> TypeError: cannot concatenate 'str' and 'int' objects

在弱类型Javascript中,这种情况会发生……

 'foo'+3 = 'foo3'

关于类型推断

有些语言(如Java)强制显式声明对象类型

int x = 50;

像Kotlin这样的其他人只是从值本身推断它是一个int型

x = 50

但是因为这两种语言都使用静态类型,x不能从int型改变。两种语言都不允许像这样的动态变化

x = 50
x = 'now a string'

这个问题已经回答过几次了,但Python是一种强类型语言:

>>> x = 3
>>> y = '4'
>>> print(x+y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

JavaScript代码:

var x = 3    
var y = '4'
alert(x + y) //Produces "34"

这就是弱类型和强类型的区别。弱类型自动尝试从一种类型转换为另一种类型,这取决于上下文(例如Perl)。强类型从不隐式转换。

您的困惑在于误解了Python如何将值绑定到名称(通常称为变量)。

在Python中,名称没有类型,所以你可以这样做:

bob = 1
bob = "bob"
bob = "An Ex-Parrot!"

名字可以绑定到任何东西上:

>>> def spam():
...     print("Spam, spam, spam, spam")
...
>>> spam_on_eggs = spam
>>> spam_on_eggs()
Spam, spam, spam, spam

欲进一步阅读:

https://en.wikipedia.org/wiki/Dynamic_dispatch

还有稍微相关但更高级的:

http://effbot.org/zone/call-by-object.htm

术语“强类型”没有明确的定义。

因此,这个词的使用取决于你和谁说话。

我不认为任何没有显式声明变量类型或没有静态类型的语言是强类型的。

强类型不只是排除转换(例如,“自动”将整数转换为字符串)。它排除了赋值(即改变变量的类型)。

如果以下代码编译(解释),则该语言不是强类型的:

Foo = 1 Foo = "1"

在强类型语言中,程序员可以“依赖”类型。

例如,如果程序员看到声明,

UINT64 kZarkCount;

并且他或她知道20行之后,kZarkCount仍然是UINT64(只要它出现在同一个块中)——而不必检查中间的代码。

现有的答案大多同意Python是一种强类型语言,因为它不会隐式地将值从一种类型转换为另一种类型。这些答案提到了将字符串添加到整数的情况来支持这种说法;"foo" + 3在Python中引发TypeError,而在Javascript(通常被认为是弱类型语言)中,数字3隐式转换为字符串,然后连接,因此结果是字符串"foo3"。

但在其他一些情况下,Python确实会执行隐式类型转换:

# implicit conversion from int to float
1 + 1.0

# implicit conversion from list to bool
if []: pass

相比之下,f#(通常被认为是强类型语言)不允许这两种:

  1 + 1.0;;
  ----^^^
error FS0001: The type 'float' does not match the type 'int'

  if [] then 1 else 2;;
  ---^^
error FS0001: This expression was expected to have type bool but here has type 'a list  

因此,“强类型”和“弱类型”语言并没有严格的二分法,相反,我们可以说Python比Javascript更强类型,但没有f#强类型。