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

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

bob = 1
bob = "bob"

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

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


当前回答

Python变量存储对表示该值的目标对象的无类型引用。

任何赋值操作都意味着将未类型化的引用赋值给已赋值的对象——即对象通过原始引用和新引用(已计数)共享。

值类型绑定到目标对象,而不是引用值。(强)类型检查是在执行带有该值的操作(运行时)时执行的。

换句话说,变量(技术上)没有类型——如果想要精确,那么按照变量类型来考虑是没有意义的。但是引用是自动解除引用的我们实际上是根据目标对象的类型来考虑的。

其他回答

这个问题已经回答过几次了,但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是强动态类型的。

强类型意味着值的类型不会以意外的方式改变。只包含数字的字符串不会像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成为一种严格的类型语言,其中类型是完全不相连的,并且只能通过类型类进行受控的重载。

我刚刚发现了一个极好的、简洁的记忆方法:

动态/静态类型表达式;强/弱类型值。

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'