1. 程式人生 > 實用技巧 >Python零基礎入門第1章.環境搭建

Python零基礎入門第1章.環境搭建

基本資料型別(二)

一、序列型別

序列型別用來表示有序的元素集合。

1. 字串

python中字串用str表示,字串是使用單引號,雙引號,三引號包裹起來的字元的序列,用來表示文字資訊。

1.1 字串的定義

a = 'a'
b = "bc"
c = """hello,world"""
d = '''hello,d'''
e = """
    hello,
    world!
    """
print('a的型別為:', type(a))    # a的型別為: <class 'str'>
print('b的型別為:', type(b))    # b的型別為: <class 'str'>
print('c的型別為:', type(c))    # c的型別為: <class 'str'>
print('d的型別為:', type(d))    # d的型別為: <class 'str'>
print('e的型別為:', type(e))    # e的型別為: <class 'str'>
a的型別為: <class 'str'>
b的型別為: <class 'str'>
c的型別為: <class 'str'>
d的型別為: <class 'str'>
e的型別為: <class 'str'>

使用單引號和雙引號進行字串定義沒有任何區別,當要表示字串的單引號時用雙引號進行定義字串,反之亦然。

一對單引號或雙引號只能建立單行字串,三引號可以建立多行表示的字串。三雙引號一般用來做多行註釋,表示函式,類定義時的說明。

print('最近我看了"平凡的世界"')
print("最近我看了'平凡的世界'")
最近我看了"平凡的世界"
最近我看了'平凡的世界'
定義空字串
a = ''
print(a)

1.2 字串的索引

任何序列型別中的元素都有索引用來表示它在序列中的位置。

字串是字元的序列表示,單個字元在字串中的位置使用索引來表示,也叫下標。

索引使用整數來表示。

通過索引可以獲取字串中的單個字元

語法如下:

str[index]
s = 'hello world!'
print(s[0])
print(s[-1])
h
!

注意字串索引從0開始

1.3 字串的切片

獲取序列中的子序列叫切片。

字串的切片就是獲取字串的子串。

字串切片的語法如下:

str[start:end:step]

start表示起始索引,end表示結束索引,step

表示步長。

str[m:n:t]表示從字串索引為mn之間不包含n每隔t個字元進行切片。

step為1的時候可以省略。

特別的,當step為負數時,表示反向切片。

s = '0123456789'
print(s[1:5])  # 包頭不包尾
1234
print(s[:5])  # 從頭開始切可以省略start
01234
print(s[1:])  # 切到末尾省略end
123456789
print(s[1::2]) # 步長為2進行切片
13579
print(s[1::-2]) # 步長為負數反向切片
1
思考

獲取一個字串的逆串,例如'abc'的逆串是'cba'

1.4 字串拼接

python中可以通過+拼接兩個字串

a = 'hello'
b = ' '
c = 'world!'
print(a+b+c)
hello world!

字串和整數進行乘法運算表示重複拼接這個字串

print('*' * 10)
**********

1.5 字串常用方法

通過內建函式dir可以返回傳入其中的物件的所有方法名列表。

print(dir(str))
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

通過內建函式help可以返回傳入函式的幫助資訊。

help('abc'.replace)
Help on built-in function replace:

replace(old, new, count=-1, /) method of builtins.str instance
    Return a copy with all occurrences of substring old replaced by new.
    
      count
        Maximum number of occurrences to replace.
        -1 (the default value) means replace all occurrences.
    
    If the optional argument count is given, only the first count occurrences are
    replaced.

官方文件地址

1.6 字串和數值的相互轉化

1'1'不同,1.2'1.2'也不相同,但是它們可以相互轉化

# 整數和字串之間的轉化
int('1')
1
str(1)
'1'
# 浮點數和字串之間的轉化
float('1.2')
1.2
str(1.2)
'1.2'
# 嘗試 int('1.2')看看結果會是什麼
int('1.2')

1.7 轉義符

在需要在字元中使用特殊字元時,python 用反斜槓 \ 轉義字元。常用轉義字元如下表:

(在行尾時) 續行符
\\ 反斜槓符號
\' 單引號
\" 雙引號
\a 響鈴
\n 換行
\t 橫向製表符
\r 回車
\f 換頁
print('窗前明月光,\n疑是地上霜。')  # 輸出換行
窗前明月光,
疑是地上霜。
print('對\\錯')   # 輸出反斜槓本身
對\錯
print('\'')      # 輸出單引號本身
'

1.8 字串格式化

在實際工作中經常需要動態輸出字元。

例如,我們通過程式計算計算機的記憶體利用率,然後輸出

10:15 計算機的記憶體利用率為30%

其中下劃線內容會動態調整,需要根據程式執行結果進行填充,最終形成上述格式的字串輸出。

python支援兩種形式的字串格式化

% 字串格式化

語法格式如下:

%[(name)][flags][width][.precision]typecode
  • (name) 可選,用於選擇指定的key

  • flags 可選,可供選擇的值有,注意只有在和數值型別的typecode配合才起作用

    • +, 右對齊,正數前加正號,負數前加負號
    • -, 左對齊,正數前無符號,負數前加負號
    • 空格, 右對齊,正數前加空格,負數前加負號
    • 0, 右對齊,正數前無符號,複數前加負號;用0填充空白處
  • width,可選字串輸出寬度

  • .precision 可選,小數點後保留位數,注意只有在和數值型別的typecode配合才起作用

  • typecode必選

    • s,獲取傳入物件的字串形式,並將其格式化到指定位置
    • r,獲取傳入物件的__repr__方法的返回值,並將其格式化到指定位置
    • c,整數:將數字轉換成其unicode對應的值,10進位制範圍為 0 <= i <= 1114111(py27則只支援0-255);字元:將字元新增到指定位置
    • o,將整數轉換成 八 進製表示,並將其格式化到指定位置
    • x,將整數轉換成十六進位制表示,並將其格式化到指定位置
    • d,將整數、浮點數轉換成 十 進製表示,並將其格式化到指定位置
    • e,將整數、浮點數轉換成科學計數法,並將其格式化到指定位置(小寫e)
    • E,將整數、浮點數轉換成科學計數法,並將其格式化到指定位置(大寫E)
    • f, 將整數、浮點數轉換成浮點數表示,並將其格式化到指定位置(預設保留小數點後6位)
    • F,同上
    • g,自動調整將整數、浮點數轉換成 浮點型或科學計數法表示(超過6位數用科學計數法),並將其格式化到指定位置(如果是科學計數則是e;)`
    • G,自動調整將整數、浮點數轉換成 浮點型或科學計數法表示(超過6位數用科學計數法),並將其格式化到指定位置(如果是科學計數則是E;)`
    • %,當字串中存在格式化標誌時,需要用 %%表示一個百分號
res = '%s計算機的記憶體利用率為%s%%' % ('11:15', 75)
print(res)
# '%s'作為槽位和 % 號後提供的值按順序一一對應
11:15計算機的記憶體利用率為75%
res = '%(time)s計算機的記憶體利用率為%(percent)s%%' % {'time':'11:15', 'percent': 75}
# % 後是字典時,可以通過name指定key對應的值
print(res)
11:15計算機的記憶體利用率為75%
# 輸出兩位數的月份,例如01,02
res = '%02d' % 8
print(res)
08
# 保留2為小數
res = '%(time)s計算機的記憶體利用率為%(percent).2f%%' % {'time':'11:15', 'percent': 75.123}
print(res)
11:15計算機的記憶體利用率為75.12%
print('字串%(key)s,十進位制%(key)d,科學計數%(key)e,八進位制%(key)o,16進位制%(key)x,unicode字元%(key)c' % {'key': 65})
字串65,十進位制65,科學計數6.500000e+01,八進位制101,16進位制41,unicode字元A
format函式格式化

%的字串格式化繼承自C語言,python中給字串物件提供了一個format函式進行字串格式化,且功能更強大,並且大力推薦,所以我們要首選使用。

基本語法是:

<模板字串>.format(<逗號分隔的引數>)

在模板字串中使用{}代替以前的%作為槽位

'{}計算機的記憶體利用率為{}%'.format('11:15', 75)
'11:15計算機的記憶體利用率為75%'

當format中的引數使用位置引數提供時,{}中可以填寫引數的整數索引和引數一一對應

'{0}計算機的記憶體利用率為{1}%'.format('11:15', 75)
'11:15計算機的記憶體利用率為75%'

當format中的引數使用關鍵字引數提供時,{}中可以填寫引數名和引數一一對應

'{time}計算機的記憶體利用率為{percent}%'.format(time='11:15', percent=75)
'11:15計算機的記憶體利用率為75%'

{}中除了可以寫引數索引外,還可以填寫控制資訊來實現更多的格式化功能,語法如下

{<引數序號>:<格式控制標記>}
其中格式控制標記格式如下
[fill][align][sign][#][0][width][,][.precision][type]
  • fill 【可選】空白處填充的字元

  • align 【可選】對齊方式(需配合width使用)

    • <,內容左對齊
    • >,內容右對齊(預設)
    • =,內容右對齊,將符號放置在填充字元的左側,且只對數字型別有效。 即使:符號+填充物+數字
    • ^,內容居中
  • sign 【可選】有無符號數字

    • +,正號加正,負號加負;
    • -,正號不變,負號加負;
    • 空格 ,正號空格,負號加負;
  • # 【可選】對於二進位制、八進位制、十六進位制,如果加上#,會顯示 0b/0o/0x,否則不顯示

  • , 【可選】為數字新增分隔符,如:1,000,000

  • width 【可選】格式化位所佔寬度

  • .precision 【可選】小數位保留精度

  • type 【可選】格式化型別

    • 傳入” 字串型別 “的引數
      • s,格式化字串型別資料
      • 空白,未指定型別,則預設是None,同s
    • 傳入“ 整數型別 ”的引數
      • b,將10進位制整數自動轉換成2進製表示然後格式化
      • c,將10進位制整數自動轉換為其對應的unicode字元
      • d,十進位制整數
      • o,將10進位制整數自動轉換成8進製表示然後格式化;
      • x,將10進位制整數自動轉換成16進製表示然後格式化(小寫x)
      • X,將10進位制整數自動轉換成16進製表示然後格式化(大寫X)
    • 傳入“ 浮點型或小數型別 ”的引數
      • e, 轉換為科學計數法(小寫e)表示,然後格式化;
      • E, 轉換為科學計數法(大寫E)表示,然後格式化;
      • f , 轉換為浮點型(預設小數點後保留6位)表示,然後格式化;
      • F, 轉換為浮點型(預設小數點後保留6位)表示,然後格式化;
      • g, 自動在e和f中切換
      • G, 自動在E和F中切換
      • %,顯示百分比(預設顯示小數點後6位)
# 輸出兩位數的月份,例如01,02
res = '{:0>2}'.format(8) 
print(res)
08
# 保留2為小數
res = '{time}計算機的記憶體利用率為{percent:.2%}'.format(time='11:15', percent=0.75123)
print(res)
11:15計算機的記憶體利用率為75.12%
print('字串{key},十進位制{key:d},科學計數{key:e},八進位制{key:o},16進位制{key:x},unicode字元{key:c}'.format(key=65))
字串65,十進位制65,科學計數6.500000e+01,八進位制101,16進位制41,unicode字元A

2. 列表

python中列表(list)用來表示有序可變元素的集合,元素可以是任意資料型別。

2.1 列表的定義

列表由一對中括號進行定義,元素與元素直接使用逗號隔開。

a = []                      # 空列表
b = ["a", "b", "cde"]       # 字串列表項
c = [1, "b", "c"]           # 數字列表項    
d = [1, "b", []]            # 列表列表項
e = [1, "b", [2, "c"]]      # 列表作為列表的元素叫做列表的巢狀


print('a的型別為:', type(a))    # a的型別為: <class 'list'>
print('b的型別為:', type(b))    # b的型別為: <class 'list'>
print('c的型別為:', type(c))    # c的型別為: <class 'list'>
print('d的型別為:', type(d))    # d的型別為: <class 'list'>
print('e的型別為:', type(e))    # e的型別為: <class 'list'>
a的型別為: <class 'list'>
b的型別為: <class 'list'>
c的型別為: <class 'list'>
d的型別為: <class 'list'>
e的型別為: <class 'list'>

2.2 列表的拼接

像字串一樣,列表之間可以進行加法運算實現列表的拼接,列表可以和整數進行乘法運算實現列表的重複。

[1,2,3] +  [4,5,6]
[1, 2, 3, 4, 5, 6]
[1,2,3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

2.3 列表的索引和切片

序列的切片操作完全一致,參見字串

注意巢狀列表的元素獲取

ls = [1,2,['a','b']]
ls[2][0]
'a'

2.4 列表的常用操作

python中的列表操作非常靈活,是非常重要和經常使用的資料型別。

2.4.1 修改元素

列表的中的元素可以進行修改,只需使用索引賦值即可。

ls = [1,2,3]
ls[1] = 'a'
print(ls)
[1, 'a', 3]
2.4.2 增加元素

給列表新增元素需要使用到列表的方法

.append(el),在列表的末尾新增一個元素

ls = [1,2,3]
ls.append(4)
print(ls)
[1, 2, 3, 4]

.insert(index, el),在列表的指定索引處插入一個元素

ls = [1,2,3]
ls.insert(0,0)
print(ls)
[0, 1, 2, 3]

.extend(iterable),擴充套件列表,元素為傳入的可迭代物件中的元素

ls = [1,2,3]
ls.extend([4,5,6])
print(ls)
[1, 2, 3, 4, 5, 6]
2.4.3 刪除元素

.pop(index=-1),刪除指定索引的元素,並返回該元素,沒有指定索引預設刪除最後一個元素

ls = [1,2,3]
ls.pop()
3
print(ls)
[1, 2]
ls.pop(0)
1
print(ls)
[2]

.remove(value),從列表中刪除第一個指定的值value,如不不存在value則報錯。

ls = [1,2,3,1]
ls.remove(1)
print(ls)
[2, 3, 1]

.clear(),清空列表,原列表變成空列表

ls = [1,2,3]
ls.clear()
print(ls)
[]

2.5 列表的其他方法

.copy() 返回一個列表的淺拷貝。在講可變與不可變型別的時候再詳細討論。

.count(value),統計列表中value的出現次數

ls = [1,2,3,1]
ls.count(1)
2

.index(self, value, start=0, stop=9223372036854775807),返回列表中指定值value的第一個索引,不存在則報錯

ls = [1,2,3,1]
ls.index(1)
0
l.index(1,1)
3

.reverse(),翻轉列表元素順序

ls = [1,2,3]
ls.reverse()
print(ls)
[3, 2, 1]

.sort(key=None, reverse=False),對列表進行排序,預設按照從小到大的順序,當引數reverse=True時,從大到小。注意列表中的元素型別需要相同,否則丟擲異常。

ls = [2,1,3]
ls.sort()
print(ls)
[1, 2, 3]
# 從大到小
ls.sort(reverse=True) 
print(ls)
[3, 2, 1]
ls = [1,2,'3']
ls.sort()
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-74-edfad8e910d4> in <module>
      1 ls = [1,2,'3']
----> 2 ls.sort()


TypeError: '<' not supported between instances of 'str' and 'int'

2.6 字串和列表的轉換

字串是字元組成的序列,可以通過list函式將字串轉換成單個字元的列表。

s = 'hello world!'
ls = list(s)
print(ls)
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!']

由字元組成的列表可以通過字串的join方法進行拼接

# 接上面的案例
''.join(ls)
'hello world!'

3. 元組

元組(tuple)表示有序不可變元組的集合,元素可以是任意資料型別,可以說元組就是不可變的列表。

3.1 元組的定義

元組通過一對小括號進行定義,元組之間使用逗號隔開。

a = ()                      # 空元祖
b = ("a", "b", "cde")       # 字串
c = (1, "b", "c")           # 數字
d = (1, "b", [])            # 列表
e = (1, "b", (2, "c"))      # 元祖
f = 1,2

print('a的型別為:', type(a))    # a的型別為: <class 'tuple'>
print('b的型別為:', type(b))    # b的型別為: <class 'tuple'>
print('c的型別為:', type(c))    # c的型別為: <class 'tuple'>
print('d的型別為:', type(d))    # d的型別為: <class 'tuple'>
print('e的型別為:', type(e))    # e的型別為: <class 'tuple'>
print('f的型別為:', type(f))    # f的型別為: <class 'tuple'>
a的型別為: <class 'tuple'>
b的型別為: <class 'tuple'>
c的型別為: <class 'tuple'>
d的型別為: <class 'tuple'>
e的型別為: <class 'tuple'>
f的型別為: <class 'tuple'>

注意單元素元組的定義,一定要多加個逗號

g = ('hello')
h = ('hello',)
print('g的型別為:', type(g))    # g的型別為: <class 'str'>
print('h的型別為:', type(h))    # h的型別為: <class 'tuple'>
g的型別為: <class 'str'>
h的型別為: <class 'tuple'>

3.2 元組的索引和切片

序列的索引和切片完全一致,參加字串。

3.2 元組的常用操作

元組的元素不能修改,增加和刪除,其他操作和列表的操作一致。

元組利用不可修改的特性,應用在多變數賦值和函式多返回值上。

a, b = (1, 2)
# 經常簡寫為a, b= 1, 2

當然多變數賦值時可以使用可迭代物件,但是元組最安全,它是不可變的。

關於函式多返回值的問題我們後面再講

3.3 元組的常用方法

元組只有兩個公有方法count,index用法與列表相同。

3.4 len函式

python內建函式len可以獲取物件中包含的元素個數

s = 'hello'
ls = [1,2,3]
t = (1,2,3)
print(len(s))
print(len(ls))
print(len(t))
5
3
3

4. 可變型別與不可變型別

python中的資料型別根據底層記憶體機制分為可變和不可變兩種。

基本資料型別中可變型別有列表,集合和字典,其他為不可變型別。直觀的體現為,不可變型別資料建立後不能修改,只能重新建立。

通過內建函式hash可以對資料進行運算,凡是不可hash的都是可變型別,可以hash的是不可變型別

hash(1)
1
hash([1,2])
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-83-9ce67481a686> in <module>
----> 1 hash([1,2])


TypeError: unhashable type: 'list'

5.賦值與深淺拷貝

5.1 賦值

python是解釋型程式語言,當直譯器在碰到賦值語句時它首先會計算賦值符號右邊的表示式的值,然後再建立左邊的變數。

變數中實際儲存的是值在記憶體中的地址,引用變數時通過地址指向記憶體中的值。通過內建函式id可以檢視直譯器中變數的虛擬記憶體地址整數值。

a = 1
id(a)
4382612480

將一個變數賦值給另外一個變數時,並不會建立新的值,只是新變數會指向值的記憶體地址

a = 1
b = a
id(a) == id(b)
True

對於字串和數字這樣的不可變資料型別,當上例中的變數a自加1時,會建立一個新值重新,它不會改變原來的值。因此對變數b沒有影響。

a += 1
print(a)
print(b)
2
1

但是看下面的案例

ls = [1,2,3]
ln = ls
ls[0] = 2
print(ls)
[2, 2, 3]

會發現變數ls在修改列表的值後,變數ln的值也發生了同樣的改變,這是因為ls,ln指向相同的列表。對可變資料型別進行變數賦值時要考慮這個特性。

5.2 淺拷貝

匯入copy模組中的copy函式就是淺拷貝操作

import copy
a = 123
s = 'hello'
b = copy.copy(a)
d = copy.copy(s)
print(id(a),id(b))
print(id(s),id(d))
4382616384 4382616384
140571355341296 140571355341296

對於字串數字這種不可變資料型別來說,淺拷貝相當於變數賦值,所以變數a和b的id相等,變數s和d的id相等。

a += 1
print(a)
print(b)
124
123

對原變數的修改會建立新的值,不會影響淺拷貝生成的變數,變數a自加1後指向值124,變數b的值不變

對於可變資料型別,列表,字典,集合等淺拷貝會有不一樣的結果。

ls = [1,'2',['a','b']]
ln = copy.copy(ls)
print(id(ls),id(ln))
140571352915648 140571355343040

當對可變資料型別進行淺拷貝時,會建立一個新的資料,所以變數ls和ln的id不想等。

print(id(ls[2]),id(ln[2]))
140571355288384 140571355288384

但只會拷貝第一層,ls列表中的元素,ln中只是引用,ln中的每個對應位置指向的記憶體地址和ls相同。

ls[0] = 2
print(ls)
print(ln)
[2, '2', ['a', 'b']]
[1, '2', ['a', 'b']]

修改ls中第一個元素,因為是不可變資料型別,所以ls中第一個位置指向了新的記憶體地址,ln中的不變。

ls[2][0] = 1
print(ls)
print(ln)
[2, '2', [1, 'b']]
[1, '2', [1, 'b']]

修改ls中最後一個元素,因為是可變資料型別,所以ln中的值也發生了改變。

5.3 深拷貝

不可變資料型別的深淺拷貝一致。

複雜資料型別進行深拷貝會對資料中的所有元素完全重新複製一份,不管有多少層巢狀,互不影響。

import copy
ls = [1,2,3,['a', 'b']]
# 深拷貝使用deepcopy
ln = copy.deepcopy(ls)
ls[3][0]='b'
print(ls)
print(ln)
[1, 2, 3, ['b', 'b']]
[1, 2, 3, ['a', 'b']]