為什麼說 Python 是強類型語言?

撇開 弱類型、強類型、動態類型、靜態類型語言的區別是什麼? - 編程語言 - @姚培森給的學術定義不談,就只從「類型檢查有多嚴格」價值觀取向上來區分強弱類型語言。

然而 Python 支持 int, float 和 bool 之間的混合運算,`not` 關鍵字大概能把 Python 幾乎所有內置類型統統轉換成 bool 類型。那 Python 與 C 之間到底還有什麼區別,以致讓一些人認為 Python 是強類型,C 是弱類型?


強弱定義有學術上的,如果按照題主提到的含義「是否存在隱式轉換」來看待的話,其實py和C還是有差別的,不過這個差別得去實現層面去看了,具體說就是,類型的轉換是語言本身決定的,還是類型自己決定的

譬如說,支持int和float的混合運算,C就是語言本身決定的,編譯器看到你用int和float做加法,就根據規定把int轉float,然後做float的加法,這是一種弱類型特性

但是py中並不是這樣的,py是動態類型語言,編譯器看到a+b,並不知道a和b是什麼類型,其實也不需要知道,因為只有運行時才知道它們是什麼類型(嚴格說,是它們「引用的對象」是什麼類型,因為py的變數是無所謂類型的),語言上的規定很寬鬆,就一句話:a+b等同於a.__add__(b),也就是說加法運算是對象的一個方法,由對象自己決定(實際情況稍複雜一點,也可以等同於b.__radd__(a),即正向走不通走反向),所以並不是「隱式類型轉換」,而是「a類型能支持以b的類型為參數的加法方法」;而像not轉bool,其實也是調用方法,任何對象轉bool都是由其本身定義的方法決定,只不過過程更複雜,會先看有沒有__nonzero__方法,如果沒有就看有沒有__len__……,總之是類型自己決定行為的,當然內建類型的行為,語言規範也會定義到,但依然是runtime實現而非編譯器介入

所以上面說C有「弱類型特性」,弱類型是一種特性,一個語言也可以同時存在強弱兩種特性,用這個判斷語言本身其實只是一種大略的說法了,《編譯原理》一書甚至有一節論述中認為java也是動態類型語言呢,因為所有對象都可以用Object引用


反對@劉哲奇的答案。

首先在Python中=是重新賦值的意思,並不是對比。其二是判斷一個語言是否是強類型語言的標準只有一個:

如果語言經常隱式地轉換變數的類型,那這個語言就是弱類型語言,如果很少會這樣做,那就是強類型語言。

Python很少會隱式地轉換變數的類型,所以Python是強類型的語言。

針對題主的問題:Python並不會隱式地轉換int或其他類型的變數的類型為bool型,而是變數的類中的__bool__方法讓大家產生了這種錯覺。Python在判斷一個變數的布爾值時,如果該變數有__bool__方法,那麼解釋器就會調用該方法判斷變數是否為真,注意是邏輯上的變數是否為真而不是變數的值等於真。

延伸:

然而這是什麼情況?

我們可以去看看bool類的源碼:

原來在Python中,bool類的父類是int……所以實際上:

在Python中==其實調用的是__eq__方法,而bool類繼承自int類,又沒有重寫__eq__方法,所以在使用==的時候,bool類的對象自然就會調用父類的__eq__方法了,自然就會出現上面的這種情況了。


首先,python的not xxx,幾乎與C的(!xxx) 沒什麼區別。

int與float的問題,我不是專家,不清楚專業上該怎麼表述,直觀感覺就是小數據類型轉換成大數據類型的操作。

說C是弱類型顯然是誇張了,主要問題是void*這種指針可以任意轉換,這樣類型細節就丟掉了。


首先看你怎麼定義強弱類型

按照一般人的理解,強類型是指:一個變數的實際類型在運行期是可以用某種方式確定的,在Python中用type()確定,JS用typeof,Java用instanceof/getClass()

弱類型是指,一個變數的類型根本不會對外暴露,使用的時候,可以把它當作整型/浮點型/字元串/bool等等

按這種定義,幾乎不存在弱類型的語言,因為實現起來不僅麻煩,而且沒有效率。

注意區分隱式類型轉換不是弱類型:

// js:
1 + "1"
1 * "1"

這是JS解釋器自作多情的功能,應該避免使用。

正常語言的隱式轉換隻發生在「允許升級」的情況下,一般僅限short/int/long/float/double:

// java
long x = 1L + 2; // int -&> long
long x = 1L + 2.0; // error: double -&> long

C語言沒有bool類型,習慣以0表示FALSE,非零都看成TRUE

Python的if規定了false的幾種情況:False, None, "", [], (),這和int和bool混合運算沒啥關係,因為Python的True=1,False=0:

&>&>&> 1+True
2
&>&>&> 1/False
ZeroDivisionError

還要注意區分操作符重載

如果強弱類型的定義不一樣,那討論就沒啥意義。


我的結論:Python是一種強類型的動態語言。

有人可能會問,在python中,可以這樣寫而不報錯,所以是弱類型的:

i=1

print(i)

i="hello world"

print(i)

 顯然,這樣的同學搞錯了python的實現。實際上述代碼中,i僅僅是一個指向,每次賦值,實際上只是改變了i的指向。

實際上,這裡python表現出的特性為,他是一種動態類型語言。動態類型語言是一種在運行期間才去確定數據類型的語言,與靜態類型相反。VBScript 和 Python 是動態類型的,因為它們確定一個變數的類型是在你給它賦值的時候。靜態類型語言是一種在編譯期間就確定數據類型的語言。大多數靜態類型語言是通過要求在使用任一變數之前聲明其數據類型來保證這一點的。Java 和 C 是靜態類型語言。

  Python 是強制類型定義的。指的是加入我們有一個整數,如果不明確地進行轉換 ,不能將把它當成一個字元串,所以顯然,C/C++和Java都是強類型語言。 弱類型語言與強類型相反。VBScript 是弱類型的。在 VBScript 中,我們可以將字元串 "12" 和整數 3 進行連接得到字元串"123",然後可以把它看成整數 123 ,所有這些都不需要任何的顯示轉換。


強語言類型,

兩個不同類型相加會出現

typeerror

如下

當弱類型相加的時候

你看並不會出現typeerror.

但是你會蛋疼的發現結果不正確,但是程序又不報錯,也不異常。你不感受到深深的惡意嗎?

對這個問題進行簡單的概括

就是上邊的樣子,大家可以做一個簡單的判斷。

以上


我看了兩個問題下的所有回答,發現都沒有提到 Guido van Rossum (Benevolent Dictator For Life (BDFL))的意見,這裡貼一下,提供更多信息。

Weak typing is not really a fair description of what"s going on in Python. It"s really runtime typing because every object is labeled with a type.」 by Guido van Rossum

他的意思就是,Python 是 runtime typing,不是 weak typing,那是不是就意味著 Python is a strongly typed language,好像也不是。

Strong versus Weak Typing

Strong versus Weak Typing

A Conversation with Guido van Rossum, Part V

by Bill Venners with Frank Sommers

February 10, 2003

……

Guido van Rossum: One of the things I like about Python is that everything happens at runtime. Python"s compile-time complexity is almost nonexistent compared to that complexity of languages like C++ or even Java, which is much simpler than C++ at compile time. Although, doesn"t Sun plan to add generics to Java?

Bill Venners: Yes.

Guido van Rossum: Well, they have to, because it is a strongly typed language, and you can"t do certain things with strong typing otherwise.

Weak typing is not really a fair description of what"s going on in Python. It"s really runtime typing because every object is labeled with a type. Bill Venners: Every object in Python does have a type.

Guido van Rossum: Every object does have a type. It is a string, an integer, a floating point number, a dictionary, or whatever.

Bill Venners: But method parameters and return values don"t have types.

Guido van Rossum: Those variables don"t have types. Runtime typing works differently, because you can easily make a mistake where you pass the wrong argument to a method, and you will only find out when that method is actually called. On the other hand, when you find out, you find out in a very good way. The interpreted language tells you exactly this is the type here, that"s the type there, and this is where it happened. If you make a mistake against the type system in C or C++, and it only happens at runtime, you"re in much worse shape. So you can"t simply say strongly typed languages are better than runtime typed languages or vice versa, because you have a whole tradeoff of different parts.


看了那麼多層回答,發現很多人連什麼是強類型都沒弄懂。

其實我也不懂,所以別討論這個問題了行不?大家對強類型的定義都不一樣,討論「是不是」有什麼意思?


強類型不允許隱式轉換類型,python有個not關鍵字,可以理解為顯示轉換,所以是強類型。。。大概吧


Python本就是弱類型。。。說Python是強類型,不過是一群無知的初學者不懂裝懂,互相洗腦而已。

強類型(JAVA,C#,C++):

int a=1;

a=「1」; //報錯

弱類型(JS,PHP,PYTHON)

var a=1; //JS

$a=1; //php

a=1 # python

a="1"; //不報錯


推薦閱讀:

C/C++ 這類更底層的語言,如果把平時常用的高級函數和功能都實現,能否達到 Python 的開發效率?
python 的絕對優勢在哪些方向?
學習編程,如果只看"工程類"書籍,不看"科學類『書籍,會有哪些不良後果?
個人充電,想學一門替代python的語言?
自動處理excel數據,用什麼語言合適?

TAG:編程語言 | Python | 類型系統 |