1. 程式人生 > 實用技巧 >鞏固複習(對以前的隨筆總結)_02

鞏固複習(對以前的隨筆總結)_02

接著上一篇隨筆,繼續進行整理總結
注:以下內容基本都在以前的隨筆中可以找到

Python定位模組:

匯入模組時,系統會根據搜尋路徑進行尋找模組:

  1.在程式當前目錄下尋找該模組

  2.在環境變數 PYTHONPATH 中指定的路徑列表尋找

  3.在 Python 安裝路徑中尋找

搜尋路徑是一個列表,所以具有列表的方法
使用 sys 庫的 path 可以檢視系統路徑

import sys
# 以列表方式輸出系統路徑,可以進行修改
print(sys.path)
增加新目錄到系統路徑中

sys.path.append("新目錄路徑")
sys.path.insert(0,"
新目錄路徑")
新增環境變數

set PYTHONPATH=安裝路徑\lib;
Python 會在每次啟動時,將 PYTHONPATH 中的路徑載入到 sys.path中。

Python名稱空間和作用域:

變數擁有匹配物件的名字,名稱空間包含了變數的名稱(鍵)和所指向的物件(值)。

Python表示式可以訪問區域性名稱空間和全域性名稱空間

注:當局部變數和全域性變數重名時,使用的是區域性變數

每個函式和類都具有自己的名稱空間,稱為區域性名稱空間

如果需要在函式中使用全域性變數,可以使用 global 關鍵字宣告,聲明後,Python會將該關鍵字看作是全域性變數


# global 全域性變數名:
# 在函式中使用全域性變數,可以對全域性變數進行修改。 # 注:如果只是在函式中使用了和全域性變數相同的名字,則只是區域性變數 # 定義全域性變數 total total = 0 def add(num1,num2): # 使用 global 關鍵字宣告全域性變數 total global total total = num1 + num2 # 輸出全域性變數 print(total) add(4,6) # 10 # 輸出全域性變數 print(total) # 10

Python dir(模組名 或 模組名.方法名):
檢視 模組名 或 模組名.方法名 的所有可以呼叫的方法

# 匯入 math 庫 import math # 檢視 math 可以呼叫的方法 print(dir(math)) ''' ['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc'] ''' import urllib.request print(dir(urllib.request)) ''' ['AbstractBasicAuthHandler', 'AbstractDigestAuthHandler', 'AbstractHTTPHandler', 'BaseHandler', 'CacheFTPHandler', 'ContentTooShortError', 'DataHandler', 'FTPHandler', 'FancyURLopener', 'FileHandler', 'HTTPBasicAuthHandler', 'HTTPCookieProcessor', 'HTTPDefaultErrorHandler', 'HTTPDigestAuthHandler', 'HTTPError', 'HTTPErrorProcessor', 'HTTPHandler', 'HTTPPasswordMgr', 'HTTPPasswordMgrWithDefaultRealm', 'HTTPPasswordMgrWithPriorAuth', 'HTTPRedirectHandler', 'HTTPSHandler', 'MAXFTPCACHE', 'OpenerDirector', 'ProxyBasicAuthHandler', 'ProxyDigestAuthHandler', 'ProxyHandler', 'Request', 'URLError', 'URLopener', 'UnknownHandler', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_cut_port_re', '_ftperrors', '_have_ssl', '_localhost', '_noheaders', '_opener', '_parse_proxy', '_proxy_bypass_macosx_sysconf', '_randombytes', '_safe_gethostbyname', '_splitattr', '_splithost', '_splitpasswd', '_splitport', '_splitquery', '_splittag', '_splittype', '_splituser', '_splitvalue', '_thishost', '_to_bytes', '_url_tempfiles', 'addclosehook', 'addinfourl', 'base64', 'bisect', 'build_opener', 'contextlib', 'email', 'ftpcache', 'ftperrors', 'ftpwrapper', 'getproxies', 'getproxies_environment', 'getproxies_registry', 'hashlib', 'http', 'install_opener', 'io', 'localhost', 'noheaders', 'os', 'parse_http_list', 'parse_keqv_list', 'pathname2url', 'posixpath', 'proxy_bypass', 'proxy_bypass_environment', 'proxy_bypass_registry', 'quote', 're', 'request_host', 'socket', 'ssl', 'string', 'sys', 'tempfile', 'thishost', 'time', 'unquote', 'unquote_to_bytes', 'unwrap', 'url2pathname', 'urlcleanup', 'urljoin', 'urlopen', 'urlparse', 'urlretrieve', 'urlsplit', 'urlunparse', 'warnings'] '''

Python globals和locals函式_reload函式:

globals( ):

返回所有能夠訪問到的全域性名字

num = 5
sum = 0

def add(num):
    func_sum = 0
    func_sum += num
    return func_sum

print(globals())
'''
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F5F98CC2E0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'G:/code/time/1.py', '__cached__': None, 'num': 5, 'sum': 0, 'add': <function add at 0x000001F5F97E51F0>}

'''

注:我此處的程式碼是停留在昨天的time模組中,所以在路徑下會出現G:/code/time/1.py 

locals( ):

在函式中使用 locals ,返回形參和區域性變數


num = 5
sum = 0

def add(num):
    func_sum = 0
    func_sum += num
    print(locals())
    return func_sum

add(num)
# {'num': 5, 'func_sum': 5}

reload(模組名):reload 在 importlib 模組中

重新匯入之前匯入過的模組

注:當一個模組匯入到另一個指令碼時,模組頂層部分的程式碼只會被執行一次


# 重新匯入模組
import func
# 匯入自定義的模組
from importlib import reload
# reload 函式在 importlib 模組中
reload(func)
# 重新匯入 func 模組
from func import get_info
get_info()
# 獲取到了 func 模組的資訊

使用reload的前提,是reload的 模組,之前已經使用import或者from匯入過,否則會失敗

import 匯入的模組,使用模組名.方法的方式,reload會強制執行模組檔案,然後原來匯入的模組會被新使用的匯入語句覆蓋掉

from 匯入的模組,本質是一個賦值操作
即在當前檔案中(即執行 from 語句的檔案)進行 attr = module.attr

注:reload 函式對 reload 執行之前的from語句沒有影響

Python包:

包是一種管理 Python 模組名稱空間的形式,採用 “點模組名稱”

例:A.B  表示 A 模組的 B子模組

當不同模組間存在相同的變數名時,一個是使用 模組名.變數名 另一個是 變數名

當匯入一個包時,Python 會根據 sys 模組的 path 變數中尋找這個包

目錄中只有一個 __init__.py 檔案才會被認為是一個包

導包常見的幾種方式:

  import 模組名 或 包:呼叫方法,使用 模組名.方法

  from 模組名 import 子模組(子模組 或 函式 或 類 或 變數):使用函式呼叫

  from 模組名 import * :使用函式進行呼叫

  注:如果 __init__.py 檔案中存在 __all__變數,則匯入 __all__變數的值,在更新包的時候,注意修改__all__的值

  __all__ = ["echo", "surround", "reverse"] 匯入 * 時,從 __all__ 匯入

包還提供 __path__ ,一個目錄列表,每一個目錄都有為這個包服務的 __init__.py 檔案,先定義,後執行其他的__init__.py檔案

__path__ :主要用於擴充套件包裡面的模組

float_num = 2.635
print("輸出的是%f"%(float_num))
# 輸出的是2.635000

# 保留兩位小數
print("輸出的是%.2f"%(float_num))
# 輸出的是2.63

float_num = 5.99
print("輸出的數字是{}".format(float_num))
# 輸出的數字是5.99

# 指定引數名
float_num = 5.99
strs = 'happy'
print("輸出的數字是{num},輸出的字串是{str}".format(num = float_num,str = strs))
# 輸出的數字是5.99,輸出的字串是happy

input(字串):字串通常為提示語句

輸入語句

注:通常使用變數進行接收,input 返回字串型別,如果輸入的為數字,可使用 int 轉化為數字

# input(字串):字串通常為提示語句
# 輸入語句
# 注:通常使用變數進行接收,input 返回字串型別,如果輸入的為數字,可使用 eval 轉化為數字

strs = input("請輸入一個字串")
print(type(strs))
print("輸入的字串為:",strs)

# 請輸入一個字串HELLO
# <class 'str'>
# 輸入的字串為: HELLO


num = eval(input("請輸入一個數字"))
print(type(num))
print("輸入的數字為:",num)

# 請輸入一個數字56
# <class 'int'>
# 輸入的數字為: 56
注:
input 使用 eval 進行轉換時,如果輸入的是
[1,2,3] 那麼轉換的就是 [1,2,3] 為列表型別

Python開啟和關閉檔案:

open(檔名,開啟檔案的模式[,寄存區的緩衝]):

  檔名:字串值  

    注:檔名帶有後綴名

# 開啟建立好的 test.txt 檔案
f = open("test.txt",'r')

# 輸出檔案所有的內容
print(f.readlines( ))
# ['hello,world.\n']

# 關閉檔案
f.close()

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

寄存區的緩衝:

    小於 0 的整數:系統預設設定寄存區的大小

    0:不進行寄存

    1:進行寄存

    大於 1 的整數:整數即為寄存區的緩衝區大小

Python read和write方法:

read():
從檔案中讀取字串

注:Python 字串可以是二進位制資料,而不僅僅是文字。

語法:

檔案物件.read([count])
count:開啟檔案需要讀取的字元數

注:read 函式不使用 count 會盡可能多地讀取更多的內容,通常一直讀取到檔案末尾
# 使用 count
# 開啟建立好的 test.txt 檔案
f = open("test.txt",'r')
# 輸出檔案的前 11 個字元
print(f.read(11))

# 關閉檔案
f.close()
# hello,world

檔案位置:

tell():

返回檔案內當前指向的位置
f = open("test.txt",'r')
# 輸出檔案的前 11 個字元
f.read(11)

print(f.tell())
# 11

seek(offset [,from]):

改變當前檔案的位置

  offset:表示要移動的位元組數

  from :指定開始移動位元組的參考位置。

    0:檔案開頭

    1:當前位置

    2:檔案末尾
# 開啟建立好的 test.txt 檔案
f = open("test.txt",'r')
# 輸出檔案的前 11 個字元
print(f.read(11))
# hello,world
# 返回檔案內當前指向的位置
print(f.tell())
# 11
print(f.seek(0,0))
# 0
print(f.tell())
# 0
print(f.read(11))
# hello,world
# 關閉檔案
f.close()

write( ):

將任意字串寫入一個檔案中

注:Python字串可以是二進位制資料 和 文字,換行符('\n') 需要自己新增

語法:
檔案物件.write(字串)

程式:

# write 方法
# 開啟建立好的 test.txt 檔案

f = open("test.txt",'w')
# 在開頭,新增檔案內容
f.write('hey boy')

# 關閉檔案
f.close()

PythonFile物件的屬性:
一個檔案被開啟後,使用物件進行接收,接收的物件即為 File 物件

file.closed
返回true如果檔案已被關閉,否則返回false

file.mode
返回被開啟檔案的訪問模式

file.name
返回檔案的名稱


file = open("test.txt",'r')
# file.name 返回檔案的名稱
print(file.name)
# test.txt

# file.closed 如果檔案未關閉返回 False
print(file.closed)
# False

# file.mode 返回被開啟檔案的訪問模式
print(file.mode)
# r

# file.closed 如果檔案已關閉返回 True
file.close()
print(file.closed)
# True

os 的方法:

mkdir(目錄名):
在當前目錄下建立新的目錄

程式:

import os
# 建立新的目錄-包結構
os.mkdir('新目錄-test')


getcwd()方法:
顯示當前的工作目錄。

程式:
import os

print(os.getcwd())
# G:\code\time

chdir(修改的目錄名):
修改當前的目錄名為 修改的目錄名

程式:

import os
# 建立新的目錄-包結構
print(os.getcwd())
# D:\見解\Python\Python程式碼\vacation\備課\新目錄-test
os.chdir('新目錄-test2')
print(os.getcwd())
# D:\見解\Python\Python程式碼\vacation\備課\新目錄-test\新目錄-test2


rmdir(目錄名):
刪除目錄
注:目錄名下為空,沒有其他檔案

程式:

import os
os.rmdir('新目錄-test2')
刪除後包檔案消失

rename(當前的檔名,新檔名):
將當前的檔名修改為新檔名

程式:

# os.rename('舊名字',’新名字‘)

import os
os.rename('舊名字.txt','新名字.txt')


remove(檔名):
刪除檔案

程式:
import os
os.remove('名稱.txt')

'''
程式設計完成一個簡單的學生管理系統,要求如下:
(1)使用自定義函式,完成對程式的模組化
(2)學生資訊至少包括:姓名、性別及手機號
(3)該系統具有的功能:新增、刪除、修改、顯示、退出系統
設計思路如下:
(1)    提示使用者選擇功能序號
(2)    獲取使用者選擇的能夠序號
(3)    根據使用者的選擇,呼叫相應的函式,執行相應的功能
'''
stu_lst = [[],[],[],[],[]]
# 建立儲存五個學生的容器
def show_gn():
    '''展示學生管理系統的功能'''
    print("==========================")
    print("學生管理系統v1.0")
    print("1.新增學生資訊(請先輸入1)")
    print("2.刪除學生資訊")
    print("3.修改學生資訊")
    print("4.顯示所有學生資訊")
    print("0.退出系統")
    print("==========================")

def tj_gn(num):
    '''新增功能'''
    stu_lst[num].append(input("請輸入新學生的名字:"))
    # 第一個引數為新學生的名字
    stu_lst[num].append(input("請輸入新學生的性別:"))
    # 第二個引數為新學生的性別
    stu_lst[num].append(input("請輸入新學生的手機號:"))
    # 第三個引數為新學生的手機號
    stu_lst[num].append(num)
    # 第四個引數為新學生的預設學號(從 0 開始)

def sc_gn():
    '''刪除功能'''
    stu_xlh = int(eval(input("請輸入需要刪除的學生序列號:")))
    xs_gn_returni = xs_gn(stu_xlh)
    pd_str = input("請問確定刪除嗎? 請輸入全小寫字母 yes / no ? ")
    # pd_str 判斷是否刪除學生資訊
    if pd_str == 'yes':
        del stu_lst[xs_gn_returni]
        print("刪除完畢")
    if pd_str == 'no':
        print("刪除失敗")


def xg_gn():
    '''修改功能'''
    stu_xlh = int(eval(input("請輸入需要修改的學生序列號:")))
    xs_gn_returni = xs_gn(stu_xlh)
    # xs_gn_returni 接收的是如果存在輸入的學生序列號,則返回經過確認的索引下標
    xg_str = input("請問需要修改該名學生哪一處資訊,請輸入提示後面的小寫字母 (姓名)name,(性別)sex,(手機號)sjh")
    if xg_str in ['name','sex','sjh']:
        if xg_str == 'name':
            stu_lst[xs_gn_returni][0] = input("請輸入新的姓名值")
        elif xg_str == 'sex':
            stu_lst[xs_gn_returni][1] = input("請輸入新的性別值")
        else:
            stu_lst[xs_gn_returni][2] = input("請輸入新的手機號值")
    else:
        print("輸入錯誤")

def xs_gn(stu_xlh = -1):
    '''顯示功能'''
    print("姓名性別手機號序列號資訊如下")
    if stu_xlh == -1:
        for i in stu_lst:
            if i != []:
                print(i)
    else:
        for i in range(len(stu_lst)):
            if stu_xlh in stu_lst[i] and  i != []:
                print("該學生資訊如下:")
                print(stu_lst[i])
                return i

show_gn()

gn_num = int(eval(input("請輸入功能對應的數字:")))
# gn_num 功能對應的數字

num = 0
while 0 <= gn_num < 1000:
    if gn_num == 1:
        tj_gn(num)
        num += 1
        gn_num = int(eval(input("請輸入功能對應的數字:")))
    elif gn_num == 2:
        sc_gn()
        gn_num = int(eval(input("請輸入功能對應的數字:")))
    elif gn_num == 3:
        xg_gn()
        gn_num = int(eval(input("請輸入功能對應的數字:")))
    elif gn_num == 4:
        xs_gn()
        gn_num = int(eval(input("請輸入功能對應的數字:")))
    elif gn_num == 0:
        print("退出系統")
        exit()
    else:
        print("請重新執行該程式,輸入的數字不在 0~4 之中")
        exit()

a = 10
b = 8

print("a>b") if a>b else pass
pass 為何報錯問題:
第一部分:print
第二部分:("a>b") if a>b else pass

第一種情況 print ("a>b")

第二種情況 print(pass)
    pass 關鍵字,不用於輸出,導致出錯

Python 實現分層聚類演算法

'''
1.將所有樣本都看作各自一類
2.定義類間距離計算公式
3.選擇距離最小的一堆元素合併成一個新的類
4.重新計算各類之間的距離並重覆上面的步驟
5.直到所有的原始元素劃分成指定數量的類

程式要點:
1.生成測試資料
    sklearn.datasets.make_blobs
2.系統聚類演算法
    sklearn.cluster.AgglomerativeClustering
3.必須滿足該條件不然會報錯(自定義函式中的引數)
    assert 1 <= n_clusters <= 4
4.顏色,紅綠藍黃
r g b y
5. o * v +
    散點圖的形狀
6.[] 內可以為條件表示式,輸出陣列中滿足條件的資料
    data[predictResult == i]
7.訪問 x 軸,y 軸座標
    subData[:,0] subData[:,1]
8.plt.scatter(x軸,y軸,c,marker,s=40)
    colors = "rgby"
    markers = "o*v+"
    c 顏色 c=colors[i]
    marker 形狀 marker=markers[i]
9.生成隨機資料並返回樣本點及標籤
data,labels = make_blobs(n_samples=200,centers=4)
    make_blobs 為 sklearn.datasets.make_blobs 庫
    n_samples 為需要的樣本數量
    centers 為標籤數
'''
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import AgglomerativeClustering
def AgglomerativeTest(n_clusters):
    assert 1 <= n_clusters <= 4
    predictResult = AgglomerativeClustering(
        n_clusters=n_clusters,
        affinity='euclidean',
        linkage='ward'
    ).fit_predict(data)
    # 定義繪製散點圖時使用的顏色和散點符號
    colors = "rgby"
    markers = "o*v+"
    # 依次使用不同的顏色和符號繪製每個類的散點圖
    for i in range(n_clusters):
        subData = data[predictResult == i]
        plt.scatter(
            subData[:,0],
            subData[:,1],
            c = colors[i],
            marker = markers[i],
            s = 40
        )
    plt.show()
# 生成隨機資料,200個點,4類標籤,返回樣本及標籤
data , labels = make_blobs(n_samples=200,centers=4)
print(data)
AgglomerativeTest(2)


KNN演算法基本原理與sklearn實現

'''
KNN 近鄰演算法,有監督學習演算法
用於分類和迴歸
思路:
    1.在樣本空間中查詢 k 個最相似或者距離最近的樣本
    2.根據這 k 個最相似的樣本對未知樣本進行分類
步驟:
    1.對資料進行預處理
        提取特徵向量,對原來的資料重新表達
    2.確定距離計算公式
        計算已知樣本空間中所有樣本與未知樣本的距離
    3.對所有的距離按升序進行排列
    4.選取與未知樣本距離最小的 k 個樣本
    5.統計選取的 k 個樣本中每個樣本所屬類別的出現概率
    6.把出現頻率最高的類別作為預測結果,未知樣本則屬於這個類別
程式要點:
1.建立模型需要用到的包
sklearn.neighbors.KNeighborsClassifier
2.建立模型,k = 3
knn = KNeighborsClassifier(n_neighbors = 3)
    n_neighbors 數值不同,建立的模型不同
3.訓練模型,進行擬合
knn.fit(x,y)
    x 為二維列表資料
        x = [[1,5],[2,4],[2.2,5],
             [4.1,5],[5,1],[5,2],[5,3],[6,2],
             [7.5,4.5],[8.5,4],[7.9,5.1],[8.2,5]]
    y 為一維分類資料,將資料分為 0 1 2 三類
        y = [0,0,0,
             1,1,1,1,1,
             2,2,2,2]
4.進行預測未知資料,返回所屬類別
knn.predict([[4.8,5.1]])
5.屬於不同類別的概率
knn.predict_proba([[4.8,5.1]])
'''
from sklearn.neighbors import KNeighborsClassifier
# 導包
x = [[1,5],[2,4],[2.2,5],
     [4.1,5],[5,1],[5,2],[5,3],[6,2],
     [7.5,4.5],[8.5,4],[7.9,5.1],[8.2,5]]
# 設定分類的資料
y = [0,0,0,
     1,1,1,1,1,
     2,2,2,2]
# 對 x 進行分類,前三個分為 0類,1類和2類
knn = KNeighborsClassifier(n_neighbors=3)
# 建立模型 k = 3
knn.fit(x,y)
# 開始訓練模型
'''
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
                     metric_params=None, n_jobs=None, n_neighbors=3, p=2,
                     weights='uniform')
'''
knn.predict([[4.8,5.1]])
# array([1]) 預測 4.8,5.1 在哪一個分組中
knn = KNeighborsClassifier(n_neighbors=9)
# 設定引數 k = 9
knn.fit(x,y)
'''
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
                     metric_params=None, n_jobs=None, n_neighbors=9, p=2,
                     weights='uniform')
'''
knn.predict([[4.8,5.1]])
# array([1])
knn.predict_proba([[4.8,5.1]])
# 屬於不同類別的概率
# array([[0.22222222, 0.44444444, 0.33333333]])
# 返回的是在不同組的概率
'''
總結:
     knn = KNeighborsClassifier(n_neighbors=3) 
     使用 KNeighborsClassifier 建立模型 n_neighbors 為 k  
     使用 knn.fit() 進行預測
          第一個引數為 二維列表
          第二個引數為 一維列表
     使用 predict_proba([[num1,num2]])
     檢視num1,num2 在模型中出現的概率
'''

'''
程式要點:import numpy as np
1.檢視 e 的 多少次方
    np.exp(引數)
2.檢視引數的平方根
    np.sqrt(引數)
3.生成三維四列的隨機值(-1,1)之間
    np.random.random((3,4))
4.向下取整
    a = np.floor(引數)
5.將矩陣拉平
    a.ravel()
6.修改矩陣的形狀
    a.shape(6,2)
7.將矩陣轉置
    a.T
8.將矩陣橫行進行拼接
    a = np.floor(引數)
    b = np.floor(引數)
    np.hstack((a,b))
9.將矩陣縱行進行拼接
    np.vstack((a,b))
10.按照行進行切分陣列,切分為3份
    np.hsplit(a,3)
    注:第二個引數可以為元組(3,4)
11.按照列進行切分陣列,切分為2份
    np.vsplit(a,2)

'''
import numpy as np
a = np.floor(10 *np.random.random((3,4)))
'''
array([[6., 8., 0., 9.],
       [9., 3., 7., 4.],
       [2., 4., 9., 1.]])
'''
np.exp(a)
'''
array([[4.03428793e+02, 2.98095799e+03, 1.00000000e+00, 8.10308393e+03],
       [8.10308393e+03, 2.00855369e+01, 1.09663316e+03, 5.45981500e+01],
       [7.38905610e+00, 5.45981500e+01, 8.10308393e+03, 2.71828183e+00]])
'''
np.sqrt(a)
'''
array([[2.44948974, 2.82842712, 0.        , 3.        ],
       [3.        , 1.73205081, 2.64575131, 2.        ],
       [1.41421356, 2.        , 3.        , 1.        ]])
'''
a.ravel()
'''array([6., 8., 0., 9., 9., 3., 7., 4., 2., 4., 9., 1.])'''
a = np.floor(10 *np.random.random((3,4)))
b = np.floor(10 *np.random.random((3,4)))
np.hstack((a,b))
'''
array([[8., 2., 3., 8., 0., 1., 8., 6.],
       [7., 1., 0., 3., 1., 9., 6., 0.],
       [6., 0., 6., 6., 4., 3., 6., 3.]])
'''
np.vstack((a,b))
'''
array([[8., 2., 3., 8.],
       [7., 1., 0., 3.],
       [6., 0., 6., 6.],
       [0., 1., 8., 6.],
       [1., 9., 6., 0.],
       [4., 3., 6., 3.]])
'''
a = np.floor(10 *np.random.random((2,12)))
np.hsplit(a,3)
'''
[array([[6., 4., 2., 2.],
       [6., 2., 2., 8.]]), array([[1., 8., 8., 8.],
       [1., 9., 3., 6.]]), array([[2., 6., 0., 8.],
       [7., 1., 4., 3.]])]
'''
a = np.floor(10 *np.random.random((12,2)))
np.vsplit(a,3)
'''
[array([[2., 6.],
       [7., 1.],
       [4., 7.],
       [3., 1.]]), array([[2., 5.],
       [4., 6.],
       [2., 0.],
       [4., 4.]]), array([[9., 5.],
       [7., 1.],
       [2., 1.],
       [5., 1.]])]
'''

注:上中下的這三篇隨筆,在分類方面都會比較亂.

不同複製操作對比(三種)

'''
1.b = a
    b 發生變化 a 也會發生變化
2.淺複製
    c = a.view()
    c.shape 發生變化,a.shape 不會發生變化
    c 和 a 共用元素值,id 指向不同
    c[1,0] = 1234 , a 的值也會發生變化
3.深複製
    d = a.copy()
    d[0,0] = 999
    d 發生改變,a 不會發生改變
'''

import numpy as np
a = np.arange(1,8)
# array([1, 2, 3, 4, 5, 6, 7])
b = a
b[2] = 999
b
# array([  1,   2, 999,   4,   5,   6,   7])
a
# array([  1,   2, 999,   4,   5,   6,   7])

a = np.arange(1,9)
c = a.view()
c.shape = 4,2
'''
array([[1, 2],
       [3, 4],
       [5, 6],
       [7, 8]])
'''
a
# array([1, 2, 3, 4, 5, 6, 7, 8])
d = a.copy()
d[3] = 888
d
# array([  1,   2,   3, 888,   5,   6,   7,   8])
a
# array([1, 2, 3, 4, 5, 6, 7, 8])

'''
1.檢視列上最大索引的位置
    data.argmax(axis = 0)
2.輸出索引位置上的元素
    data[index,range(data.shape[1])]
    使用 range 輸出幾個元素
3.對numpy 物件進行擴充套件
    a = np.array([4,5,6,2])
    np.tile(a,(2,3))
4.對陣列按行排序,從小到大
    a = np.array([[4,3,5],[1,7,6]])
    np.sort(a,axis = 1)
5.對陣列元素進行排序,返回索引下標
    a = np.array([4,3,1,2])
    j = np.argsort(a)
    a[j]
'''

import numpy as np
data = np.array([
    [4,5,6,8],
    [7,4,2,8],
    [9,5,4,2]
])
data.argmax(axis = 0)
# array([2, 0, 0, 0], dtype=int64)

data.argmax(axis = 1)
# array([3, 3, 0], dtype=int64)

index = data.argmax(axis = 0)
# array([9, 5, 6, 8])

a = np.array([4,5,6,2])
np.tile(a,(2,3))
'''
array([[4, 5, 6, 2, 4, 5, 6, 2, 4, 5, 6, 2],
       [4, 5, 6, 2, 4, 5, 6, 2, 4, 5, 6, 2]])
'''

a = np.array([[4,3,5],[1,7,6]])
'''
array([[4, 3, 5],
       [1, 7, 6]])
'''

np.sort(a,axis = 1)
'''
array([[3, 4, 5],
       [1, 6, 7]])
'''

np.sort(a,axis = 0)
'''
array([[1, 3, 5],
       [4, 7, 6]])
'''

a = np.array([4,3,1,2])
j = np.argsort(a)
# array([1, 2, 3, 4])

正則表示式
1. /b 和 /B
    # /bthe 匹配任何以 the 開始的字串
    # /bthe/b 僅匹配 the 
    # /Bthe 任何包含但並不以 the 作為起始的字串
2. [cr] 表示 c 或者 r 
    [cr][23][dp][o2] 
    一個包含四個字元的字串,第一個字元是“c”或“r”,
    然後是“2”或“3”,後面 是“d”或“p”,最後要麼是“o”要麼是“2”。
    例如,c2do、r3p2、r2d2、c3po等 
3.["-a] 
    匹配在 34-97 之間的字元
4.Kleene 閉包
    * 匹配 0 次或 多次
     + 匹配一次或 多次
     ? 匹配 0 次或 15.匹配全部有效或無效的 HTML 標籤
    </?[^>]+>
6.國際象棋合法的棋盤移動
    [KQRBNP][a-h][1-8]-[a-h][1-8]
    從哪裡開始走棋-跳到哪裡
7.信用卡號碼
    [0-9]{15,16}
8.美國電話號碼
    \d{3}-/d{3}-/d{4}
    800-555-1212
9.簡單電子郵件地址
    \w+@\w+\.com
    [email protected]
10.使用正則表示式,使用一對圓括號可以實現
    對正則表示式進行分組
    匹配子組
        對正則表示式進行分組可以在整個正則表示式中使用重複操作符
    副作用:
        匹配模式的子字串可以儲存起來
    提取所匹配的模式
    簡單浮點數的字串:
        使用 \d+(\.\d*)?
        0.004  2  75.
    名字和姓氏
        (Mr?s?\.)?[A-Z][a-z]*[A-Za-z-]+
11.在匹配模式時,先使用 ? ,實現前視或後視匹配 條件檢查 
    (?P<name>) 實現分組匹配
    (?P:\w+\.)* 匹配以 . 結尾的字串
        google  twitter. facebook.
    (?#comment) 用作註釋
    (?=.com) 如果一個字串後面跟著 .com 則進行匹配
    (?<=800-) 如果一個字串之前為 800- 則進行匹配
        不使用任何輸入字串
    (?<!192\.168\.) 過濾掉一組 C 類 IP 地址
    (?(1)y|x) 如果一個匹配組1(\1) 存在,就與y匹配,否則與x匹配


Pandas 複習

1.導包
    import pandas as pd

2.資料讀取,檔案在該程式碼資料夾內
    food_info = pd.read_csv('food_info.csv')

3.檢視型別
    food_info.dtypes

4.檢視前五條資料
    food_info.head()
    檢視前三條資料
    food_info.head(3)

5.檢視後四行資料
    food_info.tail(4)

6.檢視列名
    food_info.columns

7.檢視矩陣的維度
    food_info.shape

8.取出第 0 號資料
        food_info.loc[0]
    使用切片獲取資料
        food_info.loc[3:6]
    使用索引獲取資料
        food_info.loc['Name']
        獲取多個列
        columns = ["Price","Name"]
        food_info.loc[columns]

9.將列名放入到列表中
    col_names = food_info.columns.tolist()

10.檢視以 d 結尾的列
    for c in col_names:
        c.endswith("d")

11.將商品價格打一折
    food_info["Price"]/10

12.最大值 最小值 均值
    food_info["Price"].max()  
    food_info["Price"].min()  
    food_info["Price"].mean()

13.根據某一列進行排序
    升序:
    food_info.sort_values["Price",inplace=True]
    降序:
    food_info.sort_values["Price",inplace=True,ascending=False]

14.檢視該數值是否為 NaN
    price = food_info["Price"]
    price_is_null = pd.isnull(price)
    food_info[price_is_null]

Pandas 複習2

import pandas as pd
import numpy as np 
food_info = pd.read_csv('food_info.csv')
1.處理缺失值(可使用平均數,眾數填充)
    檢視非缺失值的資料:
        price_is_null = pd.isnull(food_info["Price"])
        price = food_info["Price"][price_is_null==False]
    使用 fillna 填充
        food_info['Price'].fillna(food_info['Price'].mean(),inplace = True)

2.求平均值
    food_info["Price"].mean()

3.檢視每一個 index 級,values 的平均值
    food_info.pivot(index = "",values = "",aggfunc = np.mean)

4.檢視總人數
    food_info.pivot(index = "",values = ["",""],aggfunc = np.sum)

5.丟棄缺失值
    dropna_columns = food_info.dropna(axis = 1)
    將 Price 和 Time 列存在 NaN 的行去掉
        new_food_info = food_info.dropna(axis = 0,subset = ["Price","Time"])

6.定位具體值到 83 
    row_index_83_price = food_info.loc[83,"Price"]

7.進行排序(sort_values 預設升序)
    new_food_info.sort_values("Price")

8.將索引值重新排序,使用 reset_index
    new_food_info.reset_index(drop = True)

9.使用 apply 函式
    new_food_info.apply(函式名)

10.檢視缺失值的個數
    def not_null_count(column):
        column_null = pd.isnull(column)
        # column_null 為空的布林型別
        null = column[column_null]
        # 將為空值的列表傳遞給 null 
        return len(null)
    column_null_count = food_info.apply(not_null_count)

11.劃分等級:年齡 成績
    def which_class(row):
        pclass = row["Pclass"]
        if pd.isnull(pclass):
            return "未知等級"
        elif pclass == 1:
            return "第一級"
        elif pclass == 2:
            return "第二級"
        elif pclass == 3:
            return "第三級"
    new_food_info.apply(which_class,axis = 1)

12.使用 pivot_table 展示透視表
    new_food_info.pivot_table(index = " ",values=" ")

Series結構(常用)

1.建立 Series 物件
    fandango = pd.read_csv("xxx.csv")
    series_rt = fandango["RottenTomatoes"]
    rt_scores = series_rt.values
    series_film = fandango["FILM"]
    # 獲取資料 使用 .values 
    film_names = series_film.values
    series_custom = Series(rt_scores,index = film_names)

2.使用切片獲取資料
    series_custom[5:10]

3.轉換為列表
    original_index = series_custom.index.tolist()

4.進行排序,此時的 original_index 是一個列表
    sorted_index = sorted(original_index)

5.排序索引和值
    series_custom.sort_index()
    series_custom.sort_values()

6.將大於 50 的資料輸出
    series_custom[series_custom > 50]

7.設定索引值
    fandango.set_index("FILM",drop = False)

8.顯示索引值
    fandango.index

9.顯示資料型別
    series_film.dtypes

10.在 apply 中使用匿名函式
    series_film.apply(lambda x : np.std(x),axis = 1)

部分畫圖

import pandas as pd 
unrate = pd.read_csv("unrate.csv")
1.轉換日期時間
    unrate["date"] = pd.to_datetime(unrate["DATE"])

import matplotlib.pyplot as plt 
2.畫圖操作
    plt.plot()
    傳遞 x y 軸,繪製折線圖
    plt.plot(unrate["date"],unrate["values"])

3.展示
    plt.show()

4.對 x 軸上的標籤傾斜 45 度
    plt.xticks(rotation = 45)

5.設定 x 軸 y 軸標題
    plt.xlabel("xxx")
    plt.ylabel("xxx")

6.設定名字
    plt.title("xxx")
fig = plt.figure()

7.繪製子圖
    fig.add_subplot(行,列,x)
        x 表示 在第幾個模組 
        fig.add_subplot(4,3,1)

8.建立畫圖區域時指定大小
    fig = plt.figure((3,6))
    長為 3 寬為 6

9.畫線時指定顏色
    plt.plot(x,y,c="顏色")

10.將每一年的資料都顯示出來
    fig = plt.figure(figsize = (10,6))
    colors = ['red','blue','green','orange','black']
    # 設定顏色
    for i in range(5):
        start_index = i*12
        end_index = (i+1)*12
        # 定義開始和結束的位置
        subset = unrate[start_index:end_index]
        # 使用切片
        label = str(1948 + i)
        # 將標籤 動態命名
        plt.plot(subset['month'],subset['value'],c = colors[i],label = label)
        # 進行繪製
    plt.legend(loc = 'best')
        loc = upper left 顯示在左上角
    # 列印右上角的資料
    plt.show()
    # 展示

11.柱狀圖:
    明確:柱與柱之間的距離,柱的高度
    高度:
        cols = ['FILM','XXX','AAA','FFF','TTT','QQQ']
        norm_reviews = reviews[cols]
        num_cols = ['A','B','C','D','E','F']
        bar_heights = norm_reviews.ix[0,num_cols].values
        # 將每一列的高度都存起來
    位置(距離 0 的距離):
        bar_positions = arange(5) + 0.75
        fig,ax = plt.subplots()
        ax.bar(bar_positions,bar_heights,0.3)
            先寫位置後寫距離
            0.3 表示柱的寬度
            ax.barh() 表示橫著畫
    plt.show()

12.散點圖
    fig,ax = plt.subplots()
        # 使用 ax 進行畫圖,ax 畫圖的軸,fig 圖的樣子
    ax.scatter(norm_reviews['A'],norm_reviews['B'])
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    plt.show()

    # 使用 add_subplot 繪製子圖
    fig = plt.figure(figsize = (5,10))
    ax1 = fig.add_subplot(2,2,1)
    ax2 = fig.add_subplot(2,2,2)
    ax1.scatter(x,y)
    ax1.set_xlabel('x')
    ax1.set_ylabel('y')
    ax2.scatter(x2,y2)
    ax2.set_xlabel('x')
    ax2.set_ylabel('y')
    plt.show()

13.當存在多個值時,可以指定區間進行畫圖
    # 指定 bins 預設為 10
    fig,ax = plt.subplots()
    ax.hist(unrate['Price'],bins = 20)
    ax.hist(unrate['Price'],range(4,5),bins = 20)

14.設定 x y 區間
    sey_xlim(0,50)
    set_ylim(0,50)

15.盒圖:
    num_cols = ['AA','BB','CC','DD']
    fig,ax = plt.subplots()
    ax.boxplot(norm_reviews[num_cols].values)
    # 繪製盒圖
    ax.set_xticklabels(num_cols,rotation = 45)
    # 設定 x 軸標籤,並傾斜45度
    ax.set_ylim(0,5)
    # 設定 y 的區間
    plt.show()

16.去掉圖示後的尺
    ax.tick_params(bottom = "off",top = "off",left = "off",right = "off")

17.展示在右上角
    ax.legend(loc = "upper right")

提取txt文字有效內容
from re import sub

from jieba import cut


def getWordsFromFile(txtFile):
    # 獲取每一封郵件中的所有詞語
    words = [] 
    # 將所有儲存郵件文字內容的記事本檔案都使用 UTF8 編碼
    with open(txtFile,encoding = "utf8") as fp:
        for line in fp:
            # 遍歷每一行,刪除兩端的空白字元
            line = line.strip()
            # 過濾掉干擾字元
            line = sub(r'[.【】 0-9、-。,!~\*]','',line)
            # 對 line 進行分詞
            line = cut(line)
            # 過濾長度為 1 的詞
            line = filter(lambda word:len(word) > 1 ,line)
            # 將文字預處理得到的詞語新增到 words 列表中
            words.extend(line)
        return words

chain 和 Counter  
from collections import Counter
from itertools import chain

1.使用 chain 對 allwords 二維列表進行解包
    解包: chain(*allwords)
        將 allwords 裡面的子列表解出來

2.獲取有效詞彙的數目
    freq = Counter(chain(*allwords))

3.Counter 返回的是可迭代物件出現的次數
    使用 most_common 方法返回出現次數最多的前三個 
        .most_common(3)
    Counter ("dadasfafasfa")
        Counter({'a': 5, 'f': 3, 'd': 2, 's': 2})
    Counter ("dadasfafasfa").most_common(2)
        [('a', 5), ('f', 3)]

1.特徵向量
    每一個有效詞彙在郵件中出現的次數(使用一維列表方法)
    word 詞彙出現的次數
        一維列表.count(word) 
2.將列表轉換為陣列形式 array(引數) 建立垃圾郵件,正常郵件訓練集 array(列表物件 或 表示式)
3.使用 樸素貝葉斯演算法 model = MultinomialNB()
4.進行訓練模型 model.fit model.fit(array陣列,array陣列)
5.對指定 topWords 資料使用函式 map(lambda x:words.count(x),topWords)
6.預測資料 model.predict ,返回值為 0 或 1 result = model.predict(array陣列.reshape(1,-1))[0]
7.檢視在不同區間的概率 model.predict_proba(array陣列.reshape(1,-1))
8.條件語句,預測的結果便於區分 1 為垃圾郵件,0 為 正常郵件 return "垃圾郵件" if result == 1 else "正常郵件"

函式進階1

'''
1.print "a>b" if a>b else pass 出錯問題
    pass 不可以被輸出,導致報錯
    
2.定義函式:
    def 函式名():
    return 可選
    
3.print 輸出時會執行函式
    print func_name()
    注:func_name 中有 print 後,最好不要再使用 print 輸出
        會返回兩個結果
        
4.最好讓函式擁有返回值,便於維護
    沒有返回值會返回 None
    
5.如何製造函式:
    抽象需求,注意可維護性
    當創造方法時,注意可維護性和健壯性
    
6.引數使用 * 號,函式內為元組物件

7.可選引數存在預設值,必選引數沒有預設值

8.健壯性:
    直到函式會返回什麼(異常處理,條件判斷)
    返回的結果是你需要的
    
9.測試時使用斷言 assert

程式:'''

def func_name():
    return 1 
print(func_name())
# 1

def func_name2():
    print("hello")
print(func_name2())
# hello
# None

def add(num1,num2):
    return num1 + num2 
print(add(5,6))
# 11

def add(*num):
    d = 0 
    for i in num:
        d += i
    return d 
print(add(1,2,3,4))
# 10

def add(num1,num2 = 4):
    return num1 + num2
print(add(5))
# 9
print(add(5,8))
# 13

def add(num1,num2):
    # 健壯性
    if isinstance(num1,int) and isinstance(num2,int):
        return num1 + num2
    else:
        return "Error"
print(add('a',(1,2,3)))
# Error
print(add(3,4))
# 7

'''
1.在迴圈中不要使用 排序函式
2.解決問題先要有正確的思路
    寫出虛擬碼
        第一步做什麼
        第二步做什麼
        ...
    慢慢實現

3.使用 filter 函式
    當函式中引數型別為 int 時才進行比較
    def func(*num):
        num = filter(lambda x:isinstance(x,int),num)

4.引數為 module ,將引數輸出
    print("doc %s"%module)

5.不要將程式碼複雜化,讓人一看到就知道實現了什麼功能

6.os.path.exists(file) 作為條件判斷語句,看是否存在該 file 檔案

7.檢測函式 assert:
    型別斷言、資料斷言

8.將問題實現的越簡單越好,測試完整

9.使用下劃線或駝峰命名函式名
    get_doc    getDoc

10.虛擬碼:
    將思路寫出來

11.預設值的好處:
    省事,方便配置,多寫註釋
        傳入引數的資料型別
        返回的資料的型別

12.測試

程式:'''
def function(*num):
    # 輸出 最大值和最小值
    num = filter(lambda x : isinstance(x,int),num)
    # 過濾掉不是 int 型別的資料
    a = sorted(num)
    return "max:",a[-1],"min:",a[0]

print(function(5,6,"adaf",1.2,99.5,[4,5]))

# ('max:', 6, 'min:', 5)

Python異常及異常處理:

當程式執行時,發生的錯誤稱為異常

例:

  0 不能作為除數:ZeroDivisionError

  變數未定義:NameError

  不同型別進行相加:TypeError

異常處理:

'''
try:
    執行程式碼
except:
    發生異常時執行的程式碼

執行 try 語句:
    如果發生異常,則跳轉到 except 語句中

    如果沒有異常,則執行完 try 語句,繼續 except 後面的語句
    
'''

False:布林型別,假。當條件判斷不成立時,返回False。

# == 判斷兩個物件的值是否相等 
print('' == False)
# False

print(None == False)
# False

print([] == False)
# False

print(() == False)
# False

print({} == False)
# False

# is 判斷兩個物件是否引用自同一地址空間

print('' is False)
# False

print(None is False)
# False

print([] is False)
# False

print(() is False)
# False

print({} is False)
# False

正則表示式補充2


正則表示式基礎1

'''
1.指定 eval()呼叫一個程式碼物件會提高效能

2.在進行模式匹配之前,正則表示式的模式必須編譯為正則表示式物件
    匹配時需要進行多次匹配,進行預編譯可以提升速度
    re.compile(pattern,flags = 0)

3.消除快取
    re.purge()

4.使用 re.S 後 . 可以匹配換行符 \n

5.使用了match() 和 search() 方法之後返回的物件稱為匹配物件
    匹配物件常用 group() 和 groups() 方法
    group() 返回整個匹配物件 或 特定子組
    groups() 返回一個包含唯一 或 全部子組的元組

6.match() 方法 對字串的起始部分進行模式匹配
    成功:返回一個匹配物件
    失敗:返回 None

7.search() 方法 對字串任意位置進行模式匹配
    成功:返回匹配物件
    失敗:返回 None

8.可以使用 pos , endpos 引數指定目標字串的搜尋範圍

9.使用 . 匹配任何單個字元
    .end 不能匹配 end
    不能匹配 \n 換行符
    使用 \. 匹配 .

10.建立字符集 [ ]
    [cr][23] 表示 匹配第一個字元 c 或者 r
                     第二個字元 2 或者 3


程式:'''
import re
# match(pattern,string,flags = 0) 匹配示例
m = re.match('foo','foo')
if m is not None:
    # 如果匹配成功則輸出匹配內容
    print(m.group())
    # print(m.groups()) 返回空元組 因為沒有子組
    # foo
    # 匹配物件具有 group() 和 groups() 方法
    print(m)
    # <re.Match object; span=(0, 3), match='foo'>

# search(pattern,string,flags = 0) 匹配示例
m = re.search('foo','sea food')
if m is not None:
    print(m.group())
    # foo
    print(m)
    # <re.Match object; span=(4, 7), match='foo'>
    # 返回第四個元素的位置

# | 或 示例
bt = 'bat|bet'
m = re.match(bt,'bat')
# match 只匹配開頭
m2 = re.search(bt,'abat')
# search 從開始到結尾
print(m.group())
# bat
print(m2.group())
# bat

# . 匹配任意字元示例
anyend = '.end'
m = re.match(anyend,'aend')
print(m.group())
# aend
m2 = re.search(anyend,'abcdend')
print(m2.group())
# dend

pi_pattern = '3.14'
m = re.match(pi_pattern,'3.14')
print(m.group())
# 3.14
pi_pattern = '3\.14'
# 將 . 轉義
m = re.match(pi_pattern,'3.14')
print(m.group())
# 3.14

#  [ ]  建立字符集
m = re.match('[cr][23][dp][po]','c3po')
print(m.group())
# c3po

m = re.match('[cr][23][dp][po]','c2do')
print(m.group())
# c2do

兩數相加(B站看視訊總結)

'''
兩數相加:
    給出兩個 非空 的連結串列用來表示兩個非負的整數
    各自的位數是按照逆序的方式儲存的 每一個節點只能儲存 一位數
示例:
    輸入:(2->4->3) + (5->6->4)
    輸出:7->0->8
    原因:342 + 465 = 807

'''

class ListNode:
    def __init__(self,x):
        # 在類宣告時進行呼叫
        self.val = x
        self.next = None
        # self 指的是自身,在類中宣告函式需要新增才可以訪問自身元素和其他函式
a = ListNode(10086)
# print(a,a.val)
# <__main__.ListNode object at 0x000001F76D46A148> 10086

# # 實現尾部元素指向頭部元素
# move = a
# for i in range(4):
#     temp = ListNode(i)
#     # temp 為 ListNode 節點
#     move.next = temp
#     # move 下面的節點為 temp
#     move = move.next
#     # 將節點向下移動
# move.next = a
# # 重新指向頭節點 a
class Solution1:
    def addTwoNumbers(self,l1:ListNode,l2:ListNode) ->ListNode:
        res = ListNode(10086)
        move = res
        carry = 0
        # 進位
        while l1 != None or l2 != None:
            if l1 == None:
                l1,l2 = l2,l1
                # 替換位置,將 l1 作為輸出
            if l2 == None:
                carry,l1.val = divmod((l1.val + carry),10)
                # 對 l1 進行重新整理
                move.next = l1
                # 設定資料
                l1,l2,move = l1.next,l2.next,move.next
                # 將資料向下移動
            else:
                carry,l1.val = divmod((l1.val + l2.val + carry),10)
                # 如果都不為 None,則對應位置進行相加,然後進行求餘
                move.next = l1
                # 更新資料
                l1,move = l1.next,move.next
                # 向下移動
        if carry == 1:
            move.next = ListNode(carry)
        return res.next

class ListNode:
    def __init__(self,x):
        # 在類宣告時進行呼叫
        self.val = x
        self.next = None
        # self 指的是自身,在類中宣告函式需要新增才可以訪問自身元素和其他函式
# a = ListNode(10086)

# 使用迭代寫法
class Solution1:
    def addTwoNumbers(self,l1:ListNode,l2:ListNode) -> ListNode:
        def recursive(n1,n2,carry = 0):
            if n1 == None and n2 == None:
                return ListNode(1) if carry == 1 else None
                # 如果存在進位 則 輸出 1
            if n1 == None:
                n1,n2 = n2,n1
                # 當 n1 為空時 將位置替換
                return recursive(n1,None,carry)
                # 進行遞迴 使用 n1 進行遞迴
            if n2 == None:
                carry,n1.val = divmod((n1.val + carry),10)
                # 返回值為 進位和數值 將 n1 的值進行替換
                n1.next = recursive(n1.next,None,carry)
                # 對 n1 接下來的資料繼續進行呼叫,更新 n1 連結串列
                return n1
            carry,n1.val = divmod((n1.val + n2.val + carry),10)
            # 當不存在空值時,進行相加,更新 n1 值
            n1.next = recursive(n1.next,n2.next,carry)
            # 設定 n1 接下來的值為 所有 n1 和 n2 接下來的運算呼叫
            return n1
        return recursive(l1,l2)
        # 返回到內部函式中

猜數字遊戲

'''
分析:
    引數->指定整數範圍,最大次數
    在指定範圍內隨機產生一個整數,讓使用者猜測該數
    提示,猜大,猜小,猜對
    給出提示,直到猜對或次數用盡
'''
import random

def fail(os_num):
    '''輸入數字範圍錯誤,沒有猜數字次數'''
    print("猜數失敗")
    print("系統隨機的數為:", os_num)
    print("遊戲結束,歡迎下次再來玩")
    return

def cxsr(count):
    '''重新輸入一個數'''
    count -= 1
    print("提示:您還有 %d 次機會" % (count))
    if count == 0:
        fail(os_num)
    else:
        user_cs = int(eval(input("請重新輸入一個 0~8 之間的整數:\n")))
        csz(os_num,count,user_cs)

def csz(os_num,count,user_cs,num_range = 8):
    '''這是一個猜數字的函式'''
    # num_range 是整數範圍,count為最大次數,user_cs 為使用者猜到的數
    if user_cs > num_range or user_cs < 0 :
        print("請重新執行,輸入錯誤~")
        return
    if count == 0:
        fail()
    else:
        if os_num > user_cs:
            print("您猜的數字比系統產生的隨機數小")
            cxsr(count)

        elif os_num < user_cs:
            print("您猜的數字比系統產生的隨機數大")
            cxsr(count)

        else:
            print("恭喜您,猜對了~")
            print("歡迎下次再玩!")
os_num = random.randint(0,8)
# os_num 為系統產生的隨機數
print("遊戲開始~")
user_cs = int(eval(input("這是一個猜數字的遊戲(您有三次猜數字的機會),請輸入一個 0~8 之間的整數\n")))
# user_cs 為使用者猜到的數
csz(os_num,3,user_cs)

由於以前的隨筆中的習題和我手裡現存的題太多了,大約1000多道左右,所以此處不做整理了.只做一些知識點上的積累

函式進階3

'''
1.考慮可維護性
    一行程式碼儘量簡單
    列表推導式 lambda 匿名函式
    
2.斷言語句用於自己測試,不要寫在流程控制中
    assert 不要寫在 for 迴圈中
    
3.程式的異常處理 引數處理
    try 異常處理 ,引數型別是什麼
    
4.函式->儘量不要在特定環境下使用

5.斷言就是異常->出錯了就會丟擲異常

6.區域性變數和全域性變數的區別:
    當局部變數與全域性變數重名時,生成一個在區域性作用域中的變數
    使用 global 宣告 可以讓區域性變數修改為全域性變數
    
7.引數為可變引數時,使用索引下標會修改原資料

程式:'''
def func1(num1,num2):
    return num1 + num2

# 列印變數名
print(func1.__code__.co_varnames)
# ('num1', 'num2')
print(func1.__code__.co_filename)
# 檔名

# 第六點:
arg = 6
def add(num = 3):
    arg = 4
    return arg + num
print(add())
# 7

arg = 6
def add(num = 3):
    # 使用 global 宣告
    global arg
    return arg + num
print(add())
# 9

函式進階4
'''
1.匿名函式:
    一個表示式,沒有 return 
    沒有名稱
    執行很小的功能
    
2.判斷引數是否存在 如果不存在會怎樣->給出解決辦法

3.可以使用 filter 和 lambda 進行使用
    如果不進行 list 轉換,則只返回 filter 物件
    
4.引數:
    位置匹配:
        func(name)
    關鍵字匹配:
        func(key = value)
            從最右面開始賦予預設值
    收集匹配:
        元組收集
            func(name,arg1,arg2)
                func(*args)
        字典收集
             func(name,key1 = value1,key2 = value2)
                 func(**kwargs)
    引數順序
    
5.遞迴:
    遞迴就是呼叫自身

程式:'''
# 第一點:
d = lambda x:x+1 
print(d(2))
# 3

d = lambda x:x + 1 if x > 0 else "不大於0"
print(d(3))
# 4
print(d(-3))
# 不大於0

# 列表推導
g = lambda x:[(x,i) for i in range(5)] 
print(g(5))
# 只傳遞了一個引數
# [(5, 0), (5, 1), (5, 2), (5, 3), (5, 4)]


# 第三點:
t = [1,4,7,8,5,3,9]
g = list(filter(lambda x: x > 5,t))
# 使用 list 將結果轉換為列表
print(g)
# [7, 8, 9]


# 第四點:
# 對應位置傳遞引數
def func(arg1,arg2,arg3):
    return arg1,arg2,arg3

print(func(1,2,3))
# (1, 2, 3)

# 關鍵字匹配,不按照位置進行匹配
def func(k1 = '',k2 = '',k3 = ''):
    return k1,k2,k3

print(func(k2 = 4 , k3 = 5 , k1 = 3))
# (3, 4, 5)


# 收集匹配
# 元組
def func(*args):
    return args
print(func(5,6,7,8,[1,2,3]))
# (5, 6, 7, 8, [1, 2, 3])

def func(a,*args):
    # 先匹配 a 後匹配 *args
    return args
print(func(5,6,7,8,[1,2,3]))
# (6, 7, 8, [1, 2, 3])


# 字典
def func(**kwargs):
    return kwargs
print(func(a = 5,b = 8))
# {'a': 5, 'b': 8}

列表推導式

lst = [1,2,3]
lst2 = [1,2,3,5,1]
lst3 = [1,2]
lst4 = [1,2,3,65,8]
lst5 = [1,2,3,59,5,1,2,3]

def length(*args):
    # 返回長度
    lens = []
    lens = [len(i) for i in args]
    return lens
print(length(lst,lst2,lst3,lst4,lst5))
# [3, 5, 2, 5, 8]

dic = dict(zip(['a','b','c','d','e'],[4,5,6,7,8]))
lst = ["%s : %s" %(key,value) for key,value in dic.items()]
print(lst)
# ['a : 4', 'b : 5', 'c : 6', 'd : 7', 'e : 8']

關於類和異常的筆記
原文連結:https://www.runoob.com/python/python-object.html

面向物件技術簡介
類(Class): 用來描述具有相同的屬性和方法的物件的集合。它定義了該集合中每個物件所共有的屬性和方法。物件是類的例項。
類變數:類變數在整個例項化的物件中是公用的。類變數定義在類中且在函式體之外。類變數通常不作為例項變數使用。
資料成員:類變數或者例項變數, 用於處理類及其例項物件的相關的資料。
方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override),也稱為方法的重寫。
區域性變數:定義在方法中的變數,只作用於當前例項的類。
例項變數:在類的宣告中,屬性是用變數來表示的。這種變數就稱為例項變數,是在類宣告的內部但是在類的其他成員方法之外宣告的。
繼承:即一個派生類(derived class)繼承基類(base class)的欄位和方法。繼承也允許把一個派生類的物件作為一個基類物件對待。例如,有這樣一個設計:一個Dog型別的物件派生自Animal類,這是模擬"是一個(is-a)"關係(例圖,Dog是一個Animal)。
例項化:建立一個類的例項,類的具體物件。
方法:類中定義的函式。
物件:通過類定義的資料結構例項。物件包括兩個資料成員(類變數和例項變數)和方法。
建立類
使用 class 語句來建立一個新類,class 之後為類的名稱並以冒號結尾:

class ClassName:
   '類的幫助資訊'   #類文件字串
   class_suite  #類體
類的幫助資訊可以通過ClassName.__doc__檢視

class_suite 由類成員,方法,資料屬性組成

例項
以下是一個簡單的 Python 類的例子:

例項
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
class Employee:
   '所有員工的基類'
   empCount = 0
 
   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print "Total Employee %d" % Employee.empCount
 
   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary
empCount 變數是一個類變數,它的值將在這個類的所有例項之間共享。你可以在內部類或外部類使用 Employee.empCount 訪問。 第一種方法__init__()方法是一種特殊的方法,被稱為類的建構函式或初始化方法,當建立了這個類的例項時就會呼叫該方法 self 代表類的例項,self 在定義類的方法時是必須有的,雖然在呼叫時不必傳入相應的引數。 self代表類的例項,而非類 類的方法與普通的函式只有一個特別的區別——它們必須有一個額外的第一個引數名稱, 按照慣例它的名稱是 self。
class Test: def prt(self): print(self) print(self.__class__) t = Test() t.prt() 以上例項執行結果為: <__main__.Test instance at 0x10d066878> __main__.Test 從執行結果可以很明顯的看出,self 代表的是類的例項,代表當前物件的地址,而 self.__class__ 則指向類。 self 不是 python 關鍵字 "建立 Employee 類的第一個物件" emp1 = Employee("Hany", 9000) 訪問屬性 可以使用點號 . 來訪問物件的屬性。使用如下類的名稱訪問類變數: emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount 可以新增,刪除,修改類的屬性,如下所示: del emp1.age # 刪除 'age' 屬性

你也可以使用以下函式的方式來訪問屬性: getattr(obj, name[, default]) : 訪問物件的屬性。 hasattr(obj,name) : 檢查是否存在一個屬性。 setattr(obj,name,value) : 設定一個屬性。如果屬性不存在,會建立一個新屬性。 delattr(obj, name) : 刪除屬性。 hasattr(emp1, 'age') # 如果存在 'age' 屬性返回 True。 getattr(emp1, 'age') # 返回 'age' 屬性的值 setattr(emp1, 'age', 8) # 新增屬性 'age' 值為 8 delattr(emp1, 'age') # 刪除屬性 'age' Python內建類屬性 __dict__ : 類的屬性(包含一個字典,由類的資料屬性組成) __doc__ :類的文件字串 __name__: 類名 __module__: 類定義所在的模組(類的全名是'__main__.className',如果類位於一個匯入模組mymod中,那麼className.__module__ 等於 mymod) __bases__ : 類的所有父類構成元素(包含了一個由所有父類組成的元組) Python內建類屬性呼叫例項如下: python物件銷燬(垃圾回收) Python 使用了引用計數這一簡單技術來跟蹤和回收垃圾。 在 Python 內部記錄著所有使用中的物件各有多少引用。 一個內部跟蹤變數,稱為一個引用計數器。 當物件被建立時, 就建立了一個引用計數, 當這個物件不再需要時, 也就是說, 這個物件的引用計數變為0 時, 它被垃圾回收。但是回收不是"立即"的,
由直譯器在適當的時機,將垃圾物件佔用的記憶體空間回收。 a
= 40 # 建立物件 <40> b = a # 增加引用, <40> 的計數 c = [b] # 增加引用. <40> 的計數 del a # 減少引用 <40> 的計數 b = 100 # 減少引用 <40> 的計數 c[0] = -1 # 減少引用 <40> 的計數 垃圾回收機制不僅針對引用計數為0的物件,同樣也可以處理迴圈引用的情況。迴圈引用指的是,兩個物件相互引用,但是沒有其他變數引用他們。
這種情況下,僅使用引用計數是不夠的。Python 的垃圾收集器實際上是一個引用計數器和一個迴圈垃圾收集器。
作為引用計數的補充, 垃圾收集器也會留心被分配的總量很大(及未通過引用計數銷燬的那些)的物件。 在這種情況下, 直譯器會暫停下來, 試圖清理所有未引用的迴圈。 解構函式
__del____del__在物件銷燬的時候被呼叫,當物件不再被使用時,__del__方法執行 類的繼承 面向物件的程式設計帶來的主要好處之一是程式碼的重用,實現這種重用的方法之一是通過繼承機制。 通過繼承建立的新類稱為子類或派生類,被繼承的類稱為基類、父類或超類。 繼承語法 class 派生類名(基類名) ... 在python中繼承中的一些特點: 1、如果在子類中需要父類的構造方法就需要顯式的呼叫父類的構造方法,或者不重寫父類的構造方法。詳細說明可檢視: python 子類繼承父類建構函式說明。 2、在呼叫基類的方法時,需要加上基類的類名字首,且需要帶上 self 引數變數。區別在於類中呼叫普通函式時並不需要帶上 self 引數 3、Python 總是首先查詢對應型別的方法,如果它不能在派生類中找到對應的方法,它才開始到基類中逐個查詢。(先在本類中查詢呼叫的方法,找不到才去基類中找)。 如果在繼承元組中列了一個以上的類,那麼它就被稱作"多重繼承" 。 語法: 派生類的宣告,與他們的父類類似,繼承的基類列表跟在類名之後,如下所示: class SubClassName (ParentClass1[, ParentClass2, ...]): ... 例項 #!/usr/bin/python # -*- coding: UTF-8 -*- class Parent: # 定義父類 parentAttr = 100 def __init__(self): print "呼叫父類建構函式" def parentMethod(self): print '呼叫父類方法' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "父類屬性 :", Parent.parentAttr class Child(Parent): # 定義子類 def __init__(self): print "呼叫子類構造方法" def childMethod(self): print '呼叫子類方法' c = Child() # 例項化子類 c.childMethod() # 呼叫子類的方法 c.parentMethod() # 呼叫父類方法 c.setAttr(200) # 再次呼叫父類的方法 - 設定屬性值 c.getAttr() # 再次呼叫父類的方法 - 獲取屬性值 以上程式碼執行結果如下: 呼叫子類構造方法 呼叫子類方法 呼叫父類方法 父類屬性 : 200 你可以繼承多個類 class A: # 定義類 A ..... class B: # 定義類 B ..... class C(A, B): # 繼承類 A 和 B .....
可以使用issubclass()或者isinstance()方法來檢測。 issubclass()
- 布林函式判斷一個類是另一個類的子類或者子孫類,語法:issubclass(sub,sup) isinstance(obj, Class) 布林函式如果obj是Class類的例項物件或者是一個Class子類的例項物件則返回true。 方法重寫 如果你的父類方法的功能不能滿足你的需求,你可以在子類重寫你父類的方法: 下表列出了一些通用的功能: 1 __init__ ( self [,args...] ) 建構函式 簡單的呼叫方法: obj = className(args)
2 __del__( self ) 析構方法, 刪除一個物件 簡單的呼叫方法 : del obj
3 __repr__( self ) 轉化為供直譯器讀取的形式 簡單的呼叫方法 : repr(obj)
4 __str__( self ) 用於將值轉化為適於人閱讀的形式 簡單的呼叫方法 : str(obj)
類屬性與方法 類的私有屬性 __private_attrs:兩個下劃線開頭,宣告該屬性為私有,不能在類的外部被使用或直接訪問。在類內部的方法中使用時 self.__private_attrs。 類的方法 在類的內部,使用 def 關鍵字可以為類定義一個方法,與一般函式定義不同,類方法必須包含引數 self,且為第一個引數 類的私有方法 __private_method:兩個下劃線開頭,宣告該方法為私有方法,不能在類的外部呼叫。在類的內部呼叫 self.__private_methods Python 通過改變名稱來包含類名: Traceback (most recent call last): File "test.py", line 17, in <module> print counter.__secretCount # 報錯,例項不能訪問私有變數 AttributeError: JustCounter instance has no attribute '__secretCount' Python不允許例項化的類訪問私有資料,但可以使用 object._className__attrName( 物件名._類名__私有屬性名 )訪問屬性: 單下劃線、雙下劃線、頭尾雙下劃線說明: __foo__: 定義的是特殊方法,一般是系統定義名字 ,類似 __init__() 之類的。 _foo: 以單下劃線開頭的表示的是 protected 型別的變數,即保護型別只能允許其本身與子類進行訪問,不能用於 from module import * __foo: 雙下劃線的表示的是私有型別(private)的變數, 只能是允許這個類本身進行訪問了。
原文連結:https://www.runoob.com/python3/python3-class.html

Python中的類提供了面向物件程式設計的所有基本功能:類的繼承機制允許多個基類,派生類可以覆蓋基類中的任何方法,方法中可以呼叫基類中的同名方法。

物件可以包含任意數量和型別的資料。

類定義
語法格式如下:

class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>
類例項化後,可以使用其屬性,實際上,建立一個類之後,可以通過類名訪問其屬性。

類物件
類物件支援兩種操作:屬性引用和例項化。

屬性引用使用和 Python 中所有的屬性引用一樣的標準語法:obj.name。

類物件建立後,類名稱空間中所有的命名都是有效屬性名:

類有一個名為 __init__() 的特殊方法(構造方法),該方法在類例項化時會自動呼叫

self代表類的例項,而非類 類的方法與普通的函式只有一個特別的區別——它們必須有一個額外的第一個引數名稱, 按照慣例它的名稱是 self。 繼承 Python 同樣支援類的繼承,如果一種語言不支援繼承,類就沒有什麼意義。派生類的定義如下所示: class DerivedClassName(BaseClassName1): <statement-1> . . . <statement-N> BaseClassName(示例中的基類名)必須與派生類定義在一個作用域內。除了類,還可以用表示式,基類定義在另一個模組中時這一點非常有用: class DerivedClassName(modname.BaseClassName): 多繼承 Python同樣有限的支援多繼承形式。多繼承的類定義形如下例: class DerivedClassName(Base1, Base2, Base3): <statement-1> . . . <statement-N> 需要注意圓括號中父類的順序,若是父類中有相同的方法名,而在子類使用時未指定,python從左至右搜尋 即方法在子類中未找到時,從左到右查詢父類中是否包含方法。 方法重寫 如果你的父類方法的功能不能滿足你的需求,你可以在子類重寫你父類的方法: 類的私有屬性 __private_attrs:兩個下劃線開頭,宣告該屬性為私有,不能在類的外部被使用或直接訪問。在類內部的方法中使用時 self.__private_attrs。 類的方法 在類的內部,使用 def 關鍵字來定義一個方法,與一般函式定義不同,類方法必須包含引數 self,且為第一個引數,self 代表的是類的例項。 類的私有方法 __private_method:兩個下劃線開頭,宣告該方法為私有方法,只能在類的內部呼叫 ,不能在類的外部呼叫。self.__private_methods類的例項化物件不能訪問類中的私有屬性 類的專有方法: __init__ : 建構函式,在生成物件時呼叫 __del__ : 解構函式,釋放物件時使用 __repr__ : 列印,轉換 __setitem__ : 按照索引賦值 __getitem__: 按照索引獲取值 __len__: 獲得長度 __cmp__: 比較運算 __call__: 函式呼叫 __add__: 加運算 __sub__: 減運算 __mul__: 乘運算 __truediv__: 除運算 __mod__: 求餘運算 __pow__: 乘方

Python 子類繼承父類建構函式說明
原文連結:https://www.runoob.com/w3cnote/python-extends-init.html

如果在子類中需要父類的構造方法就需要顯式地呼叫父類的構造方法,或者不重寫父類的構造方法。

子類不重寫 __init__,例項化子類時,會自動呼叫父類定義的 __init__
父類名稱.__init__(self,引數1,引數2,...)
例項
class Father(object):
    def __init__(self, name):
        self.name=name
        print ( "name: %s" %( self.name))
    def getName(self):
        return 'Father ' + self.name
 
class Son(Father):
    def __init__(self, name):
        super(Son, self).__init__(name)
        print ("hi")
        self.name =  name
    def getName(self):
        return 'Son '+self.name
 
if __name__=='__main__':
    son=Son('runoob')
    print ( son.getName() )
輸出結果為:

name: runoob
hi
Son runoob

Python 異常(菜鳥教程)
原文:https://www.runoob.com/python/python-exceptions.html

BaseException 所有異常的基類
SystemExit  直譯器請求退出
KeyboardInterrupt 使用者中斷執行(通常是輸入^C)
Exception 常規錯誤的基類
StopIteration 迭代器沒有更多的值
GeneratorExit 生成器(generator)發生異常來通知退出
StandardError 所有的內建標準異常的基類
ArithmeticError 所有數值計算錯誤的基類
FloatingPointError  浮點計算錯誤
OverflowError 數值運算超出最大限制
ZeroDivisionError 除(或取模)零 (所有資料型別)
AssertionError  斷言語句失敗
AttributeError  物件沒有這個屬性
EOFError  沒有內建輸入,到達EOF 標記
EnvironmentError  作業系統錯誤的基類
IOError 輸入/輸出操作失敗
OSError 作業系統錯誤
WindowsError  系統呼叫失敗
ImportError 匯入模組/物件失敗
LookupError 無效資料查詢的基類
IndexError  序列中沒有此索引(index)
KeyError  對映中沒有這個鍵
MemoryError 記憶體溢位錯誤(對於Python 直譯器不是致命的)
NameError 未宣告/初始化物件 (沒有屬性)
UnboundLocalError 訪問未初始化的本地變數
ReferenceError  弱引用(Weak reference)試圖訪問已經垃圾回收了的物件
RuntimeError  一般的執行時錯誤
NotImplementedError 尚未實現的方法
SyntaxError Python 語法錯誤
IndentationError  縮排錯誤
TabError  Tab 和空格混用
SystemError 一般的直譯器系統錯誤
TypeError 對型別無效的操作
ValueError  傳入無效的引數
UnicodeError  Unicode 相關的錯誤
UnicodeDecodeError  Unicode 解碼時的錯誤
UnicodeEncodeError  Unicode 編碼時錯誤
UnicodeTranslateError Unicode 轉換時錯誤
Warning 警告的基類
DeprecationWarning  關於被棄用的特徵的警告
FutureWarning 關於構造將來語義會有改變的警告
OverflowWarning 舊的關於自動提升為長整型(long)的警告
PendingDeprecationWarning 關於特性將會被廢棄的警告
RuntimeWarning  可疑的執行時行為(runtime behavior)的警告
SyntaxWarning 可疑的語法的警告
UserWarning 使用者程式碼生成的警告


什麼是異常?
異常即是一個事件,該事件會在程式執行過程中發生,影響了程式的正常執行。
一般情況下,在Python無法正常處理程式時就會發生一個異常。
異常是Python物件,表示一個錯誤。

當Python指令碼發生異常時我們需要捕獲處理它,否則程式會終止執行。

異常處理
捕捉異常可以使用try/except語句。

try/except語句用來檢測try語句塊中的錯誤,從而讓except語句捕獲異常資訊並處理。

如果你不想在異常發生時結束你的程式,只需在try裡捕獲它。

語法:

以下為簡單的try....except...else的語法:

try:
<語句>        #執行別的程式碼
except <名字><語句>        #如果在try部份引發了'name'異常
except <名字>,<資料>:
<語句>        #如果引發了'name'異常,獲得附加的資料
else:
<語句>        #如果沒有異常發生

try的工作原理是,當開始一個try語句後,python就在當前程式的上下文中作標記,這樣當異常出現時就可以回到這裡,try子句先執行,接下來會發生什麼依賴於執行時是否出現異常。

如果當try後的語句執行時發生異常,python就跳回到try並執行第一個匹配該異常的except子句,異常處理完畢,控制流就通過整個try語句(除非在處理異常時又引發新的異常)。
如果在try後的語句裡發生了異常,卻沒有匹配的except子句,異常將被遞交到上層的try,或者到程式的最上層(這樣將結束程式,並列印預設的出錯資訊)。
如果在try子句執行時沒有發生異常,python將執行else語句後的語句(如果有else的話),然後控制流通過整個try語句。

使用except而不帶任何異常型別
你可以不帶任何異常型別使用except,如下例項:

try:
    正常的操作
   ......................
except:
    發生異常,執行這塊程式碼
   ......................
else:
    如果沒有異常執行這塊程式碼

以上方式try-except語句捕獲所有發生的異常。但這不是一個很好的方式,我們不能通過該程式識別出具體的異常資訊。因為它捕獲所有的異常。
使用except而帶多種異常型別
你也可以使用相同的except語句來處理多個異常資訊,如下所示:

try:
    正常的操作
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   發生以上多個異常中的一個,執行這塊程式碼
   ......................
else:
    如果沒有異常執行這塊程式碼
try-finally 語句
try-finally 語句無論是否發生異常都將執行最後的程式碼。

try:
<語句>
finally:
<語句>    #退出try時總會執行


try:
    fh = open("testfile", "w")
    fh.write("這是一個測試檔案,用於測試異常!!")
finally:
    print "Error: 沒有找到檔案或讀取檔案失敗"
如果開啟的檔案沒有可寫許可權,輸出如下所示:

try:
    fh = open("testfile", "w")
    try:
        fh.write("這是一個測試檔案,用於測試異常!!")
    finally:
        print "關閉檔案"
        fh.close()
except IOError:
    print "Error: 沒有找到檔案或讀取檔案失敗"
當在try塊中丟擲一個異常,立即執行finally塊程式碼。

finally塊中的所有語句執行後,異常被再次觸發,並執行except塊程式碼。

變數接收的異常值通常包含在異常的語句中。在元組的表單中變數可以接收一個或者多個值。

元組通常包含錯誤字串,錯誤數字,錯誤位置。

觸發異常
我們可以使用raise語句自己觸發異常

raise語法格式如下:
raise [Exception [, args [, traceback]]]
語句中 Exception 是異常的型別(例如,NameError)引數標準異常中任一種,args 是自已提供的異常引數。
最後一個引數是可選的(在實踐中很少使用),如果存在,是跟蹤異常物件。

例項
一個異常可以是一個字串,類或物件。 Python的核心提供的異常,大多數都是例項化的類,這是一個類的例項的引數。

定義一個異常非常簡單,如下所示:

def functionName( level ):
    if level < 1:
        raise Exception("Invalid level!", level)
        # 觸發異常後,後面的程式碼就不會再執行
注意:為了能夠捕獲異常,"except"語句必須有用相同的異常來丟擲類物件或者字串。

例如我們捕獲以上異常,"except"語句如下所示:

try:
    正常邏輯
except Exception,err:
    觸發自定義異常    
else:
    其餘程式碼
例項
#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 定義函式
def mye( level ):
    if level < 1:
        raise Exception,"Invalid level!"
        # 觸發異常後,後面的程式碼就不會再執行
try:
    mye(0)            # 觸發異常
except Exception,err:
    print 1,err
else:
    print 2
執行以上程式碼,輸出結果為:

$ python test.py 
1 Invalid level!
使用者自定義異常
通過建立一個新的異常類,程式可以命名它們自己的異常。異常應該是典型的繼承自Exception類,通過直接或間接的方式。

Python3 錯誤和異常
原文連結:
https://www.runoob.com/python3/python3-errors-execptions.html

異常
即便 Python 程式的語法是正確的,在執行它的時候,也有可能發生錯誤。執行期檢測到的錯誤被稱為異常。

大多數的異常都不會被程式處理,都以錯誤資訊的形式展現在這裡:

例項
>>> 10 * (1/0)             # 0 不能作為除數,觸發異常
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3             # spam 未定義,觸發異常
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2               # int 不能與 str 相加,觸發異常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
異常以不同的型別出現,這些型別都作為資訊的一部分打印出來: 例子中的型別有 ZeroDivisionError,NameError 和 TypeError。

錯誤資訊的前面部分顯示了異常發生的上下文,並以呼叫棧的形式顯示具體資訊。

異常處理
try/except
異常捕捉可以使用 try/except 語句。

以下例子中,讓使用者輸入一個合法的整數,但是允許使用者中斷這個程式(使用 Control-C 或者作業系統提供的方法)。使用者中斷的資訊會引發一個 KeyboardInterrupt 異常。

while True:
    try:
        x = int(input("請輸入一個數字: "))
        break
    except ValueError:
        print("您輸入的不是數字,請再次嘗試輸入!")
try 語句按照如下方式工作;

首先,執行 try 子句(在關鍵字 try 和關鍵字 except 之間的語句)。

如果沒有異常發生,忽略 except 子句,try 子句執行後結束。

如果在執行 try 子句的過程中發生了異常,那麼 try 子句餘下的部分將被忽略。如果異常的型別和 except 之後的名稱相符,那麼對應的 except 子句將被執行。

如果一個異常沒有與任何的 except 匹配,那麼這個異常將會傳遞給上層的 try 中。

一個 try 語句可能包含多個except子句,分別來處理不同的特定的異常。最多隻有一個分支會被執行。

處理程式將只針對對應的 try 子句中的異常進行處理,而不是其他的 try 的處理程式中的異常。

一個except子句可以同時處理多個異常,這些異常將被放在一個括號裡成為一個元組,例如:

except (RuntimeError, TypeError, NameError):
    pass
try/except...else
try/except 語句還有一個可選的 else 子句,如果使用這個子句,那麼必須放在所有的 except 子句之後。

else 子句將在 try 子句沒有發生任何異常的時候執行。
以下例項在 try 語句中判斷檔案是否可以開啟,如果開啟檔案時正常的沒有發生異常則執行 else 部分的語句,讀取檔案內容:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()
使用 else 子句比把所有的語句都放在 try 子句裡面要好,這樣可以避免一些意想不到,而 except 又無法捕獲的異常。

異常處理並不僅僅處理那些直接發生在 try 子句中的異常,而且還能處理子句中呼叫的函式(甚至間接呼叫的函式)裡丟擲的異常。例如:

>>> def this_fails():
        x = 1/0
   
>>> try:
        this_fails()
    except ZeroDivisionError as err:
        print('Handling run-time error:', err)
   
Handling run-time error: int division or modulo by zero
try-finally 語句
try-finally 語句無論是否發生異常都將執行最後的程式碼。
以下例項中 finally 語句無論異常是否發生都會執行:

例項
try:
    runoob()
except AssertionError as error:
    print(error)
else:
    try:
        with open('file.log') as file:
            read_data = file.read()
    except FileNotFoundError as fnf_error:
        print(fnf_error)
finally:
    print('這句話,無論異常是否發生都會執行。')
丟擲異常
Python 使用 raise 語句丟擲一個指定的異常。

raise語法格式如下:

raise [Exception [, args [, traceback]]]
以下例項如果 x 大於 5 就觸發異常:

x = 10
if x > 5:
    raise Exception('x 不能大於 5。x 的值為: {}'.format(x))
執行以上程式碼會觸發異常:

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    raise Exception('x 不能大於 5。x 的值為: {}'.format(x))
Exception: x 不能大於 5。x 的值為: 10
raise 唯一的一個引數指定了要被丟擲的異常。它必須是一個異常的例項或者是異常的類(也就是 Exception 的子類)。

如果你只想知道這是否丟擲了一個異常,並不想去處理它,那麼一個簡單的 raise 語句就可以再次把它丟擲。

>>> try:
        raise NameError('HiThere')
    except NameError:
        print('An exception flew by!')
        raise
   
An exception flew by!
Traceback (most recent call last):
  File "<stdin>", line 2, in ?
NameError: HiThere
使用者自定義異常
你可以通過建立一個新的異常類來擁有自己的異常。異常類繼承自 Exception 類,可以直接繼承,或者間接繼承,例如:

>>> class MyError(Exception):
        def __init__(self, value):
            self.value = value
        def __str__(self):
            return repr(self.value)
   
>>> try:
        raise MyError(2*2)
    except MyError as e:
        print('My exception occurred, value:', e.value)
   
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'
在這個例子中,類 Exception 預設的 __init__() 被覆蓋。

當建立一個模組有可能丟擲多種不同的異常時,一種通常的做法是為這個包建立一個基礎異常類,然後基於這個基礎類為不同的錯誤情況建立不同的子類:

class Error(Exception):
    """Base class for exceptions in this module."""
    pass

class InputError(Error):
    """Exception raised for errors in the input.

    Attributes:
        expression -- input expression in which the error occurred
        message -- explanation of the error
    """

    def __init__(self, expression, message):
        self.expression = expression
        self.message = message

class TransitionError(Error):
    """Raised when an operation attempts a state transition that's not
    allowed.

    Attributes:
        previous -- state at beginning of transition
        next -- attempted new state
        message -- explanation of why the specific transition is not allowed
    """

    def __init__(self, previous, next, message):
        self.previous = previous
        self.next = next
        self.message = message
大多數的異常的名字都以"Error"結尾,就跟標準的異常命名一樣。

定義清理行為
try 語句還有另外一個可選的子句,它定義了無論在任何情況下都會執行的清理行為。 例如:

>>> try:
...     raise KeyboardInterrupt
... finally:
...     print('Goodbye, world!')
...
Goodbye, world!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt
以上例子不管 try 子句裡面有沒有發生異常,finally 子句都會執行。

如果一個異常在 try 子句裡(或者在 exceptelse 子句裡)被丟擲,而又沒有任何的 except 把它截住,那麼這個異常會在 finally 子句執行後被丟擲。

預定義的清理行為
一些物件定義了標準的清理行為,無論系統是否成功的使用了它,一旦不需要它了,那麼這個標準的清理行為就會執行。

這面這個例子展示了嘗試開啟一個檔案,然後把內容列印到螢幕上:

for line in open("myfile.txt"):
    print(line, end="")
以上這段程式碼的問題是,當執行完畢後,檔案會保持開啟狀態,並沒有被關閉。

關鍵詞 with 語句就可以保證諸如檔案之類的物件在使用完之後一定會正確的執行他的清理方法:

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")
以上這段程式碼執行完畢後,就算在處理過程中出問題了,檔案 f 總是會關閉。
Python assert(斷言)

Python assert(斷言)用於判斷一個表示式,在表示式條件為 false 的時候觸發異常。

斷言可以在條件不滿足程式執行的情況下直接返回錯誤,而不必等待程式執行後出現崩潰的情況
語法格式如下:

assert expression
等價於:

if not expression:
    raise AssertionError
assert 後面也可以緊跟引數:

assert expression [, arguments]
等價於:

if not expression:
    raise AssertionError(arguments)


非常感謝菜鳥教程.
以下為網址:
https://www.runoob.com/

以前學習的時候會經常翻閱,學習一些程式設計知識
已附上原文連結,推薦到原連結進行訪問,畢竟顯示效果會差很多

類 鞏固小結
'''
1.當方法具有結構時,使用 class 比函式要好

2.類中定義的 方法 或 屬性 如果沒有宣告許可權 
    在類外使用例項化物件可以直接訪問

3.類中的方法,第一個引數一定要寫上 self ,self 是約定好的

4.析構方法通常呼叫不到,垃圾回收機制中引用計數後會自動銷燬

5.寫程式之前:
    虛擬碼 小的程式->直接寫流程
           大專案-> 先分析結構

6.父類通常具有一些公共的方法,使用子類進行擴充套件
    子類可以使用父類中定義的初始化方法 __init__ , 但是引數可能不全

7.找到最小的節點,將節點與節點之間發生的關係使用不同的類進行標識

8._xxx, __xxx 外界都不應該直接訪問,放到類中的方法中使用

9.方法一定要先實現再進行優化

10.使用裝飾器 @property 後 下面的方法會變為屬性
    @property 
    def function(self,args):
        pass
    類例項化物件.function  呼叫 function 方法

11.@staticmethod 靜態方法,下面的方法宣告為"內建方法"
    不需要再使用 self 進行呼叫
    @staticmethod
    def function(object):pass

12.最小驚訝原則
    讓很多人一看就知道在寫什麼
    
13.注意程式碼的複雜度

'''
# 示例:
class stu(object):
    # 繼承 object 基類

    a = 'a' 
    # 定義一個屬性

    def __init__(self,name,age):
        # 初始化賦值
        self.name = name
        self.age = age


    def showName(self):
        print(self.name)

    def __del__(self):
        # 析構方法,通常自動銷燬
        del self.name
        del self.age

student = stu('張三',20)
student.showName()
print(student.a)
# 輸出類中的屬性
# a


class stu_extends(stu):
    """ 繼承 stu 類"""
    pass

class lst_extends(list):
    def append(self):
        pass
# 繼承列表類

模組小結

1.import 模組名(檔案)
    匯入模組

2.檢視模組內的方法
    dir(模組名)

3.if __name__ == "__main__":
    需要測試的語句

4.from 模組名 import 方法/屬性/* 
    再使用時 使用 方法即可 不再使用模組名.方法

5.使用 __all__ = ["方法1","方法2","屬性名1","屬性名2"]
    在匯入 * 時,只匯入該 all 中的方法或屬性
    在 __init__.py 檔案第一行

6.import 模組名(檔案) as 模組別名

7.搜尋模組:
    import sys
    sys.path.append(r'絕對路徑')
        絕對路徑指 匯入的模組的 資料夾的位置

a.py 程式:

import linecache
print(linecache.__file__)
def show( ):
    print("我是 0411 的模組")

程式:
import linecache
# 匯入模組
print(dir(linecache))
# 檢視都具有哪些方法
'''
['__all__', '__builtins__', '__cached__', 
'__doc__', '__file__', '__loader__', '__name__', 
'__package__', '__spec__', 'cache', 'checkcache', 
'clearcache', 'functools', 'getline', 'getlines', 
'lazycache', 'os', 'sys', 'tokenize', 'updatecache']
'''
linecache.__file__
# 檢視模組地址
# F:\Python IDLE\lib\linecache.py
from math import pi 

import sys
sys.path.append(r'D:\見解\Python\Python程式碼\學習\0411')
if __name__ == "__main__":
    # 執行檔案時,進行測試
    print(linecache.__file__)
    # F:\Python IDLE\lib\linecache.py
    
    print(pi)
    # 使用 math 中的 pi 屬性
    # 3.141592653589793
    import a
    # 匯入 0411 的 a.py 檔案
    a.show()
    # 我是 0411 的模組

以下部分內容為對以前內容的鞏固,部分存在重複現象.

異常 鞏固1

'''
1.索引異常
    IndexError: list index out of range

2.語法異常
    SyntaxError

3.縮排異常
    IndentationError: unexpected indent

4.try 語句完整形態:try except else finally

5.try 內的語句 出錯之後不會執行出現異常之後的 try 內語句

6.開發某些功能時 任何地方都可能會出錯
        通常引數傳遞過來時
        讀取某些未知檔案時
        開啟某個網頁時

7.except 捕獲正確的異常,對異常進行處理


程式:'''

# lst = [1,2,3,4,5]
# print(lst[5])
# 索引異常,不存在下標為 5 的元素
# IndexError: list index out of range

# print 444
# 語法異常
# SyntaxError
#  print(444)
 # 縮排異常
 # IndentationError: unexpected indent

lst = [1,2,3,4,5]
try :
    print(lst[5])
    print("出錯之後不會執行出現異常之後的語句")
except IndexError as e :
    '''try 出現異常時執行'''
    print("出現索引異常")
else:
    '''try 正常執行時執行'''
    print("程式執行 OK, 沒有問題")
finally:
    print("無論是否出錯一定會執行到 finally")

# 出現索引異常
# 無論是否出錯一定會執行到 finally

異常 鞏固2

'''
1.找到可能會丟擲異常的地方,僅對這幾行程式碼進行異常處理

2.明確會出現的異常型別
    縮排,型別,語法,索引等等

3.捕獲出現的異常
    import sys
    exc = sys.exc_info()
    exc[1] 為問題出現的原因

4.日誌 logging 模組
    import logging
    logger = logging.getLogger()
    # 獲取日誌物件
    logfile = 'test.log'
    hdlr = logging.FileHandler('senging.txt')
    # 儲存檔案日誌
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
    # 以什麼格式進行儲存,時間,等級,日誌資訊
    hdlr.setFormatter(formatter)
    # 匯入日誌格式
    logger.addHandler(hdlr)
    # 將日誌繫結
    logger.setLevel(logging.NOTSET)
    # 設定日誌級別

5.斷言 assert
    assert 表示式,出錯以後丟擲的提示資訊
    表示式 : 1 > 4   3 > 2  1 == 2
    斷言絕對不能發生的錯誤,然後再處理異常

程式:'''

import logging
logger = logging.getLogger()
# 獲取日誌物件
logfile = 'test.log'
hdlr = logging.FileHandler('senging.txt')
# 儲存檔案日誌
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
# 以什麼格式進行儲存,時間,等級,日誌資訊
hdlr.setFormatter(formatter)
# 匯入日誌格式
logger.addHandler(hdlr)
# 將日誌繫結
logger.setLevel(logging.NOTSET)
# 設定日誌級別

import sys
try:
    print(a)
except:
    exc = sys.exc_info()
    print(exc[1])
    # 檢視異常的問題
    # name 'a' is not defined
    print(exc[0])
    # <class 'NameError'>
    print(exc)
    # (<class 'NameError'>, NameError("name 'a' is not defined"),
         # <traceback object at 0x000002A8BD9DA188>)
    logging.debug(exc[1])

附:日誌這個還是很不錯的,以下為顯示的內容,會將錯誤儲存起來,便於以後的檢視
2020-07-25 09:51:01,344 DEBUG name 'a' is not defined

logging 日誌基礎

import logging
logger = logging.getLogger()
# 獲取日誌物件

logfile = 'test.log'
hdlr = logging.FileHandler('senging.txt')
# 儲存檔案日誌

formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
# 以什麼格式進行儲存,時間,等級,日誌資訊

hdlr.setFormatter(formatter)
# 匯入日誌格式

logger.addHandler(hdlr)
# 將日誌繫結

logger.setLevel(logging.NOTSET)
# 設定日誌級別

注:此處只是顯示了擁有哪些方法,具體例項還需要進行查閱相關資料

異常 鞏固3

'''
1.with open("檔案路徑","模式") as fp:
    操作
    
進入時 呼叫 __enter__ 方法
    def __enter__(self):
        print("開始執行 with 方法")
退出時 呼叫 __exit__ 方法
    def __exit__(self,type,value,traceback):
        print("退出 with 方法")
        
2.檔案操作方法:
    開啟、讀取、關閉
    d = open('a','r')
    d.read()
    d.close()
    
3.可以自己定義異常,繼承 Exception 類

程式:'''

# 檢視 with 執行的方法
class sth(object):

    def __enter__(self):
        print("開始執行 with 方法")

    def __exit__(self,type,value,traceback):
        print("退出 with 方法")

with sth( ) as fp:
    # with 自動關閉檔案
    pass


# 自定義異常
class myException(Exception):
    # 繼承 Exception
    def __init__(self,error,msg):
        self.args = (error,msg)
        self.error = error
        self.msg = msg
try:
    raise myException(1,'my exception')
except Exception as e :
    print(str(e))
    # (1, 'my exception')

多執行緒複習1
多執行緒複習1
'''
1.程序在執行時會建立一個主執行緒,每一個程序只有一個主執行緒

2.子程序 pid 唯一識別符號

3.任意時間裡,只有一個執行緒在執行,且執行順序不能確定(全域性鎖限制)

4.threading.Thread(target = test,args = [i])
    target = 函式名 ,args = [ 引數 ]

5.可以繼承 threading.Thread 然後重寫 run 方法
    class myThread(threading.Thread):
        def run():
            pass

程式:'''

import threading
# 匯入執行緒庫
def test():
    print(1)

a = threading.Thread(target = test)
# 建立 a 執行緒
b = threading.Thread(target = test)
a.start()
# 啟動執行緒
b.start()

a.join()
b.join()
# 結束之前使用 join 等待其他執行緒

import threading
# 匯入執行緒庫
import time
def test(i):
    time.sleep(0.1)
    print(i)

tests_thread = []
for i in range(0,10):
    threads = threading.Thread(target = test,args = [i])
    # 建立 a 執行緒
    tests_thread.append(threads)


for i in tests_thread:
    i.start()
    # 啟動執行緒


for i in tests_thread:
    i.join()
    # 結束之前使用 join 等待其他執行緒

print("執行緒結束")

'''
執行結果
2
0
1
8
7
9
6
534


執行緒結束
'''

多執行緒複習2

import time

def func_a():
    print("a 函式開始")
    time.sleep(2)
    print("a 函式結束")

def func_b():
    print("b 函式開始")
    time.sleep(2)
    print("b 函式結束")

b_time = time.time()
func_a()
func_b()
print(time.time() - b_time)
# 檢視執行多少秒
'''
執行結果:
a 函式開始
a 函式結束
b 函式開始
b 函式結束
4.00050163269043
'''
import threading
import time

def func_a():
    print("a 函式開始")
    time.sleep(2)
    print("a 函式結束")

def func_b():
    print("b 函式開始")
    time.sleep(2)
    print("b 函式結束")

b_time = time.time()

_a = threading.Thread(target = func_a)
_b = threading.Thread(target = func_b)
_a.start()
_b.start()
# 開始
_a.join()
_b.join()
# 等待
print(time.time() - b_time)
# 檢視時間
'''
執行結果:
a 函式開始
b 函式開始
b 函式結束a 函式結束

2.001542091369629
'''
通過使用了執行緒和不使用執行緒的對比,使用了執行緒的要快很多
執行緒裡面的加鎖和釋放鎖

# 加鎖和釋放
import threading
mlock = threading.Lock()
# 建立一把鎖, mlock 
# 當存在死鎖時,防止死鎖  可重用鎖
num = 0
def a():
    global num
    mlock.acquire()
    # 加鎖
    num += 1
    mlock.release()
    # 釋放鎖
    print(num)
for i in range(10):
    d = threading.Thread(target = a)
    d.start()

'''
1.協程,微型程序:
    yield 生成器
        yield 會儲存宣告的變數,可以進行迭代
    使用 接收函式返回的物件.__next__()
        next(接收函式返回的物件)
    .send() 方法
        傳遞給函式中 yield 宣告的物件
        x = yield i
        會發送給 x 變數
         如果一直沒有使用 send() ,x 值一直為 None
             賦值之後如果沒有修改則 x 一直為 send 後的值

2.此時 x 的值為 None ,並沒有將 i 賦值給 x
    x = yield i
程式:'''

# 建立一個包含 yield 宣告的函式
def test_yield():
    i = 0
    a = 4
    while i < a:
        x = yield i
        # x 通過 gener 進行賦值
        i += 1

# 使用 .__next__() 檢視迭代物件
gener = test_yield()

print(gener.__next__())
# 0
print(gener.__next__())
# 1
print(next(gener))
# 2
gener.send("x 通過 gener 進行賦值")
for i in test_yield():
    # i 在 test_yield 中 yield 宣告的迭代物件中
    print(i,end = " ")
# 0 1 2 3 

解決素數(質數)

def is_sushu(int_num):
    # 判斷輸入的數是否為質數
    if int_num == 1:
        return False
    if int_num == 2:
        return True
    else:
        for i in range(2,int_num):
            if int_num % i == 0:
                return False
        return True

def _get_sushu(max_num):
    return [i for i in range(1,max_num) if is_sushu(i)]
    # 使用列表推導式

if __name__ == "__main__":
    a = _get_sushu(101)
    # 返回判斷素數的列表
    print(a)

爬蟲流程複習

設定爬蟲終端:
    URL 管理器 -> 網頁下載器 -> 網頁解析器 -> 產生價值資料
    URL 管理器判斷爬取網頁連結
流程:
    排程器詢問 URL 管理器,是否存在要爬取的 URL 
        URL 管理器返回 是或否
    排程器 從 URL 管理器中 取出一個 URL 
        URL 管理器 將 URL 傳遞給排程器
    排程器將 URL 傳送到下載器
        下載器將 URL 下載的內容傳遞給排程器
    排程器將 URL 下載的內容傳遞給解析器
        解析器解析後傳遞給排程器
    此時可以收集價值資料 排程器再將需要爬取的 URL 傳遞給 URL管理器 一直到沒有需要爬取的 URL 

URL 管理器:
    管理待爬取的 URL 集合和已經爬取的 URL 集合
    使用管理器是為了防止重複抓取和防止重複抓取一個 URL

URL 功能:
    新增新的 URL 到待爬取的集合中
        確定待新增的 URL 是否在 URL 中
    獲取待爬取的 URL 
        將 URL 從待爬取的移動到已爬取的集合中
        判斷是否還有待爬取的資料

URL 管理器實現方式:
    將 待爬取的 和 已爬取的 URL 儲存在集合中 
        set()
    將 URL 儲存在 關係資料庫中,區分 URL 是待爬取還是已經爬取
        MySQL  urls(url,is_crawled)
    快取資料庫 redis

網頁下載器:

    將 URL 對應的網頁轉換為 HTML 資料
        儲存到本地檔案或者記憶體字串中
        requests 、 urllib 庫實現下載
    特殊情景處理器:
        需要使用 Cookie 訪問時:HTTPCookieProcessor
        需要使用 代理 訪問時:ProxyHandler
        需要使用 加密 訪問時:HTTPHandler
        網頁存在跳轉關係訪問時:HTTPRedirectHandler

網頁解析器:
    從網頁提取有價值的資料
    HTML 網頁文件字串
        提取出價值資料
        提取出新的 URL 列表
    正則表示式 -> 模糊匹配
        文件作為字串,直接匹配
    html.parser 
    BeautifulSoup -> 可以使用 html.parser  和 lxml
        從 HTML 和 XHTML 中提取資料
        語法:
            建立 BeautifulSoup 物件
                搜尋節點 findall find 
                訪問節點(名稱,屬性,文字)

    lxml
    ->結構化解析
        DOM 樹
            進行上下級的遍歷
        html 
            head 
            title
            文字
        body
            a
                href
                    文字
            div
                文字
                
爬蟲:
    確定目標
    分析目標
        URL 格式
            資料的連結
            資料的格式
            網頁編碼
    編寫程式碼
    執行爬蟲

列表常用方法複習:

列表的常用操作:
    1.使用 索引下標 或 切片 
        查詢對應元素的值
        修改特定位置上的值
    2.刪除列表元素
        del 物件
        物件.pop(index=-1)
        物件.remove(元素)
        物件.clear()

    3.檢視列表長度
        len(物件)
    4.重複 n 次
        物件 * n
    5.拼接兩個列表物件
        物件 + 物件
    6.檢視某一個元素是否在物件中
        元素 in 物件
    7.列表作為可迭代物件使用
        for i in 物件
        for i in range(len(物件))
    8.列表可以巢狀 
        [[],[],[]]
    9.列表內元素型別可以是任意型別
        [任意型別,任意型別]
    10.檢視列表中最大值 最小值
        max(物件)  min(物件)
    11.將其他型別資料轉換為列表物件
        list(物件)
        list(可迭代物件)
    12.在尾部增加元素
        整體新增 物件.append(元素)
        解包新增 物件.extend(元素)
    13.在任意位置新增
        物件.insert(index,元素)
    14.排序
        物件.sort()
        倒序 物件.reverse()
    15.檢視元素索引位置
        物件.index(元素)

字典常用操作複習

字典的常用操作:
    1.建立字典物件
        dict.fromkeys(seq[,value])
        dic = {key1:value1,key2,value2}
        dic = dict(zip([keys],[values]))
    2.使用 物件['鍵值'] 訪問字典元素
    3.修改字典
        物件['鍵值'] = 物件
    4.刪除字典元素或字典物件
        del 物件['鍵值']
        del 物件
        物件.clear()
        物件.pop(key)
        物件.popitem()
    5.獲取字典長度
        len(物件)
    6.複製字典
        物件.copy()
        物件.update(物件2)
    7.獲取指定鍵值的元素
        物件.get(key[,default=None])
    8.檢視 鍵 是否在字典中
        key in 物件
    9.獲取字典中的元素
        物件.keys()
        物件.values()
        物件.items()
    10.對某一個元素設定預設值 如果該鍵已有值 則設定無效
        物件.setdefault(key,default = None)

"089,0760,009"變為 89,760,9

remove_zeros = lambda s: ','.join(map(lambda sub: str(int(sub)), s.split(',')))

remove_zeros("089,0760,009")

Linux最常用的基本操作複習

1.ctrl + shift + =  放大終端字型
2.ctrl + - 縮小終端字型
3.ls 檢視當前資料夾下的內容
4.pwd 檢視當前所在的資料夾
5.cd 目錄名 切換資料夾
6.touch 如果檔案不存在 則建立檔案
    建立一個文件
7.mkdir 建立目錄
    建立一個資料夾
8.rm 刪除指定的檔名
9.clear 清屏

python連線資料庫 MySQLdb 版本


import MySQLdb
# 匯入 MySQL 庫

class MysqlMethod(object):
    def __init__(self):
        # 前提:能夠連線上資料庫
        self.get_connect()


    def get_connect(self):
        # 獲取連線
        try:
            self.conn = MySQLdb.connect(
            host = '127.0.0.1',
            # 主機
            user = 'root',
            # 使用者名稱
            passwd = 'root',
            # 密碼
            db = 'python_prac',
            # 資料庫
            port = 3306,
            # 埠號
            charset = 'utf8'
            # 避免字元編碼問題
        )
        except MySQLdb.Error as e:
            print("連線資料庫時,出現錯誤")
            print("錯誤資訊如下:\n %s"%e)
        else:
            print("連線 MySQL 成功!")


    def close_connect(self):
        # 關閉連線
        try:
            # 關閉連線
            self.conn.close()
            # 關閉資料庫連線
        except MySQLdb.Error as e:
            print("關閉資料庫時出現錯誤")
            print("錯誤資訊如下:\n %s"%e)
        else:
            print("退出成功,歡迎下次使用!")


    def get_onedata(self):
        # 獲取一條資料
        cursor = self.conn.cursor()
        # 獲取遊標
        sql = 'select * from students where age between %s and %s'
        # 查詢語句
        cursor.execute(sql,(15,25))
        # execute(語句,(引數))
        result = dict(zip([k[0] for k in cursor.description],cursor.fetchone()))
        '''
            zip(列表推導式,獲取到的值)
            字典的鍵:描述資料的值
            字典的值:獲取到的值
            例:
                lst_keys = ['a','b','c']
                lst_values = [1,2,3]
                dict(zip(lst_keys,lst_values))
            得到的結果:
                {'a': 1, 'b': 2, 'c': 3}
        '''
        # 元組型別轉換為字典,便於通過索引查詢資料
        print("獲取到一條資料:")
        return result

    def get_moredata(self,page,page_size):
        # 新增多條資料
        offset = (page - 1) * page_size
        # 起始位置
        cursor = self.conn.cursor()
        sql = 'select * from students where age between %s and %s limit %s,%s;'
        cursor.execute(sql,(15,45,offset,page_size))
        result = list(dict(zip([k[0] for k in cursor.description],row)) for row in cursor.fetchall())
        '''

            使用 zip 將 列名 和 獲取到的資料 壓縮為一個個單獨的二元組
                但型別為 <class 'zip'> 需要進行轉換才能看到具體的值
                zip([k[0] for k in cursor.description],row)
                    ('id', 1)···
            使用 dict 將 zip 型別轉換為字典型別
                dict(zip([k[0] for k in cursor.description],row))
                    {'id': 1,···}
            使用 列表推導式 將每一個 row 變為查詢到的多個數據中的一個
                原理:[元素操作 for 元素 in 序列物件]
                list -> []
                list[ row 的操作 for row in 資料集]
        '''
        print("獲取到多條資料:")
        # result 為[{},{}] 形式
        return result

    def insert_onedata(self):
        # 新增一條資料
        try:
            sql = "insert into stu_0415(name,school) values (%s,%s);"
            # 查詢語句
            cursor = self.conn.cursor()
            # 獲取遊標
            need_info = ('王五','廈大')
            # 需要插入的資料
            cursor.execute(sql,need_info)
            # 執行 sql 語句
            self.conn.commit()
            # 提交,如果沒有提交,資料庫資料不會發生變化
        except :
            print("插入資料失敗")
            self.conn.rollback()
            # 如果個別資料插入成功了,則也不算入資料庫
        print("插入資料成功")

def main():
    sql_obj = MysqlMethod()
    # 建立一個 sql 物件
    data = sql_obj.get_onedata()
    # 獲取一條資料
    print(data)

    moredata = obj.get_moredata(1,5)
    # 檢視 0~5 的資料
    for item in moredata:
        print(item)
        # 迴圈遍歷輸出字典物件
        print("-------------")
    obj.insert_onedata()
    # 插入一條資料

if __name__ == '__main__':
    main()
    # 執行主程式

顯示列表重複值

lst = [1,2,3,2,1,5,5]

lst = list(filter(lambda x:lst.count(x) != 1,lst))
此處使用了 filter 和 lambda 進行混合使用,
x 為 lst 中的元素

應用場景

列表常用場景:
    儲存不同型別的資料
        任意型別均可
    列表儲存相同型別的資料
        類 node結點 next、data
    通過迭代遍歷,在迴圈體內部(多為 while 內),對列表的每一項都進行遍歷
        樹的深度遍歷等等
    列表推導式的使用等等

元組常用場景:
    作為函式的引數和返回值
        傳遞任意多個引數 *args
            函式內為元組形式
        一次返回多個數據
             return (a,b) 或 a,b
             return a,b,c
             接收函式返回值時
                value1,value2 = 函式(引數)
                    函式(引數)即為 return (a,b)
    格式化字串
        s1 = "%s %s"
        s2 = ('hello','world')
        s1%s2
            'hello world'
    資料庫execute語句
        cursor.execute(sql,(15,25))
    讓列表不可以被修改,保護資料
        tuple(list物件)

字典常用場景:
    for in 遍歷字典
        dic = {'a':1,'b':2,'c':3}
        遍歷鍵值:
        for key in dic.keys():
            print(key,end = " ")
        遍歷值:
        for value in dic.values():
            print(value,end = " ")
        遍歷鍵值對:
        for key,value in dic.items():
            print(key,":",value,end = " ")
    使用字典(多個鍵值對)儲存一個物體的資訊
        {"name":"張三","age":23}
    將多個字典放到列表中,迴圈時對每一個字典進行相同操作
        students_info = [{"name":"張三","age":23},{"name":"李四","age":22}]
        訪問張三資料:
            students_info[0]['name']
        操作 for i in range(len(students_info)):
                students_info[i] 即可進行操作資料
            for stu in students_info:
                print(stu)  輸出的為單個字典元素

類 擴充套件

關於類和物件的理解:
    類 -> 設計圖紙,設計應該具有哪些屬性和行為
    物件 -> 使用圖紙製造出來的模型

類中定義普通方法,第一個引數為 self
    self可以修改為別的,但最好還是不要改變,約定好的
    self.屬性 self.方法 呼叫 self 指向的物件的屬性和行為

在類外可以為例項化物件直接建立屬性,但是該屬性只適用於該物件
    不推薦使用,如果一定要使用,必須先建立屬性,後使用方法

在 __init__(self,..) 初始化方法內,定義屬性初始值有利於表達屬性,定義方法

列印類的例項化物件時,實際呼叫的是 類中的 __str__方法
    __str__必須返回字串,可以自己定義

如果例項化物件 先使用 del 方法刪除了,那麼不會再執行類中的 __del__方法

保護私有公有物件,保護私有共有方法 在方法內都可以呼叫

先開發被使用的類,被包含操作的類

複習 裝飾器

'''
裝飾器的作用
    引入日誌
    函式執行時間的統計
    執行函式前預備處理
    執行函式後清理功能
    許可權校驗等場景
    快取
'''

# 定義一個函式,遵循閉包原則(函式作為引數)
def decorator(func):
    '''定義一個裝飾器函式'''
    print("func 函式開始")
    def wrapper():
        # 建立裝飾器內容
        print("進行裝飾")
        func()
        print("裝飾完畢")
    print("func 函式結束")
    return wrapper

@decorator
# 載入 wrapper 函式,將 wrapper 函式傳遞給使用裝飾器的函式
def house():
    print("大房子")

house()
'''
執行結果:
func 函式開始
func 函式結束
進行裝飾
大房子
裝飾完畢
'''

re 正則表示式練習
字串重複出現

'''
有一段英文文字,其中有單詞連續重複了 2 次,編寫程式檢查重複的單詞並只保留一個
例: This is a a desk.
輸出 This is a desk.
'''

# 方法一
import re
x = 'This is a a desk.'
# 設定字串
pattern = re.compile(r'\b(\w+)(\s+\1){1,}\b')
# \b 匹配單詞和空格間的位置
# \w 匹配包括下劃線的任何單詞字元 [A-Za-z0-9_]
# \s 匹配任何空白字元
# {1,} 大於 1 個
matchResult = pattern.search(x)
# 查詢這樣的結果
x = pattern.sub(matchResult.group(1),x)
# sub 進行替換字元
# group(1) 為 a   group(0) 為 a a
print(x)
# This is a desk.


# 方法二
import re
x = 'This is a a desk.'
# 設定字串
pattern = re.compile(r'(?P<f>\b\w+\b)\s(?P=f)')
# # \b 匹配單詞和空格間的位置
# \w 匹配包括下劃線的任何單詞字元 [A-Za-z0-9_]
matchResult = pattern.search(x)
# 匹配到 a a
x = x.replace(matchResult.group(0),matchResult.group(1))
# 字串物件.replace(舊字串,新字串)
# print(matchResult.group(0))
# a a
# print(matchResult.group(1))
# a
print(x)
# This is a desk.

最基本的Tkinter介面操作

'''
1.建立應用程式主視窗物件
    root = Tk()
    
2.在主視窗中,新增各種視覺化元件
    btn1 = Button(root)
    btn1["text"] = "點我"
    
3.通過幾何佈局管理器,管理元件得大小和位置
    btn1.pack()
    
4.事件處理
    通過繫結事件處理程式,響應使用者操作所觸發的事件
    def songhua(e):
        messagebox.showinfo("Message","送你一朵玫瑰花")
        print("送花花")
    btn1.bind("<Button-1>",songhua)
    
5.Tk() 的物件.mainloop() 方法會一直進行事件迴圈,監聽使用者操作

6.Button() 元件的引數為 Tk() 物件
    Button() 的例項化物件 ["text"] 內容為顯示在按鈕上的內容
    
7.from tkinter import messagebox  顯示點選之後提示的視窗
    messagebox.showinfo("Message","送你一朵玫瑰花")
    第一個引數為  標題
    第二個引數為  顯示資訊
    
8.btn1.bind("<Button-1>",songhua)
    使用建立好的按鈕物件繫結滑鼠事件和對應需要執行的函式
    
9.root.mainloop() 事件迴圈,一直監聽使用者操作

程式:'''

from tkinter import *
from tkinter import messagebox
root = Tk()
# 建立一個視窗物件

btn1 = Button(root)

btn1["text"] = "Submit"

btn1.pack()
# 將元件物件合理的放在視窗中
def songhua(e):
    # e 為事件 event
    messagebox.showinfo("Message","送你一朵玫瑰花")
    print("送花花")
btn1.bind("<Button-1>",songhua)
# <Button-1> 表示滑鼠左鍵單擊
root.mainloop()
# root.mainloop() 事件迴圈,一直監聽使用者操作

Tkinter經典寫法

'''
1.繼承 tkinter.Frame 類,實現類的基本寫法

2.建立 主視窗 及 主視窗大小 位置 及 標題

3.將需要新增的元件放入到類中進行建立,
    繼承的 Frame 類需要使用 master 引數作為父類的初始化使用

4.初始化時,將屬性和方法都進行初始化,此時可以將 GUI 程式所要實現的功能確定好

5.在類中定義事件發生時,需要實現的功能

6.self.btn1["command"] = self.kuaJiang
    btn1["command"] 為事件發生時進行相應的函式

7.self.btnQuit = Button(self,text = "退出",command = root.destroy)
    退出按鈕的寫法
'''

from tkinter import *
from tkinter import messagebox


class Application(Frame):
    '''GUI程式經典寫法'''
    def __init__(self,master = None):
        super().__init__(master)
        # super() 表示父類的定義,父類使用 master 引數
        self.master = master
        # 子類定義一個屬性接收傳遞過來的 master 引數
        self.pack()
        # .pack 設定佈局管理器
        self.createWidget()
        # 在初始化時,將按鈕也實現
        # master傳遞給父類 Frame 使用後,子類中再定義一個 master 物件

    def createWidget(self):
        '''建立元件'''
        self.btn1 = Button(self)
        # self 為元件容器
        self.btn1["text"] = "Hany love Python."
        # 按鈕的內容為 btn1["text"]定義的內容
        self.btn1.pack()
        # 最佳位置
        self.btn1["command"] = self.kuaJiang
        # 響應函式

        self.btnQuit = Button(self,text = "退出",command = root.destroy)
        # 設定退出操作
        self.btnQuit.pack()

    def kuaJiang(self):
        messagebox.showinfo("人艱不拆","繼續努力,你是最棒的!")

if __name__ == '__main__':
    root = Tk()
    # 定義主視窗物件
    root.geometry("200x200+200+300")
    # 建立大小
    root.title("GUI 經典寫法")

    app = Application(master = root)
    # 傳遞 master 引數為 主視窗物件
    root.mainloop()

Label 元件基本寫法

'''
1.width,height 指定區域大小
    文字 漢字 2 個位元組

2.font 指定字型和字型大小
    font(font_name,size)

3.image 顯示在 Label 上的影象 支援 gif 格式

4.fg 前景色

5.bg 背景色

6.justify 針對多行文字的對齊
    left    center  right

7.self.lab1 = Label(self,text = "Label實現",width = 10,height = 2,
                        bg = 'black',fg = 'white')

8.  photo_gif = PhotoImage(file = "images/小熊.gif")
    self.lab3 = Label(self,image = photo_gif)
    將照片傳遞給 photo_gif 然後使用 Label 將圖片變數作為引數進行傳遞

9.self.lab4 = Label(self,text = " Hany加油\n 人艱不拆!"
                    ,borderwidth = 1,relief = "solid",justify = "right")
    borderwidth 設定文字線的寬度  justify 表示左對齊 右對齊

'''

from tkinter import *

class Application(Frame):
    '''GUI程式經典寫法'''
    def __init__(self,master = None):
        super().__init__(master)
        # super() 表示父類的定義,父類使用 master 引數
        self.master = master
        # 子類定義一個屬性接收傳遞過來的 master 引數
        self.pack()
        # .pack 設定佈局管理器
        self.createWidget()
        # 在初始化時,將按鈕也實現
        # master傳遞給父類 Frame 使用後,子類中再定義一個 master 物件

    def createWidget(self):
        '''建立元件'''
        self.lab1 = Label(self,text = "Label實現",width = 10,height = 2,
                        bg = 'black',fg = 'white')
        self.lab1.pack()
        self.lab2 = Label(self,text = "Labe2實現",width = 10,height = 2,
                        bg = 'black',fg = 'white',font = ("宋體",14))
        self.lab2.pack()
        # 顯示影象
        global photo_gif
        # 將 photo_gif 設定為全域性變數,防止方法呼叫後銷燬
        photo_gif = PhotoImage(file = "路徑/圖片名.gif")
        self.lab3 = Label(self,image = photo_gif)
        self.lab3.pack()

        # 顯示多行文字
        self.lab4 = Label(self,text = " Hany加油\n 人艱不拆!"
                    ,borderwidth = 1,relief = "solid",justify = "right")
        self.lab4.pack()


if __name__ == '__main__':
    root = Tk()
    # 定義主視窗物件
    root.geometry("300x300+400+300")
    # 建立大小
    root.title("Label 測試")
    # 設定標題
    app = Application(master = root)
    # 傳遞 master 引數為 主視窗物件
    root.mainloop()

注:圖片路徑和圖片要修改為自己的

類例項化的物件呼叫的方法或屬性來自於類的哪個方法中

__init__ 構造方法 物件建立 p = Person()
__del__ 析構方法 物件回收 
__repr__ , __str__ 列印,轉換 print(a) 
__call__ 函式呼叫 a() 
__getattr__ 點號運算 a.xxx 
__setattr__ 屬性賦值 a.xxx = value 
__getitem__ 索引運算 a[key] 
__setitem__ 索引賦值 a[key]=value 
__len__ 長度 len(a)
每個運算子實際上都對應了相應的方法

運算子+ __add__ 加法
運算子- __sub__ 減法
<,<=,== __lt__,__le__,__eq__ 比較運算子 
>,>=,!= __gt__,_ ge__,__ne__ 比較運算子 
|,^,& __or__,__xor__,__and__ 或,異或,與 
<<,>>__lshift__,__ rshift__ 左移,右移
*,/,%,// __mul__,__truediv__,__mod__,__floordiv__ 乘,浮點除,模運算(取餘),整數除
** __pow__ 指數運算

tkinter Button基本用語

'''
1.self.btn2 = Button(root,image = photo,command = self.login)
    使用 image 圖片作為按鈕,command 作為響應

2.self.btn2.config(state = "disabled")
    對按鈕進行禁用
3.Button 中 anchor 控制按鈕上的圖片位置
    N NE E SE SW W NW CENTER
    預設居中

'''
from tkinter import *
from tkinter import messagebox

class Application(Frame):
    '''GUI程式經典寫法'''
    def __init__(self,master = None):
        super().__init__(master)
        # super() 表示父類的定義,父類使用 master 引數
        self.master = master
        # 子類定義一個屬性接收傳遞過來的 master 引數
        self.pack()
        # .pack 設定佈局管理器
        self.createWidget()
        # 在初始化時,將按鈕也實現
        # master傳遞給父類 Frame 使用後,子類中再定義一個 master 物件

    def createWidget(self):
        '''建立元件'''
        self.btn1 = Button(root,text = '登入',command = self.login,
            width = 5,height = 2,anchor = E)
        # command 進行操作的函式
        self.btn1.pack()

        global photo
        photo = PhotoImage(file = "圖片路徑/圖片名.gif")
        self.btn2 = Button(root,image = photo,command = self.login)
        self.btn2.pack()

        # self.btn2.config(state = "disabled")
        # # 設定按鈕為禁用按鈕

    def login(self):
        messagebox.showinfo("部落格園","歡迎使用~")

if __name__ == '__main__':
    root = Tk()
    # 定義主視窗物件
    root.geometry("300x300+400+300")
    # 建立大小
    root.title("Button 測試")
    # 設定標題
    app = Application(master = root)
    # 傳遞 master 引數為 主視窗物件
    root.mainloop()

tkinter Entry基本用法

'''
1.BooleanVar()  布林型別

2.IntVar()  整數型別

3.DoubleVar()   浮點數型別

4.StringVar()   字串型別

5.self.entry1 = Entry(self,textviable = v1)
    textviable 實現雙向關聯
    
6.v1.set("admin")
        # 設定單行文字的值
        
7.v1.get()  self.entry1.get() 獲取的是單行文字框中的值

8.self.entry_passwd = Entry(self,textvariable = v2,show = "*")
    textvariable 進行繫結 v2
        v2 = StringVar()
    使用者輸入後,show 顯示為 *
    
9.Button(self,text = "登入",command = self.login).pack()
    登入操作
    
10.點選登陸後執行的函式可以與資料庫進行互動,達到驗證的目的
    self.元件例項化物件.get() 獲取值
    
'''
from tkinter import *
from tkinter import messagebox

class Application(Frame):
    '''GUI程式經典寫法'''
    def __init__(self,master = None):
        super().__init__(master)
        # super() 表示父類的定義,父類使用 master 引數
        self.master = master
        # 子類定義一個屬性接收傳遞過來的 master 引數
        self.pack()
        # .pack 設定佈局管理器
        self.createWidget()
        # 在初始化時,將按鈕也實現
        # master傳遞給父類 Frame 使用後,子類中再定義一個 master 物件

    def createWidget(self):
        '''建立元件'''
        self.lab1 = Label(self,text = "使用者名稱")
        self.lab1.pack()
        # StringVar() 繫結到指定的元件,StringVar 和 v1 一起變化
        v1 = StringVar()
        self.entry_user = Entry(self,textvariable = v1)
        self.entry_user.pack()
        v1.set("admin")
        # 設定單行文字的值
        # v1.get()    self.entry_user.get() 獲取的是單行文字框中的值

        # 建立密碼框
        self.lab2 = Label(self,text = "密碼")
        self.lab2.pack()

        v2 = StringVar()
        self.entry_passwd = Entry(self,textvariable = v2,show = "*")
        self.entry_passwd.pack()

        Button(self,text = "登入",command = self.login).pack()

    def login(self):
        username = self.entry_user.get()
        passwd = self.entry_passwd.get()
        # 資料庫進行操作,檢視是否存在該使用者
        print("使用者名稱:" + username)
        print("密碼:" + passwd)
        if username == "Hany" and passwd == "123456":
            messagebox.showinfo("部落格園","歡迎使用~")
        else:
            messagebox.showinfo("Error","請重新輸入~")

if __name__ == '__main__':
    root = Tk()
    # 定義主視窗物件
    root.geometry("300x300+400+300")
    # 建立大小
    root.title("Button 測試")
    # 設定標題
    app = Application(master = root)
    # 傳遞 master 引數為 主視窗物件
    root.mainloop()
此處的使用者名稱是 Hany , 密碼是 123456

Text多行文字框基本用法

#coding=gbk

'''
1.Text(root,width,height,bg)
    主視窗,寬度,高度,背景色
    
2.使用 .insert() 方法新增內容
    Text 物件.insert(幾行.幾列,"內容")
        w1.insert(2.3,"···")
        END 為最後位置
            self.w1.insert(END,'[end]')
            
3.Button(視窗物件,text = "內容",command = "self.函式名").pack([side = "left"])
    Button(self,text = "返回文字",command = self.returnText).pack(side = "left")
    text 顯示的內容  command 執行的函式  pack 位置,使用 side 後,按鈕按照 pack 來
    
4.在類中定義的屬性,不會因為執行函式方法後,就銷燬
    self.photo 不用再使用 global 進行宣告
    
5.使用 PhotoImage 將圖片存起來後,將圖片顯示在多行文字 Text 中
    self.photo = PhotoImage(file = '圖片路徑/圖片名.gif')
        self.photo = PhotoImage(file = 'images/logo.gif')
    使用 .image_create(位置,image = self.photo) 進行新增
        self.w1.image_create(END,image = self.photo)
        
6.新增按鈕元件到文字中
    btn1 = Button(文字內容,text = "內容")
    
7.self.w1.tag_config (內容,background 背景顏色,foreground 文字顏色)

8.self.w1.tag_add("內容",起始位置,終止位置)
    tag_add 加入內容
    
9.self.w1.tag_bind("內容","事件",self.函式名)
    self.w1.tag_bind("baidu","<Button-1>",self.webshow)
    
10.webbrowser.open("網址")
    開啟一個網址

'''

from tkinter import *
from tkinter import messagebox
# 顯示訊息
import webbrowser
# 匯入 webbrowser 到時候點選字型跳轉使用

class Application(Frame):
    '''GUI程式經典寫法'''
    def __init__(self,master = None):

        super().__init__(master)
        # super() 表示父類的定義,父類使用 master 引數
        self.master = master
        # 子類定義一個屬性接收傳遞過來的 master 引數
        self.pack()
        # .pack 設定佈局管理器
        self.createWidget()
        # 在初始化時,將按鈕也實現
        # master傳遞給父類 Frame 使用後,子類中再定義一個 master 物件

    def createWidget(self):
        '''建立元件'''
        # 建立文字 Text(root 主視窗物件,width 寬度,height 高度,bg 背景色)
            # 只對於文字有效
        self.w1 = Text(root,width = 100,height = 40,bg = "gray")
        # 設定背景色 bg = "gray"
        self.w1.pack()

        self.w1.insert(1.0,"0123456789\nabcdefg")
        # 1.0 在 第一行 第零列 插入資料
        self.w1.insert(2.3,"活在當下\n結髮為夫妻,恩愛兩不疑\n言行在於美,不在於多")
        # 2.3 在 第二行 第三列


        Button(self,text = "重複插入文字",command = self.insertText).pack(side = "left")
        # 水平排列 side = "left"
        Button(self,text = "返回文字",command = self.returnText).pack(side = "left")
        Button(self,text = "新增圖片",command = self.addImage).pack(side = "left")
        Button(self,text = "新增元件",command = self.addWidget).pack(side = "left")
        Button(self,text = "通過 tag 控制文字",command = self.testTag).pack(side = "left")

    def insertText(self):
        '''INSERT 索引表示在游標處插入'''
        self.w1.insert(INSERT,'Hany')
        # END 索引號表示在最後插入
        self.w1.insert(END,'[end]')
        # 在文字區域最後
        self.w1.insert(1.2,"(.-_-.)")


    def returnText(self):
        '''返回文字內容'''
        # Indexes(索引) 是用來指向 Text 元件中文字的位置
        # Text 的元件索引 也是對應實際字元之間的位置
        # 核心:行號從 1 開始,列號從 0 開始
        print(self.w1.get(1.2,1.6))

        print("文字內容:\n" + self.w1.get(1.0,END))


    def addImage(self):
        '''增加圖片'''
        self.photo = PhotoImage(file = 'images/logo.gif')
        self.w1.image_create(END,image = self.photo)


    def addWidget(self):
        '''新增元件'''
        btn1 = Button(self.w1,text = "Submit")
        self.w1.window_create(INSERT,window = btn1)
        # 新增元件


    def testTag(self):
        '''將某一塊作為特殊標記,並使用函式'''
        self.w1.delete(1.0,END)
        self.w1.insert(INSERT,"Come on, you're the best.\n部落格園\nHany 加油!!!")
        # self.w1.tag_add("good",1.0,1.9)
        # 選中標記區域
        # self.w1.tag_config("good",background = "yellow",foreground = "red")
        # 單獨標記某一句,背景色 字型色
        self.w1.tag_add("baidu",3.0,3.4)
        #
        self.w1.tag_config("baidu",underline = True,background = "yellow",foreground = "red")
        self.w1.tag_bind("baidu","<Button-1>",self.webshow)


    def webshow(self,event):
        webbrowser.open("http://www.baidu.com")


if __name__ == '__main__':
    root = Tk()
    # 定義主視窗物件
    root.geometry("500x300+400+300")
    # 建立大小
    root.title("Button 測試")
    # 設定標題
    app = Application(master = root)
    # 傳遞 master 引數為 主視窗物件
    root.mainloop()
    

Radiobutton基礎語法

'''
1.Radiobutton(root 主視窗,text 文字內容,value 值(可以通過set 和 get 獲取到的值),variable 變數修改原來的StringVar)
    self.radio_man = Radiobutton(root,text = "男性",value = "man",variable = self.v)
2.Button(root,text = "提交",command = self.confirm).pack(side = "left")
        設定按鈕進行提交,然後響應的函式

'''
from tkinter import *
from tkinter import messagebox

class Application(Frame):
    '''GUI程式經典寫法'''
    def __init__(self,master = None):
        super().__init__(master)
        # super() 表示父類的定義,父類使用 master 引數
        self.master = master
        # 子類定義一個屬性接收傳遞過來的 master 引數
        self.pack()
        # .pack 設定佈局管理器
        self.createWidget()
        # 在初始化時,將按鈕也實現
        # master傳遞給父類 Frame 使用後,子類中再定義一個 master 物件

    def createWidget(self):
        '''建立元件'''
        self.v = StringVar()
        #String型別
        self.v.set("man")
        # 預設為 man 選中
        self.radio_man = Radiobutton(self,text = "男性",value = "man",variable = self.v)
        # Radiobutton(root/self 主視窗,text 文字內容,value 值(可以通過set 和 get 獲取到的值),variable 變數修改原來的StringVar()變數也修改)
        self.radio_woman = Radiobutton(self,text = "女性",value = "woman",variable = self.v)

        self.radio_man.pack(side = "left")
        self.radio_woman.pack(side = "left")
        # 放到最佳位置
        Button(self,text = "提交",command = self.confirm).pack(side = "left")
        # 設定按鈕進行提交,然後響應的函式

    def confirm(self):
        messagebox.showinfo("選擇結果","選擇的性別是 : "+self.v.get())
        # 兩個引數,一個是標題另一個是內容
        # 顯示內容

if __name__ == '__main__':
    root = Tk()
    # 定義主視窗物件
    root.geometry("300x100+400+300")
    # 建立大小
    root.title("Button 測試")
    # 設定標題
    app = Application(master = root)
    # 傳遞 master 引數為 主視窗物件
    root.mainloop()

Checkbutton基本寫法

'''
1.Checkbutton(self 視窗物件,text 按鈕顯示內容,variable 繫結變數->一起變化,
                 onvalue 使用者點選時得到的值,offvalue 沒有點選得到的值)
    self.choose1 = Checkbutton(self,text = "玩遊戲",variable = self.playHobby,
                    onvalue = 1,offvalue = 0)
2.self.playHobby.get() == 1 :
    .get() 獲取到值 判斷是否時 onvalue 的值
'''

from tkinter import *
from tkinter import messagebox

class Application(Frame):
    '''GUI程式經典寫法'''
    def __init__(self,master = None):
        super().__init__(master)
        # super() 表示父類的定義,父類使用 master 引數
        self.master = master
        # 子類定義一個屬性接收傳遞過來的 master 引數
        self.pack()
        # .pack 設定佈局管理器
        self.createWidget()
        # 在初始化時,將按鈕也實現
        # master傳遞給父類 Frame 使用後,子類中再定義一個 master 物件

    def createWidget(self):
        '''建立元件'''

        self.playHobby = IntVar()
        # 預設為 0
        #  .get() 獲取值   .set() 設定值
        self.travelHobby = IntVar()
        self.watchTvHobby = IntVar()

        # print(self.playHobby.get())  0

        self.choose1 = Checkbutton(self,text = "玩遊戲",variable = self.playHobby,
                    onvalue = 1,offvalue = 0)
        # Checkbutton(self 視窗物件,text 按鈕顯示內容,variable 繫結變數->一起變化,
        #                 onvalue 使用者點選時得到的值,offvalue 沒有點選得到的值)
        self.choose2 = Checkbutton(self,text = "去旅遊",variable = self.travelHobby,
                    onvalue = 1,offvalue = 0)
        self.choose3 = Checkbutton(self,text = "看電影",variable = self.watchTvHobby,
                    onvalue = 1,offvalue = 0)

        self.choose1.pack(side = "left")
        self.choose2.pack(side = "left")
        self.choose3.pack(side = "left")

        Button(self,text = "確定",command = self.confirm).pack(side = "left")

    def confirm(self):

        if self.playHobby.get() == 1 :
            # 獲取到的資料是 1 的話,進行接下來的操作
            messagebox.showinfo("假期專案","玩遊戲----")
        if self.travelHobby.get() == 1 :
            messagebox.showinfo("假期專案","去旅遊----")
        if self.watchTvHobby.get() == 1 :
            messagebox.showinfo("假期專案","看電影----")


if __name__ == '__main__':
    root = Tk()
    # 定義主視窗物件
    root.geometry("300x200+400+300")
    # 建立大小
    root.title("Button 測試")
    # 設定標題
    app = Application(master = root)
    # 傳遞 master 引數為 主視窗物件
    root.mainloop()

# 一行程式碼合併字典
# {**{'鍵':'值','鍵':'值'},**{'鍵','值'}}
dic = {**{'a':1,'b':2},**{'c':3},**{'d':4}}
print(dic)
# {'a': 1, 'b': 2, 'c': 3, 'd': 4}

# 一行程式碼檢視多個列表最大值
print(max([[1,2,3],[4,5,7,8],[6]],key = lambda v:max(v)))
# [4, 5, 7, 8]
print(max(max([[1,2,3],[4,5,7,8],[6]],key = lambda v:max(v))))
# 8

整理上課內容

載入資料集
sklearn.datasets 集成了部分資料分析的經典資料集·
load_boston 迴歸
load_breast_cancer 分類 聚類
fetch_california_housing 迴歸
load_iris 分類 聚類
load_digits 分類
load_wine 分類

from sklearn.datasets import load_breast_cancer
cancer=load_ breast_cancer()
print('breast_cancer資料集的長度為:',len(cancer))
print('breast_cancer資料集的型別為:',type(cancer))
資料集可以看作字典
可以使用 data target feature_names DESCR
分別獲取資料集的資料 標籤 特徵名稱 描述資訊
cancer['data'] cancer['target']
cancer['feature_names'] cancer['DESCR']

將樣本分為三部分
    訓練集(train set)用於估計模型
    驗證集(validation set) 用於確定 網路結構 或 控制模型複雜程度 的引數
    測試集(test set) 檢驗最優的模型的效能
佔比
    50%  25%  %25
通過一些資料建立一些模型 通過模型可以將新資料分組

K折交叉驗證法
常用的方法是留少部分做測試集
    對其餘 N 個樣本採用 K 折交叉驗證法
    將樣本打亂 均勻分成K份。
    輪流選擇其中 K-1 份做訓練 剩餘的一份做驗證。
    計算預測誤差平方和 把K次的預測誤差平方和的均值作為選擇最優模型結構的依據

對資料集進行拆分
sklearn.model_selection 的 train_test_split 函式
引數
    *arrays 接收一個或多個需要劃分的資料集
            分類->資料和標籤
            聚類->資料
    test_size 接收 float int None 資料
                表示測試集的大小
            float 型別  0-1 之間 表示測試集在總數中的佔比
            int 型別 表示測試集的絕對數目
            test_size 預設為 25%
    train_size 接收 float int None 型別的資料
            表示訓練集的大小 和 test_size 只能有一個
    random_state 接收 int 型別 表示隨機種子的編號
            相同隨機種子編號產生相同的隨機結果
            不同的隨機種子編號產生不同的隨機結果
    shuffle 接收布林型別 代表是否進行有放回抽樣’
    stratify 接收 array標籤 或者 None
            使用標籤進行分層抽樣

train_test_split 函式根據傳入的資料
    分別將傳入的資料劃分為訓練集和測試集
如果傳入的是1組資料,那麼生成的就是這一組資料隨機劃分後訓練集和測試集
如果傳入的是2組資料,則生成的訓練集和測試集分別2組

將breast_cancer資料劃分為訓練集和測試集
from sklearn.model_selection import train_test_split
cancer_data_train,cancer_data_test,cancer_target_train,cancer_target_test
= train_test_split(cancer_data,cancer_target,test_size=0.2,random_state=42)
.shape 檢視形狀

numpy.max() 檢視最大值

使用 sklearn 轉換器
    fit 分析特徵和目標值,提取有價值的資訊 如 統計量 或 權值係數等。
    transform 對特徵進行轉換
        無資訊轉換 指數和對數函式轉換等
        有資訊轉換
            無監督轉換
                只利用特徵的統計資訊 如 標準化 和 PCA 降維
            有監督轉換
                利用 特徵資訊 和 目標值資訊 如通過模型->選擇特徵 LDA降維等
    fit_tranform 先呼叫 fit 方法 然後呼叫 transform 方法

使用 sklearn 轉換器 能夠實現對傳入的 Numpy陣列
    進行標準化處理、歸一化處理、二值化處理、PCA降維等操作
注 各類特徵處理相關的操作都要將 訓練集和測試集 分開
    將訓練集的操作規則、權重係數等應用到測試集中

.shape 檢視形狀

sklearn 提供的方法
    MinMaxScaler 對特徵進行離差標準化
    StandardScaler 對特徵進行標準差標準化
    Normalizer 對特徵進行歸一化
    Binarizer 對定量特徵進行二值化處理
    OneHotEncoder 對定性特徵進行獨熱編碼處理
    Function Transformer 對特徵進行自定義函式變換

from sklearn.decomposition import PCA
PCA 降維演算法常用引數及作用
    n_components 接收 None int float string 引數
        未指定時,代表所有特徵都會保留下來
        int -> 降低到 n 個維度
        float 同時 svd_solver 為full
        string  如 n_components='mle'
            自動選取特徵個數為 n 滿足所要求的方差百分比 預設為 None

    copy 接收 布林型別資料
        True 執行後 原始資料不會發生變化
        False 執行 PCA 演算法後,原始資料 會發生變化
        預設為 True

    whiten 接收 布林型別資料
        表示白化 對降維後的資料的每個特徵進行歸一化
        預設為 False

    svd_solver 接收 'auto' 'full' 'arpack' 'randomized'
        預設為auto
        auto 代表PCA類會自動在上述三種演算法中去權衡 選擇一個合適的SVD演算法來降維
        full 使用SciPy庫實現的傳統SVD演算法
        arpack 和randomized的適用場景類似
            區別是 randomized 使用的是 sklearn 的SVD實現
                而arpack直接使用了 SciPy 庫的 sparse SVD實現
        randomized 一般適用於資料量大 資料維度多 同時主成分數目比例又較低的PCA降維 使用一些加快SVD的隨機演算法

聚類分析 在沒有給定 劃分類別 的情況下,根據 資料相似度 進行樣本分組的一種方法
聚類模型 可以將 無類標記的資料 聚集為多個簇 視為一類 是一種 非監督的學習演算法
聚類的輸入是 一組未被標記的樣本
    根據 自身的距離 或 相似度 將他們劃分為若干組
    原則 組內樣本最小化 組間距離最大化

常用的聚類演算法
    劃分方法
        K-Means演算法(K-平均)
        K-MEDOIDS演算法(K-中心點)
        CLARANS演算法(基於選擇的演算法)

    層次分析方法
        BIRCH演算法(平衡送代規約和聚類)
        CURE演算法(代表點聚類)
        CHAMELEON演算法(動態模型)

    基於密度的方法
        DBSCAN演算法(基於高密度連線區域)
        DENCLUE演算法(密度分佈函式)
        OPTICS演算法(物件排序識別)

    基於網格的方法
        STING演算法(統計資訊網路)
        CLIOUE演算法(聚類高維空間)
        WAVE-CLUSTER演算法(小波變換)

sklearn.cluster 提供的聚類演算法
    函式名稱  K-Means
    引數  簇數
    適用範圍  樣本數目很大 聚類數目中等
    距離度量  點之間的距離

    函式名稱  Spectral clustering
    引數  簇數
    適用範圍  樣本數目中等 聚類數目較小
    距離度量  圖距離

    函式名稱  Ward hierarchical clustering
    引數  簇數
    適用範圍  樣本數目較大 聚類數目較大
    距離度量  點之間的距離

    函式名稱  Agglomerative clustering
    引數  簇數 連結型別 距離
    適用範圍  樣本數目較大 聚類數目較大
    距離度量  任意成對點線圖間的距離

    函式名稱  DBSCAN
    引數  半徑大小 最低成員數目
    適用範圍  樣本數目很大 聚類數目中等
    距離度量  最近的點之間的距離

    函式名稱  Birch
    引數  分支因子 閾值 可選全域性叢集
    適用範圍  樣本數目很大 聚類數目較大
    距離度量  點之間的歐式距離

聚類演算法實現需要sklearn估計器 fit 和 predict
    fit 訓練演算法 接收訓練集和標籤
        可用於有監督和無監督學習
    predict 預測有監督學習的測試集標籤
        可用於劃分傳入資料的類別
將規則通過 fit 訓練好後 將規則進行 預測 predict
    如果存在資料 還可以檢驗規則訓練的好壞

引入離差標準化
from sklearn.preprocessing import MinMaxScaler

from sklearn.datasets import load_iris
from sklearn.cluster import K-Means
iris = load_iris()

資料集的特徵
iris_data = iris['data']

資料集的標籤
iris_target = iris['target']

資料集的特徵名
iris_names = iris['feature_names']

訓練規則
scale = MinMaxScaler().fit(iris_data)

應用規則
iris_dataScale = scale.transform(iris_data)

構建並訓練模型
kmeans = KMeans(n_components = 3,random_state = 123).fit(iris_dataScale)
    n_components = 3  分為三類

預測模型
result = kmeans.predict([[1.5,1.5,1.5,1.5]])

檢視預測類別
result[0]

使用 sklearn.manifold 模組的 TSNE 函式
    實現多維資料的視覺化展現
    原理 使用 TSNE 進行資料降維
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
使用 TSNE 進行資料降維 降為兩維
tsne = TSNE(n_components = 2,init = 'random',random_state = 177).fit(iris_data)
    n_components = 2 降為兩維

將原始資料轉換為 DataFrame 物件
df = pd.DataFrame(tsne.embedding_)
    轉換為二維表格式

將聚類結果存到 df 資料表中
df['labels'] = kmeans.labels_

提取不同標籤的資料
df1 = df[df['labels'] == 0]
df2 = df[df['labels'] == 1]
df3 = df[df['labels'] == 2]

繪製圖形
fig = plt.figure(figsize = (9,6))

使用不同的顏色表示不同的資料
plt.plot(df1[0],df1[1],'bo',df2[0],df2[1],'r*')

儲存為 .png 圖片
plt.savefig('../tmp/名稱.png')
plt.show()

聚類模型評價指標
    標準
        組內的物件相互之間是相似的(相關的)
        不同組中的物件是不同的(不相關的)
sklearn.metrics 提供評價指標
    ARI評價法(蘭德係數) adjusted _rand_score
    AMI評價法(互資訊) adjusted_mutual_info_score
    V-measure評分 completeness_score
    FMI評價法 fowlkes_mallows_score
    輪廓係數評價法 silhouette _score
    Calinski-Harabasz指數評價法 calinski_harabaz_score
        前四種更有說服力 評分越高越好
聚類方法的評價可以等同於分類演算法的評價

FMI評價法 fowlkes_mallows_score
from sklearn.metrics import fowlkes_mallows_score
for i in range(2,7):
    kmeans =KMeans(n_clusters =i,random_state=123).fit(iris_data)
    score = fowlkes_mallows_score(iris_target,kmeans.labels_)
    print('iris資料聚 %d 類FMI評價分值為:%f'%(i,score))

輪廓係數評價法 silhouette_score
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt

silhouettteScore=[]
for i in range(2,15):
    kmeans=KMeans(n_clusters =i,random state=123).fit(iris data)
    score = silhouette_score(iris_data,kmeans.labels_)
    silhouettteScore.append(score)
plt.figure(figsize=(10,6))
plt.plot(range(2,15),silhouettteScore,linewidth=1.5,linestyle="-")
plt.show()

使用 Calinski-Harabasz 指數評價 K-Means 聚類模型
    分值越高聚類效果越好
from sklearn.metrics import calinski_harabaz_score
for i in range(2,7):
    kmeans=KMeans(n_clusters =i,random_state=123).fit(iris_data)
    進行評價
    score=calinski_harabaz_score(iris_data,kmeans.labels_)
    print'iris資料聚%d類calinski harabaz指數為:%f'%(i,score)

構建並評價分類模型(有監督學習)
    輸入樣本的特徵值 輸出對應的類別
    將每個樣本對映到預先定義好的類別
    分類模型建立在已有模型的資料集上

    用於 影象檢測 物品分類

分類演算法
模組名            函式名稱            演算法名稱
linear_model LogisticRegression 邏輯斯蒂迴歸
svm             SVC                支援向量機
neighbors    KNeighborsClassifier K最近鄰分類
naive_bayes      GaussianNB        高斯樸素貝葉斯
tree        DecisionTreeClassifier 分類決策樹
ensemble RandomForestClassifier  隨機森林分類
ensemble GradientBoostingClassifier 梯度提升分類樹

以 breast_cancer 資料為例 使用sklearn估計器構建支援向量機(SVM)模型

import numpy as np
from sklearn.datasets import load_breast.cancer
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

cancer = load_breast_cancer()
cancer_data = cancerf['data']
Cancer_target = cancert['target']
cancer_names = cancer['feature_names']

建立 SVM 模型
svm = SVC().fit(cancer_trainStd,cancer_target_train)

預測訓練集結果
cancer_target_pred = svm.predict(cancer_testStd)

將預測結果和真實結果比對 求出預測對的結果和預測錯的結果
true = np.sum(cancer_target_pred == cancer_target_test)
預測對的結果的數目
true
預測錯的結果的數目
cancer_target_test.shape[0] - true
準確率
true/cancer_target_test.shape[0]

評價分類模型
分類模型對測試集進行預測得到的準確率並不能很好的反映模型的效能
結合真實值->計算準確率、召回率 F1 值和 Cohen's Kappa 係數等指標

方法名稱             最佳值         sklearn 函式
Precision(精確率)    1.0      metrics.precision_score
Recall(召回率)         1.0        metrics.recall_score
F1值                    1.0        metrics.f1_score
Cohen's Kappa 係數    1.0     metrics.cohen_kappa_score
ROC曲線              最靠近y軸    metrics.roc_curve

from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score

使用SVM預測breast_cancer資料的準確率為
accuracy_score(cancer_target_test,cancer_target_pred)
使用SVM預測breast_cancer資料的精確率為
precision_score(cancer_target_test,cancer_target_pred)

繪製ROC曲線
from sklearn.metrics import roc_curve
import matplotlib.pyplot as plt
求出ROC曲線的x軸和y軸
fpr,tpr,thresholds = roc_curve(cancer_target_test,cancer_target_pred)
plIt.figure(figsize=(10,6))
plt.xlim(O,1)##設定x軸的範圍
plt.ylim(0.0,1.1)##設定y軸的範圍
plt.xlabel('False Postive Rate')
plt.ylabel('True Postive Rate')
plt.plot(fpr,tpr,linewidth=2,linestyle=*-".color='red")
plt.show()

ROC曲線 與 x 軸面積越大 模型效能越好

構建並評價迴歸模型
分類和迴歸的區別
    分類演算法的標籤是離散的
    迴歸演算法的標籤是連續的
作用 交通 物流 社交網路和金融領域等

迴歸模型
    自變數已知
    因變數未知 需要預測
迴歸演算法實現步驟 分為 學習 和 預測 兩個步驟
    學習 通過訓練樣本資料來擬合迴歸方程
    預測 利用學習過程中擬合出的迴歸方程 將測試資料放入方程中求出預測值

迴歸演算法
模組名稱        函式名稱        演算法名稱
linear_model LinearRegression 線性迴歸
svm         SVR         支援向量迴歸
neighbors KNeighborsRegressor 最近鄰迴歸
tree     DecisionTreeRegressor 迴歸決策樹
ensemble RandomForestRegressor 隨機森林迴歸
ensemble GradientBoostingRegressor 梯度提升迴歸樹

以boston資料集為例 使用skllearn估計器構建線性迴歸模型
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
boston = load_boston()
X = boston['data']
y = boston['target']
names = boston['feature_names']

劃分訓練集和測試集
X_train,X_test,y_train,y_test = train_test_split(X,Y.test_size=0.2,random_state=125)
建立線性迴歸模型
clf = LinearRegression().fit(X_train.y_train)
預測訓練集結果
y_pred = clf.predict(X_test)
前二十個結果
y_pred[:20]
使用不同的顏色表示不同的資料
plt.plot(range(y_test.shape[0]),y_test,color='blue',linewidth=1.5,linestyle='-')

評價迴歸模型
方法名稱        最優值        sklearn函式
平均絕對誤差     0.0    metrics.mean_absolute_error
均方誤差         0.0    metrics.mean_squared_error
中值絕對誤差     0.0    metrics.median_absolute_error
可解釋方差值     1.0    metrics.explained_variance_score
R方值         1.0    metrics.r2_score

平均絕對誤差 均方誤差和中值絕對誤差的值越靠近 0
    模型效能越好
可解釋方差值 和 R方值 則越靠近1 模型效能越好


from sklearn.metrics import explained_variance_score,mean_absolute_error,mean_squared_error,median_absolute_error,r2_score
Boston資料線性迴歸模型的平均絕對誤差為
mean_absolute_error(y_test,y_pred)
Boston資料線性迴歸模型的均方誤差為
mean_squared_error(y_test,y _pred)
Boston資料線性迴歸模型的中值絕對誤差為
median_absolute_error(y_test,y_pred)
Boston資料線性迴歸模型的可解釋方差值為
explained_variance_score(y_test,y_pred)
Boston資料線性迴歸模型的R方值為
r2_score(y test,y_pred)

2020-07-25