天天看點

Python程式設計-資料類型方法

本文介紹python程式設計中的資料類型及方法

一、進制簡介

進制也就是進位制,是人們規定的一種進位方法。對于任何一種進制---X進制,就表示某一位置上的數運算時是逢X進一位。十進制是逢十進一,十六進制是逢十六進一,二進制就是逢二進一,以此類推,x進制就是逢x進位。

1.位和位元組

位(bit)表示二進制位。位是計算機内部資料儲存的最小機關,11010100是一個8位二進制數。

位元組(byte)習慣上用大寫的“B”表示。位元組是計算機中資料處理的基本機關。計算機中以位元組為機關存儲和解釋資訊,規定一個位元組由八個二進制位構成,即1個位元組等于8個比特(1Byte=8bit)。

八位二進制數最小為00000000,最大為11111111;通常1個位元組可以存入一個ASCII碼,2個位元組可以存放一個漢字國标碼。

(1) bit:位
    一個二進制資料0或1,是1bit;
(2) byte:位元組
    1 byte = 8 bit
(3) 一個英文字元占一個位元組;
    1 字母 = 1 byte = 8 bit
(4) 一個漢字占2個位元組;
    1 漢字 = 2 byte = 16 bit
           

GBK:一個漢字占用兩個位元組,GB18030編碼向下相容GBK和GB2312。

UTF-8:一個漢字占用3個位元組

每種編碼都有自己的碼表,是以編碼規則是不一樣的。

2.二進制

二進制是計算技術中廣泛采用的一種數制。二進制資料是用0和1兩個數位來表示的數。它的基數為2,進位規則是“逢二進一”。

資料在計算機中主要是以補碼的形式存儲的。計算機中的二進制則是一個非常微小的開關,用“開”來表示1,“關”來表示0。

二進制就是等于2時就要進位。

0=00000000

1=00000001

2=00000010

3=00000011

4=00000100

5=00000101

6=00000110

7=00000111

8=00001000

9=00001001

10=00001010

3.十進制

十進制基于位進制和十進位兩條原則,即所有的數字都用10個基本的符号表示,滿十進一,同時同一個符号在不同位置上所表示的數值不同,符号的位置非常重要。基本符号是0到9十個數字。

0 1 2 3 4 5 6 7 8 9

4.十六進制

十六進制是計算機中資料的一種表示方法。同我們日常生活中的表示法不一樣。它由0-9,A-F組成,字母不區分大小寫。與10進制的對應關系是:0-9對應0-9;A-F對應10-15。

0 1 2 3 4 5 6 7 8 9 A B C D E F

5.各進制對照表
Python程式設計-資料類型方法

二、字元串str

1.類和對象

在python中,一個對象的特征也稱為屬性(attribute)。它所具有的行為也稱為方法(method)

結論:對象=屬性+方法

在python中,把具有相同屬性和方法的對象歸為一個類(class)。

類是對象的抽象化,對象是類的執行個體化。類不代表具體的事物,而對象表示具體的事物。

類是抽象的,不占用記憶體,而對象是具體的,占用存儲空間。類是用于建立對象的藍圖,它是一個包括在特定類型的對象中的方法和變量的模闆。

Python程式設計-資料類型方法

打個比方:

智能手機就是一個類(class),它是某類對象的統稱,而你手上的這部iPhone7就是從屬于智能手機這個類的一個具體執行個體/對象(object)。智能手機都會有個電池容量的參數(智能手機這個類的域或類變量),智能手機的電池容量除以充電功率可得充滿電需要的時長(這一行為稱為智能手機這個類的方法)具體到你的這部iPhone7也有它對應的電池容量(對象的域或執行個體變量),相應的:這部iPhone7的電池容量除以它的充電器功率也就得到它充滿電需要的時間(對象可調用從屬的那個類的方法)再具體到張三的那部sumsung S7,同樣可以調用智能手機這個類的域和方法,得到那部S7的目标值。

2.字元串首字母大寫,其他變成小寫

string.capitalize()

自身不變,會生成一個新的值

name = 'toNg'
v = name.capitalize() # 自動找到name關聯的str類,執行其中的capitalize技能
print(name)
print(v)
           
運作結果:
toNg
Tong
           
3.将所有大小寫都變小寫

string.casefold()

name = 'ToNg'
v = name.casefold()
print(name)
print(v)
           
運作結果:
ToNg
tong
           

string.lower()

效果與上面的一樣。

隻不過:

python 3.3引入了string.casefold方法,對Unicode(其他語言:德語...)的時候用casefold,lower() 隻對 ASCII 也就是 'A-Z'有效,但是其它一些語言裡面存在小寫的情況就沒辦法了。

例如:德語中

s = 'ß'
a = s.lower() #  'ß'
b = s.casefold() # 'ss'
print(a)
print(b)
           
運作結果:
ß
ss
           
4.文本格式化

(1)文本居中

string.center(width, fillchar=None)

參數1: 表示總長度

參數2:空白處填充的字元(長度為1)

name = 'tong'
v = name.center(20)
print(v)
v = name.center(20,'行')
print(v)
           
運作結果:
        tong        
行行行行行行行行tong行行行行行行行行
           

(2)文本左對齊并填充右邊部分(長度包含前面的值)

string.ljust(width, fillchar=None)

name = 'tong'
v = name.ljust(20)
print(v)
v = name.ljust(20,'*')
print(v)
           
運作結果:
tong                
tong****************
           

(3)文本右對齊并填充左邊部分(長度包含後面的值)

string.rjust(width, fillchar=None)

name = 'tong'
v = name.rjust(20)
print(v)
v = name.rjust(20,'*')
print(v)
           
運作結果:
                tong
****************tong
           
5.表示傳入值在字元串中出現的次數

string.count(sub, start=None, end=None)

參數1: 要查找的值(子序列)

參數2: 起始位置(索引)

參數3: 結束位置(索引)

name = "alexasdfdsafsdfasdfaaaaaaaa"
v = name.count('a')
print(v)
v = name.count('df',0,15)
print(v)
           
運作結果:
12
2
           
6.是否以xx開頭或結尾

string.startswith(prefix, start=None, end=None)

string.endswith(suffix, start=None, end=None)

參數1:需要檢查的字元串

參數2:設定字元串檢測的起始位置

參數3:設定字元串檢測的結束位置

name = 'tong'
v1 = name.startswith('to')
print(v1)
v2 = name.endswith('g')
print(v2)
v3 = name.startswith('c')
print(v3)
           
運作結果:
True
True
False
           
7.指定的編碼格式編碼字元串

string.encode(encoding='UTF-8',errors='strict')

參數1:要使用的編碼,如"UTF-8、GBK"

參數2:設定不同錯誤的處理方案。預設為 'strict',意為編碼錯誤引起一個UnicodeError。 其他可能的值有'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace'以及通過codecs.register_error() 注冊的任何值。

name = '曉達'
v = name.encode(encoding='utf-8',errors='strict')
print(v)
a = name.encode(encoding='gbk',errors='strict')
print(a)
           
運作結果:
b'\xe6\x99\x93\xe8\xbe\xbe'
b'\xcf\xfe\xb4\xef'
           
8.找到制表符\t,進行替換(長度包含前面的值)

string.expendtabs(tabsize=8)

name = "al\te\tx\nalex\tuu\tkkk"
v = name.expandtabs(20)
print(v)
           
運作結果:
al                  e                   x
alex                uu                  kkk
           
9.找到指定子序列的索引位置:不存在傳回-1

string.find(sub, start=None, end=None)

存在傳回索引位置,不存在傳回-1

string.index(sub, start=None, end=None)

存在傳回索引位置,不存在報錯

name = 'alex'
v = name.find('o')
print(v)
a = name.find('e')
print(a)
b = name.index('e')
print(b)
c = name.index('t')
print(c)
           
運作結果:
-1
2
2
Traceback (most recent call last):
  File "E:/s17/day02/test.py", line 10, in <module>
    c = name.index('t')
ValueError: substring not found
           
10.字元串格式化

string.format(*args, **kwargs)

string.format_map(mapping)

根據索引位置
tpl = "我是:{0};年齡:{1};性别:{2}"
v = tpl.format("李傑",19,'都行')
print(v)

根據變量名
tpl = "我是:{name};年齡:{age};性别:{gender}"
v = tpl.format(name='李傑',age=19,gender='随意')
print(v)

根據KV映射關系
tpl = "我是:{name};年齡:{age};性别:{gender}"
v = tpl.format_map({'name':"李傑",'age':19,'gender':'中'})
print(v)
           
運作結果:
我是:李傑;年齡:19;性别:都行
我是:李傑;年齡:19;性别:随意
我是:李傑;年齡:19;性别:中
           
11.檢測函數

(1)檢測字元串是否由字母和數字、漢字組成

string.isalnum()

如果string至少有一個字元并且所有字元都是字母或數字則傳回 True,否則傳回 False

name  = 'alex8漢子'
v = name.isalnum()
name1  = 'alex8..*漢子'
v1 = name1.isalnum()
print(v1)
           
運作結果:
True
False
           

(2)檢測字元串是否隻由字母組成

string.isalpha()

如果字元串至少有一個字元并且所有字元都是字母則傳回 True,否則傳回 False

name  = 'alex'
name1  = 'alex8..*漢子'
v1 = name.isalpha()
print(v1)
v2 = name1.isalpha()
print(v2)
           
運作結果:
True
False
           

(3)判斷是否是數字

string.isdecimal()

string.isdigit()

string.isnumeric()

num = '②' 
v1 = num.isdecimal() # '123' 隻能識别阿拉伯數字
v2 = num.isdigit()   # '123','②' 可識别特殊數字格式
v3 = num.isnumeric() # '123','二','②' 可識别漢字,及特殊數字格式
print(v1,v2,v3)
           
運作結果:
False True True
           

(4)判斷字元串是否是合法的辨別符,字元串僅包含中文字元合法,實際上這裡判斷的是變量名是否合法

string.isidentifier()

n = 'name'
v = n.isidentifier()
print(v)
n = '仝曉達'
v = n.isidentifier()
print(v)
n = '9xiaoda'
v = n.isidentifier()
print(v)
           
運作結果:
True
True
False
           

(5)是否全部是大寫或小寫

string.isupper()

string.islower()

name = "ALEX"
v = name.isupper()
print(v)
name1 = "tong"
v1 = name1.islower()
print(v1)
           
運作結果:
True
True
           

(6)判斷字元串中所有字元是否是可見狀态

string.isprintable()

name = "釣魚要釣刀魚,\n刀魚要到島上釣"
v = name.isprintable()
print(v)
           
運作結果:
False
           

(7)字元串中如果至少有一個字元,并且全部為空格時傳回為True

string.isspace()

name = 'tong '
v = name.isspace()
print(v)
name1 = '    '
v1 = name1.isspace()
print(v1)
           
運作結果:
False
True
           
12.全部變大寫

string.upper()

name = 'alex'
v = name.upper()
print(v)
           
運作結果:
ALEX
           
13.将序列中的元素以指定的字元連接配接生成一個新的字元串

string.join(iterable)

傳回通過指定字元連接配接序列中元素後生成的新字元串

name = 'alex'
v = "_".join(name) # 内部循環每個元素
print(v)
name_list = ['海峰','杠娘','李傑','李泉']
v = "搞".join(name_list)
print(v)
           
運作結果:
a_l_e_x
海峰搞杠娘搞李傑搞李泉
           
14.對應關系 + 翻譯

string.maketrans(*args, **kwargs)

用于建立字元映射的轉換表,對于接受兩個參數的最簡單的調用方式,第一個參數是字元串,表示需要轉換的字元,第二個參數也是字元串表示轉換的目标。

string.translate(table)

根據參數table給出的表(包含256個字元)轉換字元串的字元

m = str.maketrans('aeiou','12345') # 對應關系
print(m)
name = "akpsojfasdufasdlkfj8ausdfakjsdfl;kjer09asdf"
v = name.translate(m) # 翻譯
print(v)
           
運作結果:
{97: 49, 111: 52, 117: 53, 101: 50, 105: 51}
1kps4jf1sd5f1sdlkfj815sdf1kjsdfl;kj2r091sdf
           
15.分割元素

string.partition(sep)

根據指定字元串來分割原字元串,并将指定字元串添加進原字元串内

string.split(sep=None, maxsplit=-1)

指定分隔符對字元串進行切片,可指定分割次數

content = "李泉SB劉康SB劉一"
v = content.partition('SB') # partition
print(v)
v1 = content.split('SB')
print(v1)
v2 = content.split('SB',1)
print(v2)
           
運作結果:
('李泉', 'SB', '劉康SB劉一')
['李泉', '劉康', '劉一']
['李泉', '劉康SB劉一']
           
16.替換字元串

string.replace(old, new, count=None)

content = "李泉SB劉康SB劉浩SB劉一"
v = content.replace('SB','Love')
print(v)
v = content.replace('SB','Love',1)
print(v)
           
運作結果:
李泉Love劉康Love劉浩Love劉一
李泉Love劉康SB劉浩SB劉一
           
17.移除空白,\n,\t,自定義去掉指定字元串

string.strip(chars=None)

name = ' alex\t'
v = name.strip() # 空白,\n,\t
print(v)
name1 = ' alex tong eric'
v1 = name1.strip('eric') # 自定義
print(v1)
           
運作結果:
alex
 alex tong 
           
18.大小寫轉換

string.swapcase()

name = "Alex"
v = name.swapcase()
print(v)
           
運作結果:
aLEX
           
19.填充0

string.zfill(width)

name = "alex"
v = name.zfill(20)
print(v)
           
運作結果:
0000000000000000alex
           
20.标題格式化

string.title()

string.istitle()

判斷是否為标題

傳回字元串内所有首字母均變為大寫

v = "this is string example....wow!!!"
a = v.title()
print(a)
           
運作結果:
This Is String Example....Wow!!!
           

三、整數int

1.目前整數的二進制表示,最少位數

int.bit_length()

age = 4 # 100
print(age.bit_length())
           
運作結果:
3
           
2. 擷取目前資料的位元組表示

int.to_bytes(length, byteorder, *args, **kwargs)

age = 15
v = age.to_bytes(10,byteorder='big')
v1 = age.to_bytes(10,byteorder='little')
print(v)
print(v1)
           
運作結果:
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f'
b'\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00'
           

四、布爾值bool

v = 0

v = ""

v = []

以上均為:False 其他情況為:True

五、清單list

1.追加
user_list = ['李泉','劉一','劉康','豆豆','小龍']
user_list.append('劉銘')
print(user_list)
           
運作結果:
['李泉', '劉一', '劉康', '豆豆', '小龍', '劉銘']
           
2. 清空
user_list = ['李泉','劉一','劉康','豆豆','小龍']
user_list.clear()
print(user_list)
           
運作結果:
[]
           
3. 拷貝(淺拷貝)
user_list = ['李泉','劉一','劉康','豆豆','小龍']
v = user_list.copy()
print(v)
print(user_list)
           
運作結果:
['李泉', '劉一', '劉康', '豆豆', '小龍']
['李泉', '劉一', '劉康', '豆豆', '小龍']
           
4. 計數
user_list = ['李泉','劉一','李泉','劉康','豆豆','小龍']
v = user_list.count('李泉')
print(v)
           
運作結果:
2
           
5. 擴充原清單
user_list = ['李泉','劉一','李泉','劉康','豆豆','小龍']
user_list.extend(['郭少龍','郭少霞'])
print(user_list)
           
運作結果:
['李泉', '劉一', '李泉', '劉康', '豆豆', '小龍', '郭少龍', '郭少霞']
           
6. 查找元素索引,沒有則報錯
user_list = ['李泉','劉一','李泉','劉康','豆豆','小龍']
v = user_list.index('李海')
print(v)
           
運作結果:
Traceback (most recent call last):
  File "E:/s17/day02/test.py", line 4, in <module>
    v = user_list.index('李海')
ValueError: '李海' is not in list
           
7. 删除并且擷取元素 - 索引
user_list = ['李泉','劉一','李泉','劉康','豆豆','小龍']
v = user_list.pop(1)
print(v)
print(user_list)
           
運作結果:
劉一
['李泉', '李泉', '劉康', '豆豆', '小龍']
           
8. 删除 - 值
user_list = ['李泉','劉一','李泉','劉康','豆豆','小龍']
user_list.remove('劉一')
print(user_list)
           
運作結果:
['李泉', '李泉', '劉康', '豆豆', '小龍']
           
9. 翻轉
user_list = ['李泉','劉一','李泉','劉康','豆豆','小龍']
user_list.reverse()
print(user_list)
           
運作結果:
['小龍', '豆豆', '劉康', '李泉', '劉一', '李泉']
           
10. 排序: 欠參數
nums = [11,22,3,3,9,88]
print(nums)
# 排序,從小到大
nums.sort()
print(nums)
# 從大到小
nums.sort(reverse=True)
print(nums)
           
運作結果:
[11, 22, 3, 3, 9, 88]
[3, 3, 9, 11, 22, 88]
[88, 22, 11, 9, 3, 3]
           

六、range和enumrate生成序列方式

1. 請輸出1-10

2.7: 立即生成所有數字

range(1,11) # 生成 1,2,3,4,5,6,...10

3.x: 不會立即生成,隻有循環疊代時,才一個一個生成

for i in range(1,11): 
    print(i)

for i in range(1,11,2): 
    print(i)

for i in range(10,0,-1): 
    print(i)
           
2. range: 三個參數
li = ['eric','alex','tony']

range,len,li循環

for i in range(0,len(li)):
    ele = li[i]
    print(ele)

li = ['eric','alex','tony']
for j in range(0,len(li)):
    print(j+1,li[j])
           
運作結果:
eric
alex
tony
1 eric
2 alex
3 tony
           
3.enumerate額外生成一列有序的數字
li = ['eric','alex','tony']
for i,ele in enumerate(li,1):
    print(i,ele)

v = input('請輸入商品序号:')
v = int(v)
item = li[v-1]
print(item)
           
運作結果:
1 eric
2 alex
3 tony
請輸入商品序号:2
alex
           

七、元組tuple

1.元組定義
user_tuple = ('alex','eric','seven','alex')
           

元組是不可被修改的清單;不可變類型

2. 擷取個數
user_tuple = ('alex','eric','seven','alex')
v = user_tuple.count('alex')
print(v)
           
運作結果:
2
           
3.擷取值的第一個索引位置
user_tuple = ('alex','eric','seven','alex')
v = user_tuple.index('alex')
print(v)
           
運作結果:
0
           

4.額外的元組功能:

user_tuple = ('alex','eric','seven','alex')
for i in user_tuple:  # 可以for循環
    print(i)

v = user_tuple[0]  # 可以被索引

v = user_tuple[0:2]  # 可以切片
print(v)
           
運作結果:
alex
eric
seven
alex
('alex', 'eric')
           
user_tuple = ('alex','eric','seven',['陳濤','劉浩','趙芬芬'],'alex')
user_tuple[3][1] = '劉一'  # 元組不可變,但構成元組的可變元素是可變的
print(user_tuple)

li = ['陳濤','劉浩',('alex','eric','seven'),'趙芬芬']
****** 元組最後,加逗号,否則隻有一個元素時将變成字元串 ******
li = ('alex',)
print(li)
           
運作結果:
('alex', 'eric', 'seven', ['陳濤', '劉一', '趙芬芬'], 'alex')
('alex',)
           

八、字典dict

1. 清空
dic = {'k1':'v1','k2':'v2'}
dic.clear()
print(dic)
           
運作結果:
{}
           
2. 淺拷貝
dic = {'k1':'v1','k2':'v2'}
v = dic.copy()
print(v)
           
運作結果:
{'k1': 'v1', 'k2': 'v2'}
           
3. 根據key擷取指定的value;不存在則賦予新值,不報錯
dic = {'k1':'v1','k2':'v2'}
v = dic.get('k1111',1111)
print(v)
           
運作結果:
1111
           
4. 删除并擷取對應的value值
dic = {'k1':'v1','k2':'v2'}
v = dic.pop('k1')
print(dic)
print(v)
           
運作結果:

           
5. 随機删除鍵值對,并擷取到删除的鍵值
dic = {'k1':'v1','k2':'v2'}
v = dic.popitem()
print(dic)
print(v)
           
運作結果:
{'k2': 'v2'}
v1
           
dic = {'k1':'v1','k2':'v2'}
k,v = dic.popitem() # ('k2', 'v2')
print(dic)
print(k,v)
           
運作結果:
{'k2': 'v2'}
k1 v1
           
dic = {'k1':'v1','k2':'v2'}
v = dic.popitem() # ('k2', 'v2')
print(dic)
print(v[0],v[1])
           
運作結果:
{'k1': 'v1'}
k2 v2
           
6. 增加,如果存在則不做操作
dic = {'k1':'v1','k2':'v2'}
dic.setdefault('k3','v3')
print(dic)
dic = {'k1':'v1','k2':'v2'}
dic.setdefault('k1','1111111')
print(dic)
           
運作結果:
{'k1': 'v1', 'k3': 'v3', 'k2': 'v2'}
{'k1': 'v1', 'k2': 'v2'}
           
7. 批量增加或修改
dic = {'k1':'v1','k2':'v2'}
dic.update({'k3':'v3','k1':'v24'})
print(dic)
           
運作結果:
{'k3': 'v3', 'k2': 'v2', 'k1': 'v24'}
           
dic = dict.fromkeys(['k1','k2','k3'],123)
print(dic)
dic = dict.fromkeys(['k1','k2','k3'],123)
dic['k1'] = 'asdfjasldkf'
print(dic)
           
運作結果:
{'k2': 123, 'k1': 123, 'k3': 123}
{'k2': 123, 'k1': 'asdfjasldkf', 'k3': 123}
           
dic = dict.fromkeys(['k1','k2','k3'],[1,])
dic['k1'].append(222)
print(dic)
           
運作結果:
{'k2': [1, 222], 'k3': [1, 222], 'k1': [1, 222]}
           
8.額外的字典功能:
  • 字典可以嵌套
  • 字典key: 必須是不可變類型
dic = {
    'k1': 'v1',
    'k2': [1,2,3,],
    (1,2): 'lllll',
    1: 'fffffffff',
    111: 'asdf',
}
print(dic)

key:
    - 不可變
    - True,1

dic = {'k1':'v1'}
del dic['k1']

布爾值:
1 True
0 False

bool(1111)
           

九、集合set

1.集合的定義
s1 = {"alex",'eric','tony','李泉','李泉11'}
s2 = {"alex",'eric','tony','劉一'}
           

不可重複的清單;可變類型

2.s1中存在,s2中不存在
s1 = {"alex",'eric','tony','李泉','李泉11'}
s2 = {"alex",'eric','tony','劉一'}
v = s1.difference(s2)
print(v)
           
運作結果:
{'李泉11', '李泉'}
           

s1中存在,s2中不存在,然後對s1清空,然後在重新複制

s1 = {"alex",'eric','tony','李泉','李泉11'}
s2 = {"alex",'eric','tony','劉一'}
s1.difference_update(s2)
print(s1)
print(s2)
           
運作結果:
{'李泉11', '李泉'}
{'tony', 'alex', '劉一', 'eric'}
           
3.s2中存在,s1中不存在,s1中存在,s2中不存在
s1 = {"alex",'eric','tony','李泉','李泉11'}
s2 = {"alex",'eric','tony','劉一'}
v = s1.symmetric_difference(s2)
print(v)
           
運作結果:
{'李泉', '劉一', '李泉11'}
           
4. 交集
s1 = {"alex",'eric','tony','李泉','李泉11'}
s2 = {"alex",'eric','tony','劉一'}
v = s1.intersection(s2)
print(v)
           
運作結果:
{'eric', 'tony', 'alex'}
           
5. 并集
s1 = {"alex",'eric','tony','李泉','李泉11'}
s2 = {"alex",'eric','tony','劉一'}
v = s1.union(s2)
print(v)
           
運作結果:
{'李泉', 'alex', 'tony', 'eric', '李泉11', '劉一'}
           
6. 移除
s1 = {"alex",'eric','tony','李泉','李泉11'}
s1.discard('alex')
print(s1)
           
運作結果:
{'李泉', 'eric', 'tony', '李泉11'}
           
7.更新,值存在則不更新
s1 = {"alex",'eric','tony','李泉','李泉11'}
s1.update({'alex','123123','fff'})
print(s1)
           
運作結果:
{'eric', 'alex', '123123', '李泉11', '李泉', 'tony', 'fff'}
           
8.額外的集合功能:
s1 = {"alex",'eric','tony','李泉','李泉11'}
for i in s1:  # 可以使用for循環
    print(i)

s1 = {"alex",'eric','tony','李泉','李泉11',(11,22,33)}
for i in s1:  # 可以嵌套元組,不能嵌套清單
    print(i)
           

繼續閱讀