我看到过一些链接说Python是一种强类型语言。
然而,我认为在强类型语言中你不能这样做:
bob = 1
bob = "bob"
我原以为强类型语言不允许在运行时更改类型。也许我的定义过于简单或错误。
那么,Python是强类型语言还是弱类型语言?
我看到过一些链接说Python是一种强类型语言。
然而,我认为在强类型语言中你不能这样做:
bob = 1
bob = "bob"
我原以为强类型语言不允许在运行时更改类型。也许我的定义过于简单或错误。
那么,Python是强类型语言还是弱类型语言?
Python的类型是强类型和动态类型。
至于你的例子:
bob = 1
bob = "bob"
这是因为变量没有类型限制,可以命名任何对象。在bob=1之后,您会发现type(bob)
返回int
,但在bob="bob"
之后,它返回str
。(请注意type
是一个常规函数,它评估其参数,然后返回值的类型。)+
被重载,使其适用于两个数字或两个字符串,但不适用于字符串和数字。这是实现+
时做出的设计选择,但并不是根据语言语义的必要性。事实上,当您在自定义类型上重载+
时,可以使其将任何内容隐式转换为数字。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
),但是由于Haskell中存在类型不匹配的问题,如果尝试执行以下操作(42 :: Integer) + (1 :: Float)
,Haskell会报错。这使得Haskell成为一种严格类型的语言,其中类型完全不相交,并且只有通过类型类进行控制形式的重载。
我认为所有现有答案都忽略了一些重要问题。
弱类型意味着允许访问底层表示。在C语言中,我可以创建一个字符指针,然后告诉编译器我想将其用作整数指针:
char sz[] = "abcdefg";
int *i = (int *)sz;
在一个使用32位整数的小端平台上,这使得 i
成为由数字0x64636261
和0x00676665
组成的数组。实际上,你甚至可以将指针本身强制转换为整数(具有适当的大小):intptr_t i = (intptr_t)&sz;
当然,这意味着我可以在系统的任何地方覆盖内存。
char *spam = (char *)0x12345678
spam[0] = 0;
现代操作系统使用虚拟内存和页保护,所以只能覆盖自己进程的内存。但 C 本身并没有提供这种保护,如在 Classic Mac OS 或 Win16 上编码过的人可以告诉你的那样,传统的 Lisp 也允许类似的 hackery。char sz[]
并不是指向字符的指针,而是字符数组,在赋值操作中会退化为指针。 - majkel.mkPython语言的类型是动态的,所以你可以将一个字符串变量更改为整数(在静态语言中不行)。
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'
'x' + 3
可能是通过operator+
重载来实现类型转换的吧? - VimNingint / int = float
的存在(以及一般情况下,int 几乎可以在任何 float 可以使用的地方使用)使得 Python3 在类型上略显薄弱。 - o11c根据这篇维基 Python文章,Python既是动态类型的,又是强类型的(也提供了很好的解释)。
也许您正在思考静态类型语言,在这些语言中,类型在程序执行期间无法更改,并且类型检查在编译时进行以检测可能的错误。
这个Stack Overflow问题可能会有所帮助:动态类型语言与静态类型语言,并且这篇维基百科文章类型系统提供了更多信息。
这个问题已经被回答过几次了,但是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'
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://zh.wikipedia.org/wiki/动态调用
和略微相关但更高级的:
"3"*4
。当然,结果是"3333"
。你不能说它转换任何一件事。当然,这可能只是争论语义。 - Wayne Wernerfloat
和 int
结合起来产生 float
就意味着它在隐式转换类型。浮点数和整数之间存在自然关系,事实上,类型层次结构也明确说明了这一点。我想你可以争辩说 Javascript 认为 '3'+4
和 'e'+4
都是定义良好的操作,就像 Python 认为 3.0 + 4
是定义良好的一样,但此时就不存在强类型或弱类型的概念,只有(未)定义的操作。 - Wayne WernerTypeError
(或等价物)的语言都是强类型语言。 - Wayne Werner"强类型"这个词没有明确的定义。
因此,使用这个术语是取决于你和谁在交流。
我认为任何变量类型不明确声明或静态类型化的语言都不是强类型语言。
强类型不仅会防止转换(例如,将整数“自动”转换为字符串)。它还会防止赋值(即,更改变量的类型)。
如果以下代码被编译(解释),则该语言不是强类型:
Foo = 1 Foo = "1"
在强类型语言中,程序员可以“信任”一种类型。
例如,如果程序员看到声明:
UINT64 kZarkCount;
并且他或她知道在后面的20行代码中,kZarkCount仍然是一个UINT64类型的变量(只要它出现在同一个块中)- 而不需要检查中间的代码。
Python是强类型语言,因为它没有未经检查的动态类型错误。换句话说,你不能违反它的类型系统。
&
表示单个T* (T&)
操作符值,其中T
是一个泛型类型/C++表达式std::exception
表示单个S
类值,其中S
是std::exception
的一个泛型子类型)。+
表示int (int&, int&)
和float (float&, float&)
操作符值/C++表达式3.5
表示float
和bool
值)。Cardelli(Luca),Wegner(Peter),“理解类型、数据抽象和多态性”,计算机调查,1985年,第17卷,第4期,第471-523页,DOI:https://doi.org/10.1145/6041.6042。
True
或False
。但数字提升呢?在Python中,“1.0 + 2”和在Perl或C中一样都可以正常工作,即使“'1.0'+2”不行。我同意@jbrendel的看法,这并不是真正的隐式转换,而是重载——但同样地,Perl也没有进行任何隐式转换。如果函数没有声明参数类型,则隐式转换就没有发生的地方。 - abarnertif isValid(value) - 1
可能会出现问题。布尔型被转换为整数,然后被评估为“真值”。False - 1
变成了“真值”,而True - 1
则变成了“假值”,导致一个令人尴尬的、难以调试的两层偏移量错误。从这个意义上讲,Python基本上是“强类型”的;类型转换通常不会导致逻辑错误。 - Aaron3468