1. 程式人生 > >Python 和 Lua 學習比較 一

Python 和 Lua 學習比較 一

好記性不如爛筆頭。
作的筆記以後也能來再看看。

python有多種語言寫成的版本,這裡只記錄C/C++寫的版本,lua本身是使用標準C/C++編寫的。

所以各位同學知道C的強大了吧,我覺得作為程式設計師,應該都要學一下C/C++,這是你以後成長的奠基石。以後你如果不爽python或者lua了,自己編一種新的指令碼語言,^_^

set path=%path%;C:\python34
set path=%path%;C:\lua5.3.2

python和lua都是解釋類語言,不用編譯和連結,支援動態型別語言,意思就是這兩個傢伙都支援變數的型別變化,比如:

python:

>>> 
type(a) ''' 輸出 #Traceback (most recent call last): # File "<stdin>", line 1, in <module> #NameError: name 'a' is not defined ''' >>> a = "123" >>> type(a) # 輸出 <class 'str'> >>> id(a) # 輸出 35672112 - 每個人的結果不一樣 >>> a = 12 >>> type(a) # 輸出 <class 'int'>
>>> id(a) # 輸出 1488898480 - 每個人的結果不一樣 >>> a = 12.3 >>> type(a) # 輸出 <class 'float'> >>> id(a) # 輸出 5734688 - 每個人的結果不一樣 >>> 0/0 '''作死除法 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero '''

lua:

--[[
    lua多行註釋
--]] --這裡習慣在前面加上'--'
> type(a) -- 輸出 nil
> a = "123"
> type(a) -- 輸出 string
> a = 12
> type(a) -- 輸出 number
> a = 12.3
> type(a) -- 輸出 number
> 0/0 -- 輸出 nan  意思就是Not a Number 不是數字
> type(0/0) -- 輸出 number
--[[
    上面是否讓你意外呢? 雖然是nan 但是它的型別還是number的
--]]

上面的程式碼演示了最基本的型別,在python中,使用未定義的變數會報錯,而在lua中,只是簡單的nil型別資料,相對於python,lua沒有id函式,把所有的整數,浮點數都統稱為number型別。細看python,我們發現雖然我們的變數a沒有變,但是通過id函式,我們看出來了,a其實還是變了,這個具體的變法,我們不需要關心,我們只需要瞭解有這麼回事,C/C++程式設計師知道,這裡其實是存放a內容的記憶體地址變了,是一個新的物件。至於0除以0的問題,大家看註釋瞭解就好了。
lua包含的資料型別有nilbooleannumberstringtablefunctionuserdatathread
Python後面再總結。

python和lua的提示也要了解一下,後面就不提示這個內容了。
python 預設提示 >>> ; 繼續行提示
lua 預設提示 > ; 繼續行提示 >>
前面不帶符號的就是計算的輸出了。
編碼格式的話,我覺得如果沒有必要,儘量都用UTF8,以後你會感謝我的^_^。

註釋的方法,我已經放在上面的程式碼註釋中了。

在繼續學習之前,我總結了個查詢lua API的方法

for k,v in pairs(_G) do print(k,v) end #它會告訴我們lua有哪些可用table或者function

至於python,則是通過dir內建函式

import builtins
dir(builtins)#跟lua一樣,檢視當前內建的變數和函式,模組
dir()#檢視當前定義的變數,函式,模組
import sys
dir(sys)#檢視該sys包下可用的變數,函式,模組

計算能力的話,兩者都一樣,都可以當計算器使用
python:

>>> 2 + 2
4 #前面沒有符號,這是python的輸出結果
>>> 50 - 5*6
20
>>> (50 - 5*6) / 4
5.0
>>> 8 / 5  # 除法總是返回一個浮點數
1.6
>>> 5 // 3 #取整
1
>>> 5 % 3 #取餘
2
>>> width = 20
>>> height = 5 * 9
>>> width * height
900
>>> 3 * 3.75 / 1.5 
7.5 #整數與浮點數的計算,python會把整數轉換成浮點數
>>> 7.0 / 2
3.5

lua返回的結果是跟python一樣的,所以程式碼就不給出了。雖然輸出的結果一樣,但是我們要知曉,python區分intfloat,lua都是number.

下面來看看兩者的冪運算子和對待未申明變數的區別
python:

>>> 5**2 #冪運算子 **
25 # 這裡是 int
>>> n  # 試圖訪問未申明變數
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'n' is not defined

lua:

> 5^2 --冪運算子 ^
25.0 -- 這裡雖然是number,但是是浮點數,c程式設計師懂為什麼
> n
nil

在互動模式下,python還提供了一個功能就是保留當前的計算結果,lua未提供。

>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _ #這裡的 _ 指的就是上次的計算結果12.5625
113.0625
>>> _ + 1
114.0625
  • 注:記住 python的_是隻讀的,切忌對它賦值。如果你這麼做了,那就加一句 del _

雖然python還為我們提供了強大的Decimal、Fraction和complex number,這裡就不一一介紹了。

在互動模式下兩者對字串的輸出稍顯差異
python:

>>> 'spam eggs'
'spam eggs' #這裡會有單引號括起來,表示是字串
>>> print('spam eggs') #列印函式
spam eggs
>>> s = 'First line.\nSecond line.'  # \n代表新行
>>> s  # without print(), \n is included in the output
'First line.\nSecond line.'
>>> print(s)  # with print(), \n produces a new line
First line.
Second line.

lua:

> 'spam eggs'
spam eggs -- lua的話就是普通的列印
> print('spam eggs') #列印函式
spam eggs
> print('spam eggs')
spam eggs
> s = 'First line.\nSecond line.' -- \n代表新行
> s
First line.
Second line.

對於單引號,雙引號的相互巢狀,或者反斜槓\的轉義,兩者沒有任何區別。
python:

>>> print('spam eggs')  # single quotes
spam eggs
>>> print('doesn\'t')  # use \' to escape the single quote...
doesn't
>>> print("doesn't")  # ...or use double quotes instead
doesn't
>>> print('"Yes," he said.')
"Yes," he said.
>>> print("\"Yes,\" he said.")
"Yes," he said.
>>> print('"Isn\'t," she said.')
"Isn\'t," she said.

雖然有那麼多寫法,但是我覺得,作為一名優秀的程式設計師,我們還是不要竄來竄去的,對字元使用統一的寫法,要麼用'',要麼用"",否則別人看了你的程式碼一定會頭疼的^_^

有時候我們又不想要轉義。
假如有這樣一個目錄 C:\name我們需要打印出來。

python:

>>> print("C:\name") # 結果,這裡的\n被當成是換行符了,lua也是這結果
C:\some
ame

共同的解決方法是 print("C:\\name"),不過python還提供了另一種方法就是print(r"C:\name")raw strings
python還對多行字串提供了更加方便的解決方法"""..."""或者'''...''',自動讀取換行符如果不想要換行符可以加轉義符\

python:

print("""\
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
""")
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to

下面是兩者拼接字串的區別
python:

>>> print("un" + "ium") #能拼接兩個常量字串
unium
>>> a = "un"
>>> print(a + a + "ium") #也能拼接變數(型別需要是str,否則報錯)和常量字串,lua中的加號不能拼接字串,但有其他功能
ununium
>>> print("un" "ium" "un" "ium") 
'''
自動拼接相鄰的字串,不過這個只能拼接常量字串,不能拼接變數和常量字串;但是可以用來對很長的列印資訊分行,列印結果也是單行的。lua不行
'''
uniumunium
>>> print(a*3) #這個比較厲害,可以對字串做乘法,意思就是重複字串,lua不可以
ununun

lua:

> print("un" .. "ium") -- 類似python的+,但是python不具有這個操作符
> a = "un"
> print(a .. a .. "ium") -- 類似python的+
ununium
> print(10 .. 20) -- 還能連線數字,輸出型別是string,注意點點要跟數字10分開,不然會被當成小數的。
1020
> print(10 ..20) -- 不推薦這樣寫
1020
> a = "10"
> print(a + 1) -- 當一個string加number的時候,lua會先判斷這個string能否轉換成number(tonumber函式),能就得出加出來的數,否則報錯
11.0
> a = "10a"
> print(a+1) -- 這裡就報錯了
stdin:1: attempt to perform arithmetic on a string value (global 'a')
stack traceback:
        stdin:1: in main chunk
        [C]: in ?

對字串中某個字元的讀取也不一樣,python提供的功能更強大,lua只能走string的函式
python:

>>> # 在python中索引起步是0
>>> a = "1234567"
>>> print(a[0])
1
>>> print(a[-1])
7
>>> print(a[2:4]) # : 這個符號對應的區間是:[) 前面閉區間,後面開區間
34
>>> print(a[2:0]) # 等同 print(a[-5:-7])
    #無輸出
>>> print(a[-3:-1])
56
>>> print(a[:2])
12
>>> print(a[2:])
34567
>>> a[8] # 越界訪問
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range
>>> a[-8:] # 越界,輸出全部
'1234567'
'''
對應的字串索引圖表就是
 +---+---+---+---+---+---+---+---+---+---+
     |   | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
 +---+---+---+---+---+---+---+---+---+---+
         0   1   2   3   4   5   6   7   8
-9  -8  -7  -6  -5  -4  -3  -2  -1
'''
>>> a[0] = "a" # 不能賦值
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> len(a) #檢視字串長度
7

lua:

> -- 在lua中索引起步是1,嘿嘿,區別於各種語言
> a = "1234567"
> print(string.sub(a,1)) -- 當然你要把這裡的1改成0也是可以的,不推薦
1234567
> print(string.sub(a,2,1)) -- 無輸出

> print(string.sub(a,3,3)) -- 等同python的a[2:3],python不許這種寫法:a[2:2]。
> -- 所以我們就知道了,對於lua,它的區間是:[] 前後閉區間
3
> string.sub(a,8) -- 越界了,無輸出

> string.sub(a,-8) -- 越界了,輸出全部
1234567
--[[
對應的字串索引圖表就是,
 +---+---+---+---+---+---+---+---+---+---+
     |   | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
 +---+---+---+---+---+---+---+---+---+---+
     0   1   2   3   4   5   6   7   8   9
-9  -8  -7  -6  -5  -4  -3  -2  -1
--]]
> string.len(a) --檢視字串長度
7

對於用正向索引還是負向索引看哪個用的方便吧,一般用正向的。
通過上面的比較,python對字串訪問提供的功能更多,lua要更接近C的方式一點(只能通過函式操作)。

python還有list型別,lua可以通過table的方式實現類似的功能,看例子:
python:

>>> lst = [1,4,9,16]
>>> type(lst)
<class 'list'>
>>> lst[0] # []的訪問跟上面字串的訪問一樣
1
>>> lst[1]
4
>>> lst[2]
9
>>> lst[1:10] # lua不支援
[4, 9, 16]
>>> lst[-1]
16
>>> id(lst)
35530696
>>> id(lst[:]) # 每次[]操作,返回都是新的list物件
35530888
>>> lst2 = [25,36]
>>> lst + lst2 # python還支援兩個list的串聯
[1, 4, 9, 16, 25, 36]
>>> lst[3] = 81 # list不同於str,可以賦值
>>> lst
[1, 4, 9, 81]
>>> lst.append(100) # 通過append函式追加資料
>>> lst
[1, 4, 9, 81, 100]

>>> # python不僅可以單個賦值還能區間賦值 這個lua沒有
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> # 替換成大寫
>>> letters[2:5] = ['C', 'D', 'E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> # 刪除它們
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']
>>> # 用一個空的來清空這個list
>>> letters[:] = []
>>> letters
[]
>>> len(letters) # 使用函式 len 檢視容量
0

>>> letters = [1,2,3,"a","b"] # 雖然python支援,但是我們最好不要這樣做,資料型別最好要保持一致
>>> letters
[1, 2, 3, 'a', 'b']

>>> a = ['a', 'b', 'c'] # python還支援list巢狀
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'

lua:

> lst = {1,4,9,16}
> lst
table: 00448638
> lst[1] -- lua從索引1開始
1
> lst[2]
4
> lst[3]
9
> lst[-1] -- lua的table []操作不支援負數訪問
nil
> lst1 = {25,36}
> lst + lst2 -- lua 不支援 table相加,如果要實現這個功能需要藉助table的函式,後面再說~
stdin:1: attempt to perform arithmetic on a table value (global 'lst')
stack traceback:
        stdin:1: in main chunk
        [C]: in ?
> lst[4] = 81 -- lua也可以賦值
> lst[4]
81
> #lst -- 通過 # 來取得 table 的容量
4

> letters = {1,2,3,"a","b"} -- 雖然lua可以這樣做,但是我們儘量保證我們的table資料型別一致
> letters[1]
1
> letters[4]
a

> a = {"a","b","c"} —— lua也支援table巢狀
> n = {1,2,3}
> x = {a,n}
> x[1][1]
a
> x[2][1]
1

最後我們再來看一下兩者的列印函式 print
python:

>>> help(print) # 使用help函式,我們可以看到它的文件解釋
Help on built-in function print in module builtins:

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

>>>#sep 引數表示間隔字串輸出
>>>#end 引數表示列印結束後的字串輸出
>>>#如果引數不明白,下面的例子看了就懂了
>>> print(1,2,3,4,5)
1 2 3 4 5
>>> print(1,2,3,4,5,sep=",",end=".")
1,2,3,4,5.>>>#這裡由於把end的引數改成.所以沒有回車

lua:

>-- lua 查文件 就一個 print (···),它建議我們用string.format來定製自己的列印格式,這個函式後面再細說。

> print(1,2,3,4,5) -- lua 預設分的很開
1       2       3       4       5

未完待續。。。