基礎語法
編碼
預設情況下,Python 3 原始碼檔案以 UTF-8 編碼,所有字串都是 unicode 字串。 當然你也可以為原始碼檔案指定不同的編碼:
# -*- coding: cp-1252 -*-
識別符號
- 第一個字元必須是字母表中字母或下劃線
_
- 識別符號的其他的部分由字母、數字和下劃線組成
- 識別符號對大小寫敏感
在 Python 3 中,可以用中文作為變數名,非 ASCII 識別符號也是允許的
Python 保留字
保留字即關鍵字,我們不能把它們用作任何識別符號名稱。Python 的標準庫提供了一個 keyword 模組,可以輸出當前版本的所有關鍵字:
>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
註釋
Python 中單行註釋以 #
開頭
多行註釋可以用多個 #
號,還有 '''
和 """
#!/usr/bin/python3
# 第一個註釋
# 第二個註釋
'''
第三個註釋
第四個註釋
'''
"""
第五個註釋
第六個註釋
"""
print("Hello, Python!")
行與縮排
Python 最具特色的就是使用縮排來表示程式碼塊,不使用大括號 {}
縮排的空格數是可變的,但是同一個程式碼塊的語句必須包含相同的縮排空格數。
以下程式碼最後一行語句縮排數的空格數不一致,會導致執行錯誤:
if True:
print("Answer")
print("True")
else:
print("Answer")
print("False") # 縮排不一致,會導致執行錯誤
報錯資訊:
IndentationError: unindent does not match any outer indentation level
多行語句
Python 通常是一行寫完一條語句,但如果語句很長,我們可以使用反斜槓 \
來實現多行語句
在 []
, {}
, 或 ()
中的多行語句,不需要使用反斜槓 \
total = item_one + \
item_two + \
item_three
total = ['item_one', 'item_two', 'item_three',
'item_four', 'item_five']
空行
函式之間或類的方法之間用空行分隔,表示一段新的程式碼的開始。類和函式入口之間也用一行空行分隔,以突出函式入口的開始。
空行與程式碼縮排不同,空行並不是 Python 語法的一部分。書寫時不插入空行,Python 直譯器執行也不會出錯。但是空行的作用在於分隔兩段不同功能或含義的程式碼,便於日後程式碼的維護或重構。
記住:空行也是程式程式碼的一部分。
同一行使用多條語句
Python 可以在同一行中使用多條語句,語句之間使用分號 ;
分割
#!/usr/bin/python3
import sys; x = 'runoob'; sys.stdout.write(x + '\n')
使用互動式命令列執行,輸出結果為:
>>> import sys; x = 'runoob'; sys.stdout.write(x + '\n')
runoob
7
此處的 7
表示字元數,runoob 有 6 個字元,\n 表示一個字元,加起來 7 個字元。
多個語句構成程式碼組
縮排相同的一組語句構成一個程式碼塊,我們稱之 程式碼組
像 if
、while
、def
和 class
這樣的複合語句,首行以關鍵字開始,以冒號 :
結束,該行之後的一行或多行程式碼構成程式碼組
我們將首行及後面的程式碼組稱為一個 子句(clause)
多個變數賦值
a = b = c = 1
a, b, c = 1, 2, "runoob"
Python3 直譯器
Linux/Unix的系統上,一般預設的 python 版本為 2.x,我們可以將 python3.x 安裝在 /usr/local/python3 目錄中。
安裝完成後,我們可以將路徑 /usr/local/python3/bin 新增到您的 Linux/Unix 作業系統的環境變數中,這樣您就可以透過 shell 終端輸入下面的命令來啟動 Python3
$ PATH=$PATH:/usr/local/python3/bin/python3 # 設定環境變數
$ python3 --version
Python 3.4.0
在 Window 系統下你可以透過以下命令來設定 Python 的環境變數,假設你的 Python 安裝在 C:\Python34 下:
set path=%path%;C:\python34
互動式程式設計
Linux 下:
$ python3
Python 3.6.8 (default, Apr 19 2021, 17:20:37)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Windows 下:
> python
Python 3.10.1 (tags/v3.10.1:2cd268a, Dec 6 2021, 19:10:37) [MSC v.1929 64 bit (AMD64)] on win32
指令碼式程式設計
透過以下命令執行該指令碼:
$ python3 hello.py
在 Linux/Unix 系統中,你可以在指令碼頂部新增以下命令讓 Python 指令碼可以像 SHELL 指令碼一樣可直接執行:
#! /usr/bin/env python3
然後修改指令碼許可權,使其有執行許可權,命令如下:
$ chmod +x hello.py
執行以下命令:
./hello.py
運算子
Python 語言支援以下型別的運算子:
- 算術運算子
- 比較(關係)運算子
- 賦值運算子
- 邏輯運算子
- 位運算子
- 成員運算子
- 身份運算子
- 運算子優先順序
算術運算子
以下假設變數 a=10
,變數 b=21
:
運算子 | 描述 | 例項 |
---|---|---|
+ | 加 - 兩個物件相加 | a + b 輸出結果 31 |
- | 減 - 得到負數或是一個數減去另一個數 | a - b 輸出結果 -11 |
* | 乘 - 兩個數相乘或是返回一個被重複若干次的字串 | a * b 輸出結果 210 |
/ | 除 - x 除以 y | b / a 輸出結果 2.1 |
% | 取模 - 返回除法的餘數 | b % a 輸出結果 1 |
** | 冪 - 返回x的y次冪 | a**b 為 10 的21次方 |
// | 取整除 - 向下取接近商的整數 | >>> 9//2 4 >>> -9//2 -5 |
#!/usr/bin/python3
a = 21
b = 10
c = 0
print("a 的值位:", a) # 21
print("b 的值位:", b) # 10
c = a + b
print("a + b 的值為:", c) # 31
c = a - b
print("a - b 的值為:", c) # 11
c = a * b
print("a * b 的值為:", c) # 210
c = a / b
print("a / b 的值為:", c) # 2.1
c = a % b
print("a % b 的值為:", c) # 1
# 修改變數 a 、b 、c
a = 2
b = 3
c = a ** b
print("a ** b 的值為:", c) # 8
a = 10
b = 5
c = a // b
print("a // b 的值為:", c) # 2
比較運算子
以下假設變數 a 為 10 ,變數 b 為 20 :
運算子 | 描述 | 例項 |
---|---|---|
== | 等於 - 比較物件是否相等 | (a == b) 返回 False |
!= | 不等於 - 比較兩個物件是否不相等 | (a != b) 返回 True |
> | 大於 - 返回 x 是否大於 y | (a > b) 返回 False |
< | 小於 - 返回 x 是否小於 y 。所有比較運算子返回 1 表示真,返回0表示假。這分別與特殊的變數 True 和 False 等價。注意,這些變數名的大寫。 | (a < b) 返回 True |
>= | 大於等於 - 返回 x 是否大於等於 y | (a >= b) 返回 False |
<= | 小於等於 - 返回 x 是否小於等於 y | (a <= b) 返回 True |
賦值運算子
以下假設變數 a 為 10 ,變數 b 為 20 :
運算子 | 描述 | 例項 |
---|---|---|
= | 簡單的賦值運算子 | c = a + b 將 a + b 的運算結果賦值為 c |
+= | 加法賦值運算子 | c += a 等效於 c = c + a |
-= | 減法賦值運算子 | c -= a 等效於 c = c - a |
*= | 乘法賦值運算子 | c *= a 等效於 c = c * a |
/= | 除法賦值運算子 | c /= a 等效於 c = c / a |
%= | 取模賦值運算子 | c %= a 等效於 c = c % a |
**= | 冪賦值運算子 | c **= a 等效於 c = c ** a |
//= | 取整除賦值運算子 | c //= a 等效於 c = c // a |
:= | 海象運算子,可在表示式內部為變數賦值。Python3.8 版本新增運算子 | 在這個示例中,賦值表示式可以避免呼叫 len() 兩次:if (n := len(a)) > 10: print(f"List is too long ({n} elements, expected <= 10)") |
位運算子
按位運算子是把數字看作二進位制來進行計算的。Python中的按位運演算法則如下:
下表中變數 a 為 60,b 為 13二進位制格式如下:
a = 0011 1100
b = 0000 1101
-----------------
a&b = 0000 1100
a|b = 0011 1101
a^b = 0011 0001
~a = 1100 0011
運算子 | 描述 | 例項 |
---|---|---|
& | 按位與運算子:參與運算的兩個值,如果兩個相應位都為 1 ,則該位的結果為 1 ,否則為 0 | (a & b) 輸出結果 12 ,二進位制解釋: 0000 1100 |
| | 按位或運算子:只要對應的二個二進位有一個為 1 時,結果位就為 1 | (a | b) 輸出結果 61 ,二進位制解釋: 0011 1101 |
^ | 按位異或運算子:當兩對應的二進位相異時,結果為 1 | (a ^ b) 輸出結果 49 ,二進位制解釋: 0011 0001 |
~ | 按位取反運算子:對資料的每個二進位制位取反,即把 1 變為 0 ,把 0 變為 1。~x 類似於 -x-1 | (~a) 輸出結果 -61 ,二進位制解釋: 1100 0011, 在一個有符號二進位制數的補碼形式。 |
<< | 左移動運算子:運算數的各二進位全部左移若干位,由 << 右邊的數指定移動的位數,高位丟棄,低位補 0 |
a << 2 輸出結果 240 ,二進位制解釋: 1111 0000 |
>> | 右移動運算子:把 >> 左邊的運算數的各二進位全部右移若干位, >> 右邊的數指定移動的位數 |
a >> 2 輸出結果 15 ,二進位制解釋: 0000 1111 |
邏輯運算子
Python 語言支援邏輯運算子,以下假設變數 a 為 10 ,b為 20 :
運算子 | 邏輯表示式 | 描述 | 例項 |
---|---|---|---|
and | x and y | 布林"與" - 如果 x 為 False,x and y 返回 x 的值,否則返回 y 的計算值。 | (a and b) 返回 20 |
or | x or y | 布林"或" - 如果 x 是 True,它返回 x 的值,否則它返回 y 的計算值。 | (a or b) 返回 10 |
not | not x | 布林"非" - 如果 x 為 True,返回 False 。如果 x 為 False,它返回 True | not(a and b) 返回 False |
成員運算子
除了以上的一些運算子之外,Python 還支援成員運算子,測試例項中包含了一系列的成員,包括字串,列表或元組。
運算子 | 描述 | 例項 |
---|---|---|
in | 如果在指定的序列中找到值返回 True ,否則返回 False | x 在 y 序列中 , 如果 x 在 y 序列中返回 True |
not in | 如果在指定的序列中沒有找到值返回 True ,否則返回 False | x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True |
#!/usr/bin/python3
a = 10
b = 20
list = [1, 2, 3, 4, 5]
if (a in list):
print("1 - 變數 a 在給定的列表中 list 中")
else:
print("1 - 變數 a 不在給定的列表中 list 中") # true
if (b not in list):
print("2 - 變數 b 不在給定的列表中 list 中") # true
else:
print("2 - 變數 b 在給定的列表中 list 中")
# 修改變數 a 的值
a = 2
if (a in list):
print("3 - 變數 a 在給定的列表中 list 中") # true
else:
print("3 - 變數 a 不在給定的列表中 list 中")
身份運算子
身份運算子用於比較兩個物件的儲存單元
運算子 | 描述 | 例項 |
---|---|---|
is | is 是判斷兩個識別符號是不是引用自一個物件 | x is y , 類似 id(x) == id(y) , 如果引用的是同一個物件則返回 True,否則返回 False |
is not | is not 是判斷兩個識別符號是不是引用自不同物件 | x is not y , 類似 id(x) != id(y)。如果引用的不是同一個物件則返回結果 True,否則返回 False |
id()
函式用於獲取物件記憶體地址
#!/usr/bin/python3
a = 20
b = 20
if (a is b):
print("1 - a 和 b 有相同的標識") # true
else:
print("1 - a 和 b 沒有相同的標識")
if (id(a) == id(b)):
print("2 - a 和 b 有相同的標識") # true
else:
print("2 - a 和 b 沒有相同的標識")
# 修改變數 b 的值
b = 30
if (a is b):
print("3 - a 和 b 有相同的標識")
else:
print("3 - a 和 b 沒有相同的標識") # true
if (a is not b):
print("4 - a 和 b 沒有相同的標識") # true
else:
print("4 - a 和 b 有相同的標識")
is
與 ==
區別:is
用於判斷兩個變數引用物件是否為同一個, ==
用於判斷引用變數的值是否相等
運算子優先順序
以下表格列出了從最高到最低優先順序的所有運算子, 相同單元格內的運算子具有相同優先順序。
運算子 | 描述 |
---|---|
(expressions...) , [expressions...] , {key: value...} , {expressions...} |
圓括號的表示式 |
x[index] , x[index:index] , x(arguments...) , x.attribute |
讀取,切片,呼叫,屬性引用 |
await x |
await 表示式 |
** |
乘方(指數) |
+x , -x , ~x |
正,負,按位非 NOT |
* , @ , / , // , % |
乘,矩陣乘,除,整除,取餘 |
+ , - |
加和減 |
<< , >> |
移位 |
& |
按位與 AND |
^ |
按位異或 XOR |
| |
按位或 OR |
in , not in , is , is not , < , <= , > , >= , != , == |
比較運算,包括成員檢測和標識號檢測 |
not x |
邏輯非 NOT |
and |
邏輯與 AND |
or |
邏輯或 OR |
if -- else |
條件表示式 |
lambda |
lambda 表示式 |
:= |
賦值表示式 |
Pyhton3 已不支援 <>
運算子,可以使用 !=
代替
條件控制
if 語句
Python 中用 elif
代替了 else if
,所以 if 語句的關鍵字為:if – elif – else
注意:
- 每個條件後面要使用冒號
:
,表示接下來是滿足條件後要執行的語句塊 - 使用縮排來劃分語句塊,相同縮排數的語句在一起組成一個語句塊
簡單的 if 例項:
#!/usr/bin/python3
var1 = 100
if var1: # true
print("1 - if 表示式條件為 true")
print(var1)
var2 = 0
if var2: # false
print("2 - if 表示式條件為 true")
print(var2)
print("Good bye!")
狗的年齡計算判斷:
#!/usr/bin/python3
age = int(input("請輸入你家狗狗的年齡: "))
print("")
if age <= 0:
print("你是在逗我吧!")
elif age == 1:
print("相當於 14 歲的人。")
elif age == 2:
print("相當於 22 歲的人。")
elif age > 2:
human = 22 + (age - 2) * 5
print("對應人類年齡: ", human)
### 退出提示
input("點選 enter 鍵退出")
數字的比較運算:
#!/usr/bin/python3
# 該例項演示了數字猜謎遊戲
number = 7
guess = -1
print("數字猜謎遊戲!")
while guess != number:
guess = int(input("請輸入你猜的數字:"))
if guess == number:
print("恭喜,你猜對了!")
elif guess < number:
print("猜的數字小了...")
elif guess > number:
print("猜的數字大了...")
if 巢狀
# !/usr/bin/python3
num = int(input("輸入一個數字:"))
if num % 2 == 0:
if num % 3 == 0:
print("你輸入的數字可以整除 2 和 3")
else:
print("你輸入的數字可以整除 2,但不能整除 3")
else:
if num % 3 == 0:
print("你輸入的數字可以整除 3,但不能整除 2")
else:
print("你輸入的數字不能整除 2 和 3")
match
Python中的match語句是Python 3.10及以後版本中引入的新特性,用於模式匹配。
它允許你根據物件的模式來檢查物件,並執行相應的程式碼塊。
x = 2
match x:
case 1:
print(1)
case 2:
print(2)
case _:
print('other')
迴圈語句
Python 中的迴圈語句有 for
和 while
while 迴圈
同樣需要注意冒號和縮排。另外,在 Python 中沒有 do..while
迴圈。
無限迴圈
#!/usr/bin/python3
var = 1
while var == 1: # 表示式永遠為 true
num = int(input("輸入一個數字 :"))
print("你輸入的數字是: ", num)
print("Good bye!")
無限迴圈在伺服器上客戶端的實時請求非常有用。
簡單語句組
類似 if 語句的語法,如果你的 while 迴圈體中只有一條語句,你可以將該語句與 while 寫在同一行中
#!/usr/bin/python
flag = 1
while (flag): print('歡迎訪問菜鳥教程!')
print("Good bye!")
while-else
else的下級程式碼:
沒有透過 break 退出迴圈,迴圈結束後,會執行的程式碼
num = 1
sum = 5
while num < 5:
sum += num
if sum == 10:
break
num += 1
else:
print('沒有執行break語句')
for 語句
for 迴圈可以遍歷任何可迭代物件,如一個列表或者一個字串
break 語句用於跳出當前迴圈體
#!/usr/bin/python3
sites = ["Baidu", "Google", "Runoob", "Taobao"]
for site in sites:
if site == "Runoob":
print("菜鳥教程!")
break
print("迴圈資料 " + site)
else:
print("沒有迴圈資料!")
print("完成迴圈!")
for-else
同 while-else
for i in range(5):
if i == 3:
print("Found 3, breaking the loop")
# break
print(i)
else:
print("Loop completed without breaking")
range() 函式
如果你需要遍歷數字序列,可以使用內建 range()
函式。它會生成數列
# 指定上限,下限預設 0
for i in range(5): # [0,4]
print(i)
# 指定上下限
for i in range(5, 9): # [5,8]
print(i)
# 指定步長
for i in range(0, 10, 3): # {0,3,6,9}
print(i)
# 負數
for i in range(-10, -100, -30): # {-10,-40,-70}
print(i)
結合 range()
和 len()
函式以遍歷一個序列的索引
a = ['Google', 'Baidu', 'Runoob', 'Taobao', 'QQ']
for i in range(len(a)):
print(i, a[i])
輸出結果:
0 Google
1 Baidu
2 Runoob
3 Taobao
4 QQ
使用 range()
函式來建立一個列表
print(list(range(5))) # [0, 1, 2, 3, 4]
break 和 continue 語句及迴圈中的 else 子句
break 語句可以跳出 for 和 while 的迴圈體。如果你從 for 或 while 迴圈中終止,任何對應的迴圈 else 塊將不執行。
continue 語句被用來告訴 Python 跳過當前迴圈塊中的剩餘語句,然後繼續進行下一輪迴圈。
用於查詢質數的迴圈例子:
#!/usr/bin/python3
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print(n, '等於', x, '*', n // x)
break
else:
# 迴圈中沒有找到元素
print(n, ' 是質數')
pass 語句
pass 是空語句,是為了保持程式結構的完整性。
pass 不做任何事情,一般用做佔位語句
以下例項在字母為 o
時,執行 pass 語句塊:
#!/usr/bin/python3
for letter in 'Runoob':
if letter == 'o':
pass
print('執行 pass 塊')
print('當前字母 :', letter)
print("Good bye!")
輸出結果為:
當前字母 : R
當前字母 : u
當前字母 : n
執行 pass 塊
當前字母 : o
執行 pass 塊
當前字母 : o
當前字母 : b
Good bye!
輸入和輸出
print 輸出
print 預設輸出是換行的,如果要實現不換行需要在變數末尾加上 end=""
#!/usr/bin/python3
x = "a"
y = "b"
# 換行輸出
print(x)
print(y)
print('---------')
# 不換行輸出
print(x, end=" ")
print(y, end=" ")
print()
執行結果為:
a
b
---------
a b
輸出格式美化
Python 兩種輸出值的方式: 表示式語句和 print()
函式。
第三種方式是使用檔案物件的 write()
方法,標準輸出檔案可以用 sys.stdout
引用。
如果你希望輸出的形式更加多樣,可以使用 str.format()
函式來格式化輸出值。
如果你希望將輸出的值轉成字串,可以使用 repr()
或 str()
函式來實現。
str()
: 函式返回一個使用者易讀的表達形式repr()
: 產生一個直譯器易讀的表達形式
s = 'Hello, Runoob'
print(str(s)) # Hello, Runoob
print(repr(s)) # 'Hello, Runoob'
print(str(1 / 7)) # 0.14285714285714285
x = 10 * 3.25
y = 200 * 200
s = 'x 的值為: ' + repr(x) + ', y 的值為:' + repr(y) + '...'
print(s) # x 的值為: 32.5, y 的值為:40000...
# repr() 函式可以跳脫字元串中的特殊字元
hello = 'hello, runoob\n'
hellos = repr(hello)
print(hellos) # 'hello, runoob\n'
# repr() 的引數可以是 Python 的任何物件
print(repr((x, y, ('Google', 'Runoob')))) # (32.5, 40000, ('Google', 'Runoob'))
兩種方式輸出一個平方與立方的表
for x in range(1, 11):
print(repr(x).rjust(2), repr(x * x).rjust(3), end=' ')
# 注意前一行 'end' 的使用
print(repr(x * x * x).rjust(4))
print("==============================")
for x in range(1, 11):
print('{0:2d} {1:3d} {2:4d}'.format(x, x * x, x * x * x))
字串物件的 rjust()
方法, 它可以將字串靠右, 並在左邊填充空格。
還有類似的方法, 如 ljust()
和 center()
。 這些方法並不會寫任何東西, 它們僅僅返回新的字串。
另一個方法 zfill()
, 它會在數字的左邊填充 0
,如下所示:
z = '12'.zfill(5)
print(z) # 00012
z = '-3.14'.zfill(7)
print(z) # -003.14
z = '3.14159265359'.zfill(5)
print(z) # 3.14159265359
str.format()
的基本使用如下:
print('{}網址: "{}!"'.format('菜鳥教程', 'www.runoob.com')) # 菜鳥教程網址: "www.runoob.com!"
在括號中的數字用於指向傳入物件在 format()
中的位置,如下所示:
print('{0} 和 {1}'.format('Google', 'Runoob')) # Google 和 Runoob
print('{1} 和 {0}'.format('Google', 'Runoob')) # Runoob 和 Google
如果在 format()
中使用了關鍵字引數, 那麼它們的值會指向使用該名字的引數。
print('{name}網址: {site}'.format(name='菜鳥教程', site='www.runoob.com'))
菜鳥教程網址: www.runoob.com
位置及關鍵字引數可以任意的結合:
>>> print('站點列表 {0}, {1}, 和 {other}。'.format('Google', 'Runoob', other='Taobao'))
站點列表 Google, Runoob, 和 Taobao。
!a
(使用 ascii()
), !s
(使用 str()
) 和 !r
(使用 repr()
) 可以用於在格式化某個值之前對其進行轉化
可選項 :
和格式識別符號可以跟著欄位名。 這就允許對值進行更好的格式化
在 :
後傳入一個整數,可以保證該域至少有這麼多的寬度。 用於美化表格時很有用。
如果你有一個很長的格式化字串,而你不想將它們分開, 那麼在格式化時透過變數名而非位置會是很好的事情。
最簡單的就是傳入一個字典, 然後使用方括號 []
來訪問鍵值
也可以透過在 table 變數前使用 **
來實現相同的功能:
import math
print('常量 PI 的值近似為: {}。'.format(math.pi)) # 常量 PI 的值近似為: 3.141592653589793。
# !r 使用 repr()
print('常量 PI 的值近似為: {!r}。'.format(math.pi)) # 常量 PI 的值近似為: 3.141592653589793。
# 可選項 : 和格式識別符號可以跟著欄位名
print('常量 PI 的值近似為 {0:.3f}。'.format(math.pi)) # 常量 PI 的值近似為 3.142。
# 在 : 後傳入一個整數, 可以保證該域至少有這麼多的寬度
table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
for name, number in table.items():
print('{0:10} ==> {1:10d}'.format(name, number))
"""
Google ==> 1
Runoob ==> 2
Taobao ==> 3
"""
# 傳入一個字典, 然後使用方括號 [] 來訪問鍵值
table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
print('Runoob: {0[Runoob]:d}; Google: {0[Google]:d}; Taobao: {0[Taobao]:d}'.format(table)) # Runoob: 2; Google: 1; Taobao: 3
# 也可以透過在 table 變數前使用 ** 來實現相同的功能
table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
print('Runoob: {Runoob:d}; Google: {Google:d}; Taobao: {Taobao:d}'.format(**table)) # Runoob: 2; Google: 1; Taobao: 3
老版本的字串格式化
%
運算子也可以實現字串格式化。 它將左邊的引數作為類似 sprintf()
式的格式化字串,而將右邊的代入,然後返回格式化後的字串
import math
print('常量 PI 的值近似為:%5.3f。' % math.pi) # 常量 PI 的值近似為:3.142。
因為 str.format()
是比較新的函式, 大多數的 Python 程式碼仍然使用 %
運算子。但是因為這種舊式的格式化最終會從該語言中移除, 應該更多的使用 str.format()
讀取鍵盤輸入
Python 提供了 input() 內建函式 從標準輸入讀入一行文字,預設的標準輸入是鍵盤。
#!/usr/bin/python3
str = input("請輸入:")
print("你輸入的內容是: ", str)
名稱空間和作用域
名稱空間
名稱空間(Namespace) 是從名稱到物件的對映,大部分的名稱空間都是透過 Python 字典來實現的。
名稱空間提供了在專案中避免名字衝突的一種方法。各個名稱空間是獨立的,沒有任何關係的,所以一個名稱空間中不能有重名,但不同的名稱空間是可以重名而沒有任何影響。
一般有三種名稱空間:
- 內建名稱(built-in names), Python 語言內建的名稱,比如函式名 abs、char 和異常名稱 BaseException、Exception 等等。
- 全域性名稱(global names),模組中定義的名稱,記錄了模組的變數,包括函式、類、其它匯入的模組、模組級的變數和常量。
- 區域性名稱(local names),函式中定義的名稱,記錄了函式的變數,包括函式的引數和區域性定義的變數。(類中定義的也是)
名稱空間查詢順序:
假設我們要使用變數 runoob
,則 Python 的查詢順序為:區域性的名稱空間 -> 全域性名稱空間 -> 內建名稱空間
如果找不到變數 runoob
,它將放棄查詢並引發一個 NameError
異常
名稱空間的生命週期:
名稱空間的生命週期取決於物件的作用域,如果物件執行完成,則該名稱空間的生命週期就結束。
因此,我們無法從外部名稱空間訪問內部名稱空間的物件。
# var1 是全域性名稱
var1 = 5
def some_func():
# var2 是區域性名稱
var2 = 6
def some_inner_func():
# var3 是內嵌的區域性名稱
var3 = 7
作用域
作用域就是一個 Python 程式可以直接訪問名稱空間的正文區域。
在一個 python 程式中,直接訪問一個變數,會從內到外依次訪問所有的作用域直到找到,否則會報未定義的錯誤。
Python 中,程式的變數並不是在哪個位置都可以訪問的,訪問許可權決定於這個變數是在哪裡賦值的。
變數的作用域決定了在哪一部分程式可以訪問哪個特定的變數名稱。Python 的作用域一共有4種,分別是:
有四種作用域:
- L(Local):最內層,包含區域性變數,比如一個函式/方法內部。
- E(Enclosing):包含了非區域性(non-local) 也非全域性(non-global) 的變數。比如兩個巢狀函式,一個函式(或類) A 裡面又包含了一個函式 B ,那麼對於 B 中的名稱來說 A 中的作用域就為 nonlocal
- G(Global):當前指令碼的最外層,比如當前模組的全域性變數。
- B(Built-in): 包含了內建的變數/關鍵字等,最後被搜尋。
規則順序: L –> E –> G –> B
在區域性找不到,便會去區域性外的區域性找(例如閉包),再找不到就會去全域性找,再者去內建中找。
g_count = 0 # 全域性作用域
def outer():
o_count = 1 # 閉包函式外的函式中
def inner():
i_count = 2 # 區域性作用域
內建作用域是透過一個名為 builtin
的標準模組來實現的,但是這個變數名自身並沒有放入內建作用域內,所以必須匯入這個檔案才能夠使用它。在 Python3.0 中,可以使用以下的程式碼來檢視到底預定義了哪些變數:
>>> import builtins
>>> dir(builtins)
Python 中只有模組(module),類(class)以及函式(def、lambda)才會引入新的作用域,其它的程式碼塊(如 if/elif/else/、try/except、for/while等)是不會引入新的作用域的,也就是說這些語句內定義的變數,外部也可以訪問
>>> if True:
... msg = 'I am from Runoob'
...
>>> msg
'I am from Runoob'
例項中 msg 變數定義在 if 語句塊中,但外部還是可以訪問的。
如果將 msg 定義在函式中,則它就是區域性變數,外部不能訪問
全域性變數和區域性變數
定義在函式內部的變數擁有一個區域性作用域,定義在函式外的擁有全域性作用域。
區域性變數只能在其被宣告的函式內部訪問,而全域性變數可以在整個程式範圍內訪問。呼叫函式時,所有在函式內宣告的變數名稱都將被加入到作用域中
#!/usr/bin/python3
total = 0 # 這是一個全域性變數
# 可寫函式說明
def sum(arg1, arg2):
# 返回2個引數的和."
total = arg1 + arg2 # total在這裡是區域性變數.
print("函式內是區域性變數 : ", total) # 30
return total
# 呼叫sum函式
sum(10, 20)
print("函式外是全域性變數 : ", total) # 0
global 和 nonlocal 關鍵字
當內部作用域想修改外部作用域的變數時,就要用到 global
和 nonlocal
關鍵字了。
#!/usr/bin/python3
num = 1
def fun1():
global num # 需要使用 global 關鍵字宣告
print(num)
num = 123
print(num)
fun1()
print(num)
輸出結果:
1
123
123
如果要修改巢狀作用域(enclosing 作用域,外層非全域性作用域)中的變數則需要 nonlocal
關鍵字了
#!/usr/bin/python3
def outer():
num = 10
def inner():
nonlocal num # nonlocal關鍵字宣告
num = 100
print(num)
inner()
print(num)
outer()
輸出結果:
100
100
有一種特殊情況:
#!/usr/bin/python3
a = 10
def test():
a = a + 1
print(a)
test()
以上程式執行,報錯資訊如下:
Traceback (most recent call last):
File "test.py", line 7, in <module>
test()
File "test.py", line 5, in test
a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment
錯誤資訊為區域性作用域引用錯誤,因為 test 函式中的 a 使用的是區域性,未定義,無法修改。