首頁 > 軟體

Python函數進階與檔案操作詳情

2022-08-17 22:02:25

一、作業回顧

1、格式化輸出與%百分號

以下結果中,可以正常輸出“50%及格”語句是(B)

A、print(“%d%及格” % (50)) => 回答大部分結果(Python這種寫法不正確)

B、print(“%d%%及格” % (50)) => 正確結果

2、字串切片

定義一個字串str1 = ‘abcdefg’,使用切片擷取字串str1[3::-2],求返回結果:(C)

C、‘db’

3、字典的定義

其實字典中的key可以是很多資料型別(不可變資料型別 => 整型、浮點型、字串、元組)

my_dict = {}
my_dict[1] = 1
my_dict['1'] = 2
my_dict[1.0] = 3
print(my_dict[1] + my_dict['1'] + my_dict[1.0])

二、參照變數與可變、非可變型別

1、參照變數

在大多數程式語言中,值的傳遞通常可以分為兩種形式“值傳遞與參照傳遞”,但是在Python中變數的傳遞基本上都是參照傳遞。

聊聊變數在記憶體底層的儲存形式

a = 10

第一步:首先在計算機記憶體中建立一個數值10(佔用一塊記憶體空間)

第二步:在棧空間中宣告一個變數,如a

第三步:把數值10的記憶體地址賦予給變數小a,形成所謂的==“參照關係”==

如何驗證Python中變數的參照關係

答:可以使用內建方法id(),其引數就是要顯示的變數資訊 => id(變數名稱)

a = 10
print(id(a))

把一個變數賦予給另外一個變數的影響

a = 10
b = a
print(id(a))
print(id(b))

執行結果:

說明:由以上執行結果可知,當我們把一個變數賦予給另外一個變數時,其兩者指向的記憶體地址相同。

就說明a和b指向了同一塊記憶體空間,原理圖如下:

思考:如果在b = a以後,我們改變了變數a的值,問變數b是否會受到影響?

# a = 10
# print(id(a))

a = 10
b = a

a = 100
print(b)  # 10 或 100

print(id(a))
print(id(b))

原理圖:

總結:不可變資料型別(數值)在賦值以後,其中一個值的改變不影響另外一個變數,因為兩者指向空間地址不同。

2、Python中可變和非可變資料型別

 問題1:在Python中一共有幾種資料型別?

答:7種,數值(int整型、float浮點型別)、bool型別(True和False)、字串型別(str)、元組(tuple 1,2,3)、列表(list [1, 2, 3])、字典(dict {key:value})、集合(set {1, 2})

在Python中,我們可以把7種資料型別分為兩大類:可變型別 + 非可變型別

① 非可變型別

數值(int整型、float浮點型別)

bool型別(True和False)

字串型別(str)

元組(tuple 1,2,3)

② 可變型別

列表(list [1, 2, 3])

字典(dict {key:value})

集合(set {1, 2})

問題2:如何判斷一個資料型別是可變型別還是非可變型別?

在Python中,可變型別與非可變型別主要是通過這個資料型別在記憶體中的表現形式來進行定義的。

① 可變型別就是在記憶體中,其記憶體地址一旦固定,其值是可以發生改變的

a = [1, 2, 3]
print(id(a))

# 向記憶體中追加新資料(對資料進行改變只能通過資料型別.方法()實現)
a.append(4)
print(id(a))

原理圖:

② 非可變型別就是在記憶體中,記憶體地址一旦固定,其值就沒辦法發生任何改變了

a = 10
print(id(a))

a = 'hello'
print(id(a))

原理圖:

3、可變型別與非可變型別在函數中的應用

可變型別

# 定義一個函數
def func(names):
    print(names)
    
# 定義一個全域性變數
names = ['張三', '李四', '王五']
# 呼叫函數
func(names)

原理圖:

綜上所述:可變型別在函數中,如果在全域性或區域性中對可變型別進行增刪改操作,其外部和內部都會受到影響。

不可變型別

# 定義一個函數
def func(num):
    num += 1
    print(num)
    
# 定義一個全域性變數
a = 10
# 呼叫函數
func(a)
# 在全域性作用域中列印a
print(a)

綜上所述:不可變型別在函數中,區域性或全域性的改變對外部和內部都沒有任何影響。

三、函數遞迴(重點難點)

1、前言

程式設計思想:如何利用數學模型,來解決對應的需求問題;然後利用程式碼實現對應的資料模

演演算法:使用程式碼實現對應的數學模型,從而解決對應的業務問題

程式 = 演演算法 + 資料結構

在我們經常使用的演演算法中,有兩種非常常用的演演算法:遞推演演算法 + 遞迴演演算法,專門用於解決一些比較複雜,但是拆分後相似度又非常高的程式。

2、遞推演演算法

遞迴演演算法:遞推演演算法是一種簡單的演演算法,即通過已知條件,利用特定條件得出中間推論,直至得到結果的演演算法。遞推又分為順推和逆推。

順推:通過最簡單的條件,然後逐步推演結果

逆推:通過結果找到規律,然後推導已知條件

遞推演演算法案例:斐波那契數列

1 1 2 3 5 8 13 21 …

① ② ③ ④ ⑤ ⑥ …

第1位為1,第2位為1,第3位為2 = 1 + 1,第4位元為3 = 2 + 1,依次類推…第n位結果為多少?

f(n) = f(n-1) + f(n-2)

提出問題:求斐波那契數列第15位的結果?

分析:f(15) = f(14) + f(13)

​ f(14) = f(13) + f(12)

​ f(13) = f(12) + f(11)

​ …

​ f(4) = f(3) + f(2) = 3 + 1

​ f(3) = f(2) + f(1) = 2

​ f(2) = 1

​ f(1) = 1

遞推演演算法:使用while迴圈或for迴圈

# 遞推演演算法:根據已知條件,求結果(或者根據結果求未知條件)
def recusive(n):
    """ 返回斐波那契數列某一位(n>=1)的結果 """
    if n == 1 or n == 2:
        return 1
    # 開始遞推f(3) = f(2) + f(1)  f(4) = f(3) + f(2) ... f(15) = f(14) + f(13)
    dict1 = {1:1, 2:1}
    for i in range(3, n+1):
        # f(3) = f(2) + f(1)
        # f(i) = f(i-1) + f(i-2)
        dict1[i] = dict1[i-1] + dict1[i-2]
    return dict1[n]

# 函數呼叫
print(recusive(15))

3、什麼是遞迴演演算法

程式呼叫自身的程式設計技巧稱為遞迴( recursion)。遞迴做為一種演演算法在程式設計語言中廣泛應用,它通常把一個大型複雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞迴策略只需少量的程式就可描述出解題過程所需要的多次重複計算,大大地減少了程式的程式碼量。

① 簡化問題:找到最優子問題(不能再小) ② 函數自己呼叫自己

def func():
    # 自己呼叫自己
    func()
    
func()

4、遞迴兩種重要的元素

遞迴有兩個非常重要的概念:

① 遞迴點:找到解決當前問題的等價函數(先解決規模比當前問題小一些的函數,依次類推,最終實現對問題的解決) => 有遞有歸

② 遞迴出口:當問題解決的時候,已經到達(必須存在)最優問題,不能再次呼叫函數了

注:如果一個遞迴函數沒有遞迴出口就變成了死迴圈

5、編寫遞迴三步走

① 明確你這個函數想要幹什麼

如:求斐波那契數列

② 尋找遞迴結束條件

如:就是在什麼情況下,遞迴會停止迴圈,返回結果

③ 找出函數的等價關係式

如:斐波那契數列,第n位 f(n) = f(n-1) + f(n-2)

案例1:使用遞迴求斐波那契數列

第一步:明確這個函數想要幹什麼(先定義出來,明確呼叫方式)

# 斐波那契數列 1 1 2 3 5 8 13 21 ...
def f(n):
    # 編寫遞迴程式碼求第n位的結果

# 呼叫函數
print(f(15))  # 610

第二步:尋找遞迴的結束條件

# 斐波那契數列 1 1 2 3 5 8 13 21 ...
def f(n):
    # 編寫遞迴程式碼求第n位的結果
    if n == 1 or n == 2:
        return 1

# 呼叫函數
print(f(15))  # 610

第三步:找出函數的等價關係式(最關鍵的一步)

# 斐波那契數列 1 1 2 3 5 8 13 21 ...
def f(n):
    # 編寫遞迴程式碼求第n位的結果
    if n == 1 or n == 2:
        return 1
    # 找出與斐波那契數列等價的關係式
    return f(n-1) + f(n-2)

# 呼叫函數
print(f(15))  # 610

案例2:使用遞迴求N的階乘(如n=100)

階乘是什麼?一個正整數的階乘(factorial)是所有小於及等於該數的正整數的積,如:n!=1×2×3×…×(n-1)×n

1! = 1

2! = 1x2 = 2

3! = 1x2x3 = 6

4! = 1x2x3x4 = 24

n!=1×2×3×…×(n-1)×n

第一步:明確這個函數要做什麼以及定義函數以及呼叫方式

def f(n):
    # 編寫遞迴條件
    
print(f(100))

第二步:尋找遞迴的結束條件

def f(n):
    # 編寫遞迴結束條件
    if n <= 2:
        return n
    # ...遞迴等式
print(f(100))

第三步:編寫遞迴等價公式(自己要呼叫自己)

等價公式 = 找規律

1! = f(1) = 1

2! = f(2) = 2

3! = f(2)x3 = 6

4! = f(3)x4 = 24

n!= f(n-1) * n

def f(n):
    # 編寫遞迴結束條件
    if n <= 2:
        return n
    # ...遞迴等式
    return f(n-1) * n
print(f(100))

案例3:面試題 => 猴子吃桃問題

猴子吃桃問題。猴子第1天摘下若干個桃子,當即吃了一半,還不過癮,又多吃了一個。第2天早上又將剩下的桃子吃掉一半,又多吃了一個。以後每天早上都吃了前一天剩下的一半另加一個。到第10天早上想再吃時,就只剩下一個桃子了。求第1天共摘了多少個桃子

第一步:確定函數主要要完成什麼功能,需要傳遞哪些引數,確認呼叫方式

def f(n):
    # 編寫遞迴程式碼

# 呼叫f函數
print(f(1))

第二步:編寫遞迴的結束條件(出口)

# 第一步:確定函數功能
def f(n):
    # 第二步:編寫遞迴結束條件(出口)
    if n == 10:
        return 1

# 呼叫函數
print(f(1))

第三步:找出與這個問題相等的等式關係

求桃子的剩餘數量?假設法:假設有10個桃子

第1天,10個桃子吃一半,10/2 = 5 + 1 = 6

第2天,4個桃子吃一半,4/2 = 2 + 1 = 3

第3天,再想吃剩1個

第n天,總剩餘桃子的數量 = (第(n+1)天桃子的剩餘桃子的數量 + 1) * 2

# 第一步:確定函數功能
def f(n):
    # 第二步:編寫遞迴結束條件(出口)
    if n == 10:
        return 1
    # 第三步:尋找與這個問題相似的等價公式
    return (f(n+1) + 1) * 2

# 呼叫函數
print(f(8))

四、lambda表示式

1、普通函數與匿名函數

在Python中,函數是一個被命名的、獨立的完成特定功能的一段程式碼,並可能給呼叫它的程式一個返回值。

所以在Python中,函數大多數是有名函數 => 普通函數。但是有些情況下,我們為了簡化程式程式碼,也可以定義匿名函數 => lambda表示式

2、lambda表示式應用場景

如果一個函數有一個返回值,並且只有一句程式碼,可以使用 lambda簡化。

3、lambda表示式基本語法

變數 = lambda 函數引數:表示式(函數程式碼 + return返回值)
# 呼叫變數
變數()

4、編寫lambda表示式

定義一個函數,經過一系列操作,最終返回100

def fn1():
    return 100

# 呼叫fn1函數
print(fn1)  # 返回fn1函數在記憶體中的地址
print(fn1())  # 代表找到fn1函數的地址並立即執行

lambda表示式進行簡化:

fn2 = lambda : 100

print(fn2)  # 返回fn2在記憶體中的地址
print(fn2())

5、編寫帶引數的lambda表示式

編寫一個函數求兩個數的和

def fn1(num1, num2):
    return num1 + num2

print(fn1(10, 20))

lambda表示式進行簡化:

fn2 = lambda num1, num2:num1 + num2

print(fn2(10, 20))

6、lambda表示式相關應用

帶預設引數的lambda表示式

fn = lambda a, b, c=100 : a + b + c
print(fn(10, 20))

不定長引數:可變引數*args

fn1 = lambda *args : args

print(fn1(10, 20, 30))

不定長引數:可變引數**kwargs

fn2 = lambda **kwargs : kwargs

print(fn2(name='Tom', age=20, address='北京市海淀區'))

帶if判斷的lambda表示式

fn = lambda a, b : a if a > b else b

print(fn(10, 20))

列表資料+字典資料排序(重點)

知識點:列表.sort(key=排序的key索引, reverse=True)

students = [
    {'name': 'Tom', 'age': 20},
    {'name': 'Rose', 'age': 19},
    {'name': 'Jack', 'age': 22}
]

# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)

# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)

# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)

執行流程:

students = [
    {'name': 'Tom', 'age': 20},
    {'name': 'Rose', 'age': 19},
    {'name': 'Jack', 'age': 22}
]

# 按name值升序排列
students.sort(key=lambda x:x['name'])
print(students)

五、Python中高階函數

1、什麼是高階函數

把函數作為引數傳入,這樣的函數稱為高階函數,高階函數是函數語言程式設計的體現。函數語言程式設計就是指這種高度抽象的程式設計正規化。

2、高階函數的由來

在Python中,abs()函數可以完成對數位求絕對值計算。

① 正數的絕對值是它本身 ② 負數的絕對值是它的相反數

abs()返回的結果都是正數

abs(-10) # 10

round()函數可以完成對數位的四捨五入計算。

round(1.2)  # 1
round(1.9)  # 2

需求:任意兩個數位,按照指定要求(① 絕對值 ② 四捨五入)整理數位後再進行求和計算。

def fn1(num1, num2):
    return abs(num1) + abs(num2)

print(fn1(-10, 10))
def fn2(num1, num2):
    return round(num1) + round(num2)

print(fn2(10.2, 6.9))

要求:我們能不能對以上進行簡化,然後合併為同一個函數 => 設計思想(高階函數)

def fn(num1, num2, f):
    # f代表要傳入的引數(引數是一個函數名,如abs或round)
    return f(num1) + f(num2)

# 絕對值求和
print(fn(-10, 10, abs))
# 四捨五入
print(fn(10.2, 6.9, round))

3、map()函數

map(func, lst),將傳入的函數變數func作用到lst變數的每個元素中,並將結果組成新的列表(Python2)/迭代器(Python3)返回。

lst = [1, 2, 3]

func函數:求某個數的平方,如輸入2返回4,輸入3返回9

map(func, lst)返回結果[1, 4, 9]

# 定義一個函數
def func(n):
    return n ** 2
# 定義一個列表
list1 = [1, 2, 3]
# 使用map對lst進行func函數操作
list2 = list(map(func, list1))
print(list2)

4、reduce()函數

reduce(func,lst),其中func必須有兩個引數。每次func計算的結果繼續和序列的下一個元素做累加計算。> 注意:reduce()傳入的引數func必須接收2個引數。

list1 = [1, 2, 3]

def func(a, b):

​ return a + b

reduce(func,lst)則把列表中的每個元素放入func中進行加工,然後進行累加操作

import functools
# 定義一個函數
def func(a, b):
    return a + b
# 定義一個列表
list1 = [10, 20, 30, 40, 50]
sums = functools.reduce(func, list1)
print(sums)

5、filter()函數

filter(func, lst)函數用於過濾序列, 過濾掉不符合條件的元素, 返回一個 filter 物件。如果要轉換為列表, 可以使用 list() 來轉換。

# 定義一個函數(獲取所有的偶數)
def func(n):
   return n % 2 == 0
# 定義一個序列
list1 = [1, 2, 3, 4, 5, 6, 7, 8]
# 呼叫filter函數進行過濾操作
result = filter(func, list1)
print(list(result))

六、檔案的概念

1、什麼是檔案

記憶體中存放的資料在計算機關機後就會消失。要長久儲存資料,就要使用硬碟、光碟、U 盤等裝置。為了便於資料的管理和檢索,引入了==“檔案”==的概念。

一篇文章、一段視訊、一個可執行程式,都可以被儲存為一個檔案,並賦予一個檔名。作業系統以檔案為單位管理磁碟中的資料。一般來說,檔案可分為文字檔案、視訊檔、音訊檔、影象檔案、可執行檔案等多種類別。

2、思考:檔案操作包含哪些內容呢?

在日常操作中,我們對檔案的主要操作:建立檔案、開啟檔案、檔案讀寫、檔案備份等等

3、檔案操作的作用

檔案操作的作用就是把一些內容(資料)儲存存放起來,可以讓程式下一次執行的時候直接使用,而不必重新制作一份,省時省力。

七、檔案的基本操作

1、檔案操作三步走

① 開啟檔案

② 讀寫檔案

③ 關閉檔案

2、open函數開啟檔案

在Python,使用open()函數,可以開啟一個已經存在的檔案,或者建立一個新檔案,語法如下:

f = open(name, mode)
注:返回的結果是一個file檔案物件(後續會學習,只需要記住,後續方法都是f.方法())

name:是要開啟的目標檔名的字串(可以包含檔案所在的具體路徑)。

mode:設定開啟檔案的模式(存取模式):唯讀r、寫入w、追加a等。

r模式:代表以唯讀模式開啟一個已存在的檔案,後續我們對這個檔案只能進行讀取操作。如果檔案不存在,則直接報錯。另外,r模式在開啟檔案時,會將遊標放在檔案的一行。

w模式:代表以只寫模式開啟一個檔案,檔案不存在,則自動建立該檔案。w模式主要是針對檔案寫入而定義的模式。但是,要特別注意,w模式在寫入時,遊標也是置於第一行同時還會清空原有檔案內容。

a模式:代表以追加模式開啟一個檔案,檔案不存在,則自動建立該檔案。a模式主要也是針對檔案寫入而定義模式。但是和w模式有所不同,a模式不會清空檔案的原有內容,而是在檔案的尾部追加內容。

3、write函數寫入檔案

基本語法:

f.write('要寫入的內容,要求是一個字串型別的資料')

4、close函數關閉檔案

f.close()

5、入門級案例

# 1、開啟檔案
f = open('python.txt', 'w')
# 2、寫入內容
f.write('人生苦短,我學Python!')
# 3、關閉檔案
f.close()

強調一下:中文亂碼問題,預設情況下,計算機常用編碼ASCII、GBK、UTF-8

6、解決寫入中文亂碼問題

# 1、開啟檔案
f = open('python.txt', 'w', encoding='utf-8')
# 2、寫入內容
f.write('人生苦短,我學Python!')
# 3、關閉檔案
f.close()

7、檔案的讀取操作

read(size)方法:主要用於文字型別或者二進位制檔案(圖片、音訊、視訊…)資料的讀取

size表示要從檔案中讀取的資料的長度(單位是位元組),如果沒有傳入size,那麼就表示讀取檔案中所有的資料。

f.read()  # 讀取檔案的所有內容
f.read(1024)  # 讀取1024個位元組長度檔案內容,字母或數位,一個佔1個位元組長度。中文utf-8佔3個位元組長度。
# 1、開啟檔案
f = open('python.txt', 'r', encoding='utf-8')
# 2、使用read()方法讀取檔案所有內容
contents = f.read()
print(contents)
# 3、關閉檔案
f.close()

readlines()方法:主要用於文字型別資料的讀取

readlines可以按照行的方式把整個檔案中的內容進行一次性讀取,並且返回的是一個列表,其中每一行的資料為一個元素。

# 1、開啟檔案
f = open('python.txt', 'r', encoding='utf-8')
# 2、讀取檔案
lines = f.readlines()
for line in lines:
    print(line, end='')
# 3、關閉檔案
f.close()

8、聊聊檔案操作的mode模式

模式描述
r以唯讀方式開啟檔案。檔案的指標將會放在檔案的開頭。這是預設模式。
rb以二進位制格式開啟一個檔案用於唯讀。檔案指標將會放在檔案的開頭。這是預設模式。
r+開啟一個檔案用於讀寫。檔案指標將會放在檔案的開頭。
rb+以二進位制格式開啟一個檔案用於讀寫。檔案指標將會放在檔案的開頭。
w開啟一個檔案只用於寫入。如果該檔案已存在則開啟檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。
wb以二進位制格式開啟一個檔案只用於寫入。如果該檔案已存在則開啟檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。
w+開啟一個檔案用於讀寫。如果該檔案已存在則開啟檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。
wb+以二進位制格式開啟一個檔案用於讀寫。如果該檔案已存在則開啟檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。
a開啟一個檔案用於追加。如果該檔案已存在,檔案指標將會放在檔案的結尾。也就是說,新的內容將會被寫入到已有內容之後。如果該檔案不存在,建立新檔案進行寫入。
ab以二進位制格式開啟一個檔案用於追加。如果該檔案已存在,檔案指標將會放在檔案的結尾。也就是說,新的內容將會被寫入到已有內容之後。如果該檔案不存在,建立新檔案進行寫入。
a+開啟一個檔案用於讀寫。如果該檔案已存在,檔案指標將會放在檔案的結尾。檔案開啟時會是追加模式。如果該檔案不存在,建立新檔案用於讀寫。
ab+以二進位制格式開啟一個檔案用於追加。如果該檔案已存在,檔案指標將會放在檔案的結尾。如果該檔案不存在,建立新檔案用於讀寫。

雖然mode檔案操作模式很多,但是我們只需要記住3個字元即可。r、w、a

r+、w+、a+,代加號,功能全,既能讀,又能寫(區別在於指標到底指向不同)

rb、wb、ab,代b的字元,代表以二進位制的形式對其進行操作,適合讀取文字或二進位制格式檔案,如圖片、音訊、視訊等格式

rb+、wb+、ab+,代加號,功能全,既能讀,又能寫(區別在於指標到底指向不同)

9、seek函數移動遊標

無論是檔案讀操作,還是寫操作。其起始位置都是檔案遊標決定的。

r => 檔案頭

w => 清空檔案內容,指向檔案頭

a => 檔案尾

遊標在剛開啟檔案時,預設情況下是根據r、w、a模式相關固定的。但是我們可以通過某些方法,人為移動遊標。可以通過seek方法實現。

f.seek(offset,whence=0)

offset:開始的偏移量,也就是代表需要移動偏移的位元組數
whence:給offset引數一個定義,表示要從哪個位置開始偏移;0代表從檔案開頭開始算起,1代表從當前位置開始算起,2代表從檔案末尾算起

實際工作中,seek主要用於重置遊標到起始位置。

f.seek(0)
#或
f.seek(0, 0)

其他應用:

>>> f = open('workfile', 'rb+')
>>> f.write(b'0123456789abcdef')
16
>>> f.seek(5)      # 從0開始向右移動5個位元組
5
>>> f.read(1)
b'5'
>>> f.seek(-3, 2)  # 從右向左移動3個位元組
13
>>> f.read(1)
b'd'

八、檔案備份案例

1、案例需求

需求:使用者輸入當前目錄下任意檔名,完成對該檔案的備份功能(備份檔名為xx[備份]字尾,例如:test[備份].txt)。

實現思路:

① 接收使用者輸入的檔名

② 規劃備份檔名

③ 備份檔案寫入資料

2、程式碼實現

# 1、接收使用者輸入的檔名(要備份的檔名)
oldname = input('請輸入要備份的檔名稱:')  # python.txt
# 2、規劃備份檔名(python[備份].txt)
# 搜尋點號
index = oldname.rfind('.')
# 返回檔名和檔案字尾
name = oldname[:index]
postfix = oldname[index:]
newname = name + '[備份]' + postfix
# 3、對檔案進行備份操作
old_f = open(oldname, 'rb')
new_f = open(newname, 'wb')

# 讀取原始檔內容寫入新檔案
while True:
    content = old_f.read(1024)
    if len(content) == 0:
        break
    new_f.write(content)
# 4、關閉檔案
old_f.close()
new_f.close()

到此這篇關於Python函數進階與檔案操作詳情的文章就介紹到這了,更多相關Python檔案操作 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com