Python編程進階

=================【Python基礎教程】===========

5、函數

函數是一段組織好的、能夠重複使用的,用來實現單一或相關功能的代碼段。
函數能提升應用的模塊性,提升代碼的利用率。
複製代碼

1. 自定義函數

1.1 函數語法

def 函數名(參數):
	...
	函數體
	...
	
# 自定義函數
def custom_func(elem):
    print("這是個人自定義函數...")
    print("我是參數elem: ", elem)

# 函數調用
custom_func(1)
複製代碼

1.2 函數的參數

1.2.1 普通參數

def common_parameter(par1, par2):       # 函數定義,形參,提供給使用者一個接口
    print(par1)
    print(par2)

common_parameter(11, 22)    # 函數調用,實參,實參值傳遞給形參
複製代碼

1.2.2 默認參數

# par_default爲函數的默認參數,函數調用時若是不傳值的話,就是用默認的參數的值;若是傳值了就用傳的值
def default_parameter(par1, par2, par_default="我是默認值"):
    print("..........default parameter..........")
    print(par1)
    print(par2)
    print(par_default)

default_parameter("我是par1", 222)
default_parameter(111, 222, "test")
default_parameter(par_default="位置參數生效", par1=1111, par2=True)
複製代碼

1.2.3 動態參數

# (1) 能夠接受任意個參數
# (2) 動態參數有兩種:*args和**kwargs,*args必須在*kwargs的前面
# *args: 接受的是按照位置傳參的值,組織成一個 **元組**
# **kwargs: 接受的是按照關鍵字傳參的值,組成一個 **字典**
# (3) 參數的傳遞順序:位置參數、*args、默認參數、**kwargs
def dynamic_parameter(par1, par2, *args, par_default="default", **kwargs):
    print(".......dynamic parameter.......")
    print(par1)
    print(par2)
    print(args)
    print(par_default)
    print(kwargs)
    print(kwargs['name'])
    print(kwargs['age'])
    

dynamic_parameter(1, 2, 2, 3, 4, 5, par_default=5, name='kwargs', age=12)
複製代碼

1.3 函數的返回值

# return 語句用於退出函數,選擇性地向調用方式返回一個表達式。不帶參數值的return語句返回None。
def return_func(a, b):
    total = a + b
    print("函數內:", total)
    return total


total_exc = return_func(12, 23)
print("函數外:", total_exc)
複製代碼

2. 異常處理

  異常就是程序執行時發生錯誤的信號,Python中不一樣異經常使用不一樣類對象標識不一樣的異常,一個異常標識一種錯誤。python

  Python程序執行時,檢測到一個錯誤時,若是不處理程序就在當前異常處終止。編寫特定的異常處理代碼專門來處理異常,若是捕捉成功則進入定製的另外一個程序分支,使程序不崩潰。因此在程序中必須提供一種異常處理機制來加強程序的健壯性和容錯性,提升用戶體驗。git

2.1 常見異常類:

(1) AttributeError          訪問的對象沒有該屬性
(2) IOError                 輸入/輸出異常,基本上是沒法打開文件
(3) ImportError             沒法引入模塊或包,基本是路徑或名稱錯誤
(4) IndentationError        語法錯誤,代碼沒有正確對齊
(5) IndexError              下標索引超出邊界
(6) KeyError                訪問的字典裏面不存在的鍵
(7) KeyboardInterrupt       Ctrl + c 被按下
(8) NameError               訪問一個還未被賦予對象的變量
(9) SyntaxError             Python代碼非法,代碼不能編譯
(10) TypeError              傳入對象類型與要求的不符合
(11) ValueError             傳入一個調用者不指望的值
(12) UnboundLocalError      訪問一個還未被設置的局部變量,基本上是因爲另有一個同名的全局變量
(13) AssertionError         斷言錯誤,說明斷言的條件爲假
(14) ..............
複製代碼

2.2 異常處理方式

2.2.1 try...exception...finally

GitHub代碼commits id:a7df219程序員

list_exception = [1, 2, 3]

try:
    for i in list_exception:
        print(list_exception[i+2])

    raise TypeError('....主動拋出異常...')
except IndexError as e:
    print("異常 %s 已經在這裏被捕獲了,下面再有異常處理就再也不被捕獲了" % e)
except Exception as e:
    print(e)
finally:
    print("程序執行結束,無論異常是否被捕獲,這裏必定始終會執行")
複製代碼

2.2.2 try...exception...else

GitHub代碼commits id:47da104github

else_exception = [1, 2, 3]
try:
    for i in [1, 4]:
        print(i)
except IndexError as e:
    print(e)
except SyntaxError as se:
    print(se)
else:
    print("只有再try語句裏面的執行成功的時候,纔會執行else裏面的內容")
複製代碼

2.3 自定義異常

GitHub代碼commits id:e8936a9express

class EvaException(BaseException):
    def __int__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg


try:
    raise EvaException("自定義錯誤")
except EvaException as e:
    print(e)
複製代碼

2.4 斷言

  assert斷言是聲明其布爾值必須爲真的斷定,若是發生異常則說明表達式爲假。 【GitHub代碼commits id:b4641c編程

assert 1 == 1
try:
    assert 1 == 2
except AssertionError as e:
    print("看見我說明斷言的判斷條件是錯誤的,這個異常已經被我捕獲了: %s" % e)
複製代碼

3. 迭代器

  迭代器 指的是迭代取值的工具,迭代是一個重複的過程,每一次的重複都是基於上一次的結果而進行的;迭代提供了不依賴於索引而進行取值的方法。數組

  可迭代對象 但凡內置 _iter_ 方法的對象,都稱之爲可迭代對象。Python常見數據類型中,str、list、tuple、dict、set、文件對象都是可迭代對象。緩存

  迭代器對象 (1)既內置 __next__方法,(2)又有 __iter__方法的對象,執行迭代器的 _iter_ 方法獲得的依然是迭代器對象自己,執行 _next_ 方法能夠不依賴索引進行取值。bash

  總的來講: 迭代器必定是可迭代對象,而可迭代對象不必定是迭代器。app

3.1 判斷可迭代對象和迭代器

from collections.abc import Iterable, Iterator

string1 = "Iterable"
list1 = range(10)
if isinstance(string1, Iterable):
    print("該對象是可迭代對象")
elif isinstance(string1, Iterator):
    print("該對象是迭代器")
else:
    print("您的判斷不存在")
複製代碼

3.2 迭代對象的使用

list1 = range(5)
for i in list1:
    print(i)
# 將 "可迭代對象" 轉換成 "迭代器對象"
if isinstance(list1, Iterable):
    print("該對象是可迭代對象")
elif isinstance(list1, Iterator):
    print("該對象是迭代器")
else:
    print("您的判斷不存在")
list2 = iter(list1)
try:
    print("迭代器對象獲取數據:", next(list2))
    print("迭代器對象獲取數據:", next(list2))
    print("迭代器對象獲取數據:", next(list2))
    print("迭代器對象獲取數據:", next(list2))
    print("迭代器對象獲取數據:", next(list2))
    print("迭代器對象獲取數據:", next(list2))
except StopIteration as e:
    print("That is all folks!")
複製代碼

4. 生成器

  受內存的限制,咱們若是要用列表生成式生成一個比較大的列表的時候就棘手了。生成器是一個特殊的程序,能夠被用做控制循環的迭代行爲,Python中生成器是迭代器的一種,使用yield返回值函數,每次調用yield會暫停,而可使用next()和send()函數恢復生成器。生成器一次只返回一個值。

4.1 建立生成器

l1 = [x*x for x in range(10)]
print("列表生成式l1: ", l1)
g1 = (x*x for x in range(5))
print("生成器g1: ", g1)
try:
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
except StopIteration as e:
    print("生成器全部的值已經迭代結束了......")
複製代碼

4.2 斐波拉契數列

# 0 1 1 2 3 5 8 13 21
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a+b
        n = n + 1
    return "done"


g = fib(5)
while True:
    try:
        x = next(g)
        print("......: ", x)
    except StopIteration as e:
        print("生成器已迭代完畢...", e.value)
        print("生成器已迭代完畢...", e.args)
        break
複製代碼

5. 裝飾器

  Python的裝飾器(decorators)就是用來拓展原來函數功能的一種函數,目的是不改變原函數名(或類名)的狀況下,給函數增長新的功能。

5.1 裝飾器入門

  已開發嗶哩嗶哩APP爲例,前期開發了我的空間、我的關注、錢包等功能,這些功能的訪問的必須和我的帳號的登陸狀態是掛鉤的。若是不登陸直接訪問這些功能的話就會收到權限限制的提示。這些不一樣的功能又是由不一樣的程序員開發的,權限驗證是由公共部門開發的,權限保密權限涉密等級又比較高,不能全員皆知。

  裝飾器的引入就能夠完美的解決這個問題。公共部門開發權限認證裝飾器,須要調用權限認證的功能只需調用裝飾器便可。

  裝飾器的就是讓你在一個函數的先後去執行代碼。

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
""" @File : 55_decorators.py @Time : 2019/10/8 16:07 @Author : Crisimple @Github : https://crisimple.github.io/ @Contact : Crisimple@foxmail.com @License : (C)Copyright 2017-2019, Micro-Circle @Desc : None """

def authority(function_to_decorate):
    def auth():
        username = input("請輸入用戶名:")
        password = input("請輸入用戶密碼:")
        if username == 'crisimple' and password == '123456':
            print("......認證成功......")
            function_to_decorate()
        else:
            print("......認證失敗......")
    return auth

@authority
def view_space():
    print("......歡迎進入嗶哩嗶哩我的空間......")


if __name__ == "__main__":
    view_space()
    print("view_space.__name__ is: ", view_space.__name__)
複製代碼

5.2 裝飾器應用

(1)引入日誌
    (2)函數執行時間統計
    (3)執行函數前于謙準備
    (4)執行函數後的清理工做【測試固件運用】
    (5)權限校驗等場景【登陸/權限限制】
    (6)緩存
複製代碼

5.3 帶固定參數的裝飾器

GitHub示例

def message_auth(function_to_decorate):
    def auth(user, passwd):
        username = input("請輸入用戶名:")
        password = input("請輸入用戶密碼:")
        if username == user and password == passwd:
            print("......認證成功......")
            function_to_decorate(user, passwd)
        else:
            print("......認證失敗......")
    return auth

@message_auth
def message(user, passwd):
    print("......您能夠查看您的消息了......")
複製代碼

5.4 無固定參數的裝飾器

GitHub示例

def pay_auth(function_to_decorate):
    def auth(*args, **kwargs):
        input("=====請輸入你的動態口令=====: ")
        function_to_decorate(*args, **kwargs)
    return auth

@pay_auth
def pay(a, b, c):
    print("......您的帳戶餘額爲動態口令之和:%s" % (a+b+c))
複製代碼

5.5 多個裝飾器裝飾同一函數

GitHub示例

# 對於Python中的」@」語法糖,裝飾器的調用順序與使用 @ 語法糖聲明的順序相反。
def first_decorator(function_to_decorator):
    def wrapper():
        print("This is first decorator01")
        function_to_decorator()
        print("End of the first decorator01")
    return wrapper

def second_decorator(function_to_decorator):
    def wrapper():
        print("This is second decorator02")
        function_to_decorator()
        print("End of the second decorator02")
    return wrapper

@first_decorator
@second_decorator
def func_decorator():
    print("...【This is to be decorated function】...")
複製代碼

5.6 Python內置裝飾器

在Python中有三個內置的裝飾器,都是跟class相關的:staticmethod、classmethod 和property。

(1)staticmethod 是類靜態方法,其跟成員方法的區別是沒有 self 參數,而且能夠在類不進行實例化的狀況下調用
(2)classmethod 與成員方法的區別在於所接收的第一個參數不是 self (類實例的指針),而是cls(當前類的具體類型)
(3)property 是屬性的意思,表示能夠經過經過類實例直接訪問的信息,對於一個類的屬性,python的訪問是沒有限制的,但有時候咱們須要對屬性的訪問加以限制,property能夠勝任
複製代碼

GitHub示例

class Foo(object):
    def __init__(self):
        self.name = 'zha nan'
        self.age = '23'

    # 不用傳遞self對象,就至關因而個普通方法
 @staticmethod
    def direct_call():
        print("類靜態方法,能夠在類不進行實例化的狀況下調用,能夠不用傳self參數了,看到這句話就說明了這個道理")

    # 使用classmethod裝飾器裝飾後,方法的第一個參數是類對象;調用類方法不須要建立類的實例。classmethod也是一個類,因此classmethod是一個類裝飾器。
 @classmethod
    def class_method(cls):
        print(cls.direct_call)

    # 對於一個類的屬性,python的訪問是沒有限制的,但有時候咱們須要對屬性的訪問加以限制,property能夠勝任
    # property是一個類,它有三個方法,deleter,setter,getter,有兩種使用方式。
 @property
    def name(self):
        return self.name

 @name.setter
    def name(self, set_num):
        return self.name == set_num

 @name.deleter
    def name(self):
        del self.name


from abc import abstractclassmethod, ABCMeta
# 一個類中的任何方法被abstractmethod裝飾後,這個類不能實例化而且子類必須實現被abstractmethod裝飾的方法
class ChildFoo(abstractmethod=ABCMeta):
 @abstractclassmethod
    def eat(cls):
        pass
複製代碼

6. Python的內置函數

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
""" @File : 56_builtIn_function.py @Time : 2019/10/15 18:45 @Author : Crisimple @Github : https://crisimple.github.io/ @Contact : Crisimple@foxmail.com @License : (C)Copyright 2017-2019, Micro-Circle @Desc : None """

# 1. abs() --- 返回數字的絕對值
a11 = 1
a12 = -2
a13 = 0
print("%s 的絕對值爲 %s" % (a11, abs(a11)))
print("%s 的絕對值爲 %s" % (a12, abs(a12)))
print("%s 的絕對值爲 %s" % (a13, abs(a13)))
print("\n")
# --------------------------------
# bin() --- 返回一個整數int或長整型long int的二進制表示
bin_1 = 10
bin_2 = 20
print("%s通過bin後返回%s" % (bin_1, bin(10)))
print("%s通過bin後返回%s" % (bin_2, bin(20)))
print("\n")
# --------------------------------
# max() --- 返回給定參數的最大值,參數能夠爲序列
print("返回序列的最大值:", max(100, 200, 3000, 800))
print("\n")
# --------------------------------
# min() --- 返回給定參數的最小值,參數能夠爲序列
print("返回序列的最小值:", min(-100, 200, 0, -10000))
print("\n")
# ---------------------------------
# reversed() --- 用於反向列表元素
reverse_list = [3, 5, 7, 1]
reversed_tuple = (1, 4, 3, 5)
reverse_list.reverse()
print("%s 的反向輸出爲:%s" % (reverse_list, reverse_list))
# print("%s 的反向輸出爲:%s" % (reversed_tuple, reversed_tuple))
print("\n")
# -----------------------------
# oct() --- 將一個整數轉換成8進制字符串
print("返回八進制的字符串:", oct(10))
# -----------------------------
# zip() --- 函數用於將可迭代的對象做爲參數,將對象中對應的元素打包成一個個元組,而後返回由這些元組組成的列表。
# 若是各個迭代器的元素個數不一致,則返回列表長度與最短的對象相同,利用 * 號操做符,能夠將元組解壓爲列表。
zip_1 = [1, 2, 3]
zip_2 = [4, 5, 6]
zip_3 = [7, 8, 9]
zipped1 = zip(zip_1, zip_2)
zipped2 = zip(zip_3, zip_2)
print("壓縮成數組:", zipped1)
print("解壓數組:", zip(*zipped2))
print("\n")
# -----------------------------
# complex([real[, imag]]) 建立一個值爲 real + imag * j 的複數或者轉化一個字符串或數爲複數。若是第一個參數爲字符串,則不須要指定第二個參數
# real -- int, long, float或字符串
# imag -- int, long, float
print("返回一個複數:", complex(1, 2))
print("返回一個複數:", complex("1+2j"))
print("\n")


# 2. divmod() --- 把除數和餘數運算結果結合起來,返回一個包含商和餘數的元組(a // b, a % b)
a21 = -7
b21 = -2
a22 = 0
b22 = 5
a23 = 20
b23 = 0
print("%s 除以 %s 的;返回結果爲:%s" % (a21, b21, divmod(a21, b21)))
print("%s 除以 %s 的;返回結果爲:%s" % (a22, b22, divmod(a22, b22)))
# print("%s 除以 %s 的;返回結果爲:%s" % (a23, b23, divmod(a23, b23)))
print("\n")
# pow(x, y) --- 返回x的y次方的值
c31 = 2
cc31 = -3
c32 = 2
cc32 = 3
print("%s 的 %s 次冪運算爲:%s" % (c31, cc31, pow(c31, cc31)))
print("%s 的 %s 次冪運算爲:%s" % (c32, cc32, pow(c32, cc32)))
print("\n")
# ---------------------------------------------------------
# sum(iterable[, start]) --- 對一系列數據求和
# iterable --- 可迭代對象:列表、元組、集合
# start --- 指定增長的參數,若是沒有設置這個值,默認爲0
sum_1 = [0, 1, 2, 3]
sum_2 = (9, 1, 2, 3)
sum_3 = {9, 1, 2, 0}
print("%s 求和結果爲:%s" %(sum_1, sum(sum_1)))
print("%s 求和結果爲:%s" %(sum_2, sum(sum_2)))
print("%s 求和結果爲:%s" %(sum_3, sum(sum_3)))
print("\n")
# --------------------------------------------
# sorted(iterable, cmp=None, key=None, reverse=False)
# iterable -- 可迭代對象
# cmp -- 比較的函數有兩個參數,參數的值從可迭代對象中取出,函數必須遵照,大於返回1,小於則返回-1,等於則返回0
# key -- 用來進行比較的元素,只有一個參數,函數的參數取自於可迭代對象中,指定可迭代對象中的一個元素來進行排序
# reverse -- 排序規則,reverse = True 降序 , reverse = False 升序(默認)
sorted_dict = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
print("排序結果爲:", sorted(sorted_dict, key=lambda s: s[2], reverse=True))
print("\n")


# 3. input & raw_input
# input() 讀取一個合法的 python 表達式,輸入字符串時必須引號括起來,不然會引起 SyntaxError
# raw_input() 將全部輸入做爲字符串看待
# 當實際測試下來兩個並無什麼區別的感受
# a31 = input("input: ")
# print("輸入的數據爲 %s, 它的類型爲:%s" % (a31, type(a31)))
# a32 = input("raw_input: ")
# print("輸入的數據爲 %s, 它的類型爲:%s" % (a32, type(a32)))


# 4. open() --- 用於打開一個文件,建立一個 file 對象,相關的方法才能夠調用它進行讀寫
# file() --- 用於建立file對象,它有一個別名叫open()
# 打開文件的模式:
# r 以只讀方式打開文件。文件的指針將會放在文件的開頭。這是默認模式。
# rb 以二進制格式打開一個文件用於只讀。文件指針將會放在文件的開頭。這是默認模式。
# r+ 打開一個文件用於讀寫。文件指針將會放在文件的開頭。
# rb+ 以二進制格式打開一個文件用於讀寫。文件指針將會放在文件的開頭。
# w 打開並只能寫入。若文件已存則打開文件並從頭開始編輯,原內容會被刪除。若該不存在,建立新文件。
# wb 二進制格式打開文件只用於寫入。若文件已存在則打開文件並從頭開始編輯,即原有內容會被刪除。若是該文件不存在,建立新文件。
# w+ 打開一個文件用於讀寫。若是該文件已存在則打開文件,並從開頭開始編輯,即原有內容會被刪除。若是該文件不存在,建立新文件。
# wb+ 以二進制格式打開文件用於讀寫。若是該文件已存在則打開文件從開頭開始編輯原內容會被刪除。若是該文件不存在,建立新文件。
# a 打開文件用於追加。若文件已存在,文件指針放在文件的結尾。新的內容會被寫入已有內容。若文件不存在,建立新文件進行寫入。
# ab 二進制格式打開文件用於追加。若文件已存文件指針放在文件結尾。新內容會寫入到已有內容。若文件不存在,建立新文件進行寫入。
# a+ 打開文件用於讀寫。若文件已存在文件指針將放在文件的結尾。文件打開時會是追加模式。若是該文件不存在,建立新文件用於讀寫。
# ab+ 以二進制格式打開一個文件用於追加。若是該文件已存在,文件指針將會放在文件的結尾。若是該文件不存在,建立新文件用於讀寫。
# file對象的方法
# file.read([size]) --- 指定大小讀取文件,若不寫size,則返回整個文件
# file.readline() --- 返回一行
# file.readlines([size]) --- 返回指定size行,未指定的則返回所有行
# for line in f: print line --- 經過迭代器訪問
# f.write["Hello"] --- 寫入字符串數據,如果寫入其餘類型的數據則需先轉換成字符串類型,再寫入
# f.tell() --- 返回一個整數,表示當前文件指針的位置
# f.seek(偏移量,[起始位置]) --- 用來移動文件指針,偏移量可正可負;起始位置:0-文件頭,默認;1-當前位置;2-文件尾
# f.close() --- 關閉文件
with open('55_decorators.py', 'r', encoding='utf-8') as f:
    content = f.readline()
    print(content)
print("\n")


# 5. staticmethod --- 內置裝飾器,返回類的靜態函數
class StatiClass(object):
 @staticmethod
    def write():
        print("類的靜態方法")
StatiClass.write()
print("\n")
# -------------------------------------
# classmethod --- 內置裝飾器修飾的函數不須要實例化,第一個參數由self變爲cls,用來調用類的屬性、類的方法、
class ClassMethod(object):
    bar = 1
    def func1(self):
        print('foo')

 @classmethod
    def func2(cls):
        print(cls.bar)
        cls().func1()

ClassMethod.func2()
print("\n")


# 6. all() --- 判斷給定的可迭代對象參數 iterable 中的全部元素是否都爲True,若是全是返回True,不是則爲False
# 除了0,空,None,False外都算True
a61 = [1, 2, 3, 4, 5]
a62 = [1, '', '2', 'a']
a63 = [1, 0, '2', 'a']
a64 = [1, False, '2', 'a']
print("%s 的返回:%s" % (a61, all(a61)))
print("%s 的返回:%s" % (a62, all(a62)))
print("%s 的返回:%s" % (a63, all(a63)))
print("%s 的返回:%s" % (a64, all(a64)))
print("\n")
# any() --- 判斷給定的可迭代參數iterable是否全爲False,則返回 False,若是有一個爲True則返回True
b61 = [1, 2, 3, 4, 6]
b62 = [0, 2, 3, 4, 6]
b63 = [0, '', False, None]
print("%s 的返回:%s" % (b61, any(b61)))
print("%s 的返回:%s" % (b62, any(b62)))
print("%s 的返回:%s" % (b63, any(b63)))
print("\n")


# 7. enumerate --- 將可遍歷的數據對象(列表、元組或字符串)組合成一個索引序列,同時列出數據和數據下表,多用於for循環
# enumerate(sequence, [start=0]) --- sequence(一個序列、迭代器或其餘支持迭代對象);start(下標起始位置)
sequence71 = ['A', 'B', 'C']
sequence72 = "I'm a good boy."
sequence73 = (1, 2, 3)
for i, element in enumerate(sequence71):
    print(i, element)
for i, element in enumerate(sequence72):
    print(i, element)
for i, element in enumerate(sequence73):
    print(i, element)
print("\n")
# iter(object[, sentinel]) --- 生成迭代器
iter_1 = [1, 2, 3, 4, 5, 6]
iter_2 = "xiao"
for i in iter_1:
    print("=====%s" % i)
print("**************", next(iter(iter_2)))
print("**************", next(iter(iter_2)))
print("**************", next(iter(iter_2)))
print("**************", next(iter(iter_2)))
print("\n")
# -----------------------------
# next() --- 返回迭代器的下一個項目
next_1 = iter([1, 2, 3, 4])
while True:
    try:
        x = next(next_1)
        print("next訪問迭代器的數據:", x)
    except StopIteration:
        break
print("\n")


# 8. int() --- 將一個字符串或數字轉換爲整型
a81 = 0.1
a82 = 3.8
a83 = -1
a84 = '123'
print("%s 整形爲 %s" % (a81, int(a81)))
print("%s 整形爲 %s" % (a82, int(a82)))
print("%s 整形爲 %s" % (a83, int(a83)))
print("%s 整形爲 %s" % (a84, int(a84)))
print("\n")
# str() --- 返回一個對象的string格式
print(str(123))
print(type(str({"A": 1, "B": 2})))
print("\n")
# --------------------------------------------------------------
# tuple() --- 將列表轉換爲元組
tuple_1 = [1, 2, 3, 7]
print("tuple()將 %s 轉換成元組後爲:%s" % (tuple_1, tuple(tuple_1)))
print("\n")
# --------------------------------
# list() --- 將元組轉換爲列表
list_1 = (1, '2', 'xyz', 7)
print("list()將 %s 轉換成列表後爲:%s" % (list_1, list(list_1)))
print("\n")
# --------------------------------
# slice(start, stop, step) --- 實現切片對象,用在切片操做函數裏的參數傳遞
slice_list = [1, 2, 3, 4, 5, 6, 7]
myslice = slice(1, 6, 2)
print("slice截取列表:", slice_list[myslice] )
print('\n')
# --------------------------------
# dict(**kwarg)
# dict(mapping, **kwarg)
# dict(iterable, **kwarg)
print("字典1:", dict())
print("字典1:", dict(a='1', b=2, c=3))
print("字典1:", dict(zip(['AA', 'BB', 'CC'], [11, 22, 33])))
print("字典1:", dict([("AAA", 111), ('BBB', 222), ('CCC', 333)]))
print("\n")
# --------------------------------
# bool() --- 將給定參數轉換爲布爾類型,若是沒有參數,返回False
bool_1 = 0
bool_2 = 1
bool_3 = None
bool_4 = ''
bool_5 = 'A'
print("bool() 將 %s 轉換爲bool類型後爲:%s" % (bool_1, bool(bool_1)))
print("bool() 將 %s 轉換爲bool類型後爲:%s" % (bool_2, bool(bool_2)))
print("bool() 將 %s 轉換爲bool類型後爲:%s" % (bool_3, bool(bool_3)))
print("bool() 將 %s 轉換爲bool類型後爲:%s" % (bool_4, bool(bool_4)))
print("bool() 將 %s 轉換爲bool類型後爲:%s" % (bool_5, bool(bool_5)))
print("\n")
# --------------------------------
# float() --- 將整數和字符串轉換成浮點數
print("整數轉換爲浮點數:", float(12))
print("字符串轉換爲浮點數:", float('234'))
print("\n")
# --------------------------------
# set(iterable) --- 建立一個無序不重複的元素集,iterable可迭代對象
# --- 可進行關係測試,刪除重複數據,還能夠計算並集、交集、差集等
set_1 = set("HELLO")
set_2 = set("WORLD")
print("原集合分別爲:%s %s" % (set_1, set_2))
print("%s & %s 的結果爲:%s" % (set_1, set_2, set_1 & set_2))
print("%s | %s 的結果爲:%s" % (set_1, set_2, set_1 | set_2))
print("%s - %s 的結果爲(即前面有後面沒有的):%s" % (set_1, set_2, set_1 - set_2))
print("\n")
# --------------------------------
# map(function,iterable,...) --- 會根據提供的函數對指定序列作映射
map_result = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print("map函數返回", map_result)
print("\n")
# --------------------------------
# repr() --- 將對象轉換爲供解釋器讀取的形式
repr_dict = {"A": 1, "B": 2}
print("repr返回對象的string形式:", repr(repr_dict))
print("\n")
# --------------------------------
# hash() --- 獲取取一個對象(字符串或者數值等)的哈希值
hash_1 = "test hash"
hash_2 = 123
hash_3 = str([1, 2, 3])     # 集合
hash_4 = str(sorted({'A': 1}))
print("%s 的hash值爲:%s" % (hash_1, hash(hash_1)))
print("%s 的hash值爲:%s" % (hash_2, hash(hash_2)))
print("%s 的hash值爲:%s" % (hash_3, hash(hash_3)))
print("%s 的hash值爲:%s" % (hash_4, hash(hash_4)))
print("\n")
# --------------------------------
# hex() --- 將10進制整數轉換成16進制,以字符串形式表示
print("hex的結果:", hex(255))
print("\n")
# --------------------------------
# bytearray() --- 返回一個新本身數據,數組裏的元素是可變的,而且每一個元素的值的範圍爲 0 <= x < 256
print("bytearray....: ", bytearray([1, 2, 3]))
print("bytearray....: ", bytearray())
print("\n")


# 9. ord() --- 是 chr() 函數(對於8位的ASCII字符串)或 unichr() 函數(對於Unicode對象)的配對函數
print(ord('a'))
print(ord('b'))
print(ord('C'))
# chr() --- 用一個範圍在 range(256)內的(就是0~255)整數做參數,返回一個對應的字符。
print(chr(123))
print(chr(97))
# unichr() --- 和 chr()函數功能基本同樣, 只不過是返回 unicode 的字符
# print(unichr(97))
print("\n")


# 10. eval() --- 用來執行一個字符串表達式,並返回表達式的值
# eval(expression[, globals[, locals]])
# expression -- 表達式
# globals -- 變量做用域,全局命名空間,若是被提供,則必須是一個字典對象
# locals -- 變量做用域,局部命名空間,若是被提供,能夠是任何映射對象
print(eval('3 * 4'))
print(eval('pow(2, 3)'))
print("\n")
# ----------------------------------
# exec 執行儲存在字符串或文件中的Python語句,相比於 eval,exec能夠執行更復雜的 Python 代碼。
exec('print("Hello World")')
print("\n")
# ----------------------------------
# str.format() 字符串格式化功能
print("{} {}".format("Hello", "Python"))
print("{1} {0} {1}".format("Hello", "Python"))
print("衝動的人:{name1}, 喜歡的人:{name2}".format(name1="小徐", name2="where?"))
print("\n")
# -----------------------------------
# compile(source, filename, mode[, flags[, dont_inherit]]) --- 將一個字符串編譯爲字節代碼
# source -- 字符串或者AST(Abstract Syntax Trees)對象
# filename -- 代碼文件名稱,若是不是從文件讀取代碼則傳遞一些可辨認的值。
# mode -- 指定編譯代碼的種類。能夠指定爲 exec, eval, single。
# flags -- 變量做用域,局部命名空間,若是被提供,能夠是任何映射對象
# flags和dont_inherit是用來控制編譯源碼時的標誌
compile_str = "for i in range(10): print(i)"
c_str = compile(compile_str, '', 'exec')
print("編譯後執行結果是:", exec(c_str))
print("\n")


# 11. isinstance() --- 判斷一個對象是不是一個已知類型,相似於type()
# isinstance()會認爲子類是一種父類類型,考慮繼承關係。
# type()不會認爲子類是一種父類類型,不考慮繼承關係
# isinstance(object, classinfo)
a11 = 11
print("%s 的類型爲 %s" % (a11, isinstance(a11, int)))
print("%s 的類型爲 %s" % (a11, isinstance(a11, (list, int, str))))
class A11(object):
    pass
class A12(A11):
    pass
print(isinstance(A11(), A11))
print(isinstance(A12(), A11))
print(type(A11()) == A11)
print(type(A12()) == A11)


# 12. issubclass(class, classinfo) --- 判斷參數class是不是類型參數classinfo的子類
class Issub_A:
    pass
class Issub_B(Issub_A):
    pass
print("%s 是不是 %s的之類?%s" % (Issub_B, Issub_A, issubclass(Issub_B, Issub_A)))
print("\n")
# -------------------------
# callable() --- 檢查一個對象是不是可嗲用的,若是返回True,object仍有可能調用失敗;若是返回False,調用絕對失敗
print("callable 1返回:", callable(0))
print("callable 2返回:", callable(pow))
print("\n")
# -------------------------
# locals() --- 以字典類型返回當前位置的所有局部變量
def return_local(x: object, y: object) -> object:
    z = 1
    print(locals())
all_result = return_local(2, 3)
print("返回當前位置的所有局部變量:", all_result)
print("\n")


# 13. super() --- 函數是用於調用父類(超類)的方法
# super 是用來解決多重繼承問題的,直接用類名調用父類方法在使用單繼承的時候沒問題,可是若是使用多繼承,會涉及到查找順序(MRO)、重複調用(鑽石繼承)等種種問題
# MRO 就是類的方法解析順序表, 其實也就是繼承父類方法時的順序表。
class Super_A(object):
    def add(self,x):
        y = x + 1
        print(y)
class Super_B(Super_A):
    def add(self,x):
        super().add(x)
superb = Super_B()
superb.add(2)
print("\n")
# ------------------------------
# property() --- 在新式類中返回屬性值
class Property_A(object):
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x

    def setx(self, value):
        self._x = value

    def delx(self):
        del self._x

    x = property(getx, setx, delx, "I'm the 'x' property.")
# -----------------------------------
# getattr() --- 返回一個對象屬性值
class Getattr(object):
    bar = 1
g = Getattr()
print("獲取屬性值:", getattr(g, 'bar'))
print("\n")
# ------------------------------------
# delattr(object, name_of_atrr)
class Delattr(object):
    x = 1
    y = 2
    z = 3
d = Delattr()
print("d的屬性:", d.x)
delattr(Delattr, 'x')
# print("d的屬性:" % d.x)
print("\n")
# ------------------------------------
# setattr(object, name, value) -- 設置對象的屬性值,該屬性不必定是存在的
class Setattr(object):
    s1 = 1
s_1 = Setattr()
setattr(s_1, 's2', 5)
print("設置不存在屬性的值:", s_1.s2)
print("\n")
# hasattr(object, name) --- 用於判斷對象是否包含對應的屬性
# object--對象;name--屬性名字符串
class Hasattr(object):
    x = 10
    y = 100
    z = 1000
print("判斷對象是否含有屬性:", hasattr(Hasattr, 'x'))
print("判斷對象是否含有屬性:", hasattr(Hasattr, 'e'))
print("\n")


# 14. filter(function, iterable) --- 過濾序列中不符合條件的元素,返回由符合條件元素組成的新列表
# function --- 判斷函數
# iterable --- 可迭代對象
import random
def func_filter(x):
    list_a = []
    for i1 in x:
        if (i1 % 2) == 0:
           list_a.append(i1)
    return list_a
filter_result = func_filter([1, 2, 3, 4])
print("過濾後的序列爲:%s" % filter_result)


# 15. len() --- 返回對象(字符、列表、元組等)長度或項目個數
len_1 = "len"
len_2 = [1, 2, 3, 4]
len_3 = (1, 2, 3)
print("%s 的長度爲:%s" % (len_1, len(len_1)))
print("%s 的長度爲:%s" % (len_2, len(len_2)))
print("%s 的長度爲:%s" % (len_3, len(len_3)))
print("\n")
# vars() --- 返回對象object的屬性和屬性值的字典對象。
class Vars_A(object):
    a = 1
print("vars()返回:", vars(Vars_A))
print("vars()返回:", vars(Vars_A()))
print("\n")
# -------------------------------------------------
# range(start, stop[, step])
range_result = range(10)
print("&&&&&&&&", range_result)
print("\n")
# -------------------------------------------------
# frozenset() --- 返回一個凍結集合,凍結後結合不能再添加或刪除任何元素
frozenset_1 = frozenset(range(10))
print("frozenset1: %s" % frozenset_1)
frozenset_2 = frozenset("HELLO")
print("frozenset2: %s" % frozenset_2)
print("\n")
# --------------------------------------------------
# globals() --- 以字典類型返回當前位置的所有變量
globals_1 = 'test'
print("當前位置的全局變量:", globals())
print("\n")


# 16.memoryview --- 返回給定參數的內存查看對象(Momory view)。
# 所謂內存查看對象,是指對支持緩衝區協議的數據進行包裝,在不須要複製對象基礎上容許Python代碼訪問。
v = memoryview(bytearray('abc', 'utf-8'))
print(v[0])
print(v[1])
print(v[2])
print("\n")
# -------------------------
# round(x[, n]) --- 方法返回浮點數x的四捨五入值。
print(round(10.2565, 2))


# 17. help() --- 用於查看刪除活模塊的用途的詳細說明
print(help('sys'))
print("\n")
# print(help('str'))
# --------------------------
# dir() --- 不帶參數時,返回當前範圍內的變量、方法和定義的類型列表;
# 帶參數時,返回參數的屬性、方法列表。若是參數包含方法__dir__(),該方法將被調用。
# 若是參數不包含__dir__(),該方法將最大限度地收集參數信息。
print("dir返回:", dir())
print("\n")
# id() --- 用於獲取對象的內存地址
id_1 = '1'
id_2 = 1
id_3 = 4
print("%s 的內存id爲:%s" % (id_1, id(id_1)))
print("%s 的內存id爲:%s" % (id_2, id(id_2)))
print("%s 的內存id爲:%s" % (id_3, id(id_3)))
print("\n")
複製代碼

6、面向對象編程

  面向對象(Object Oriented)設計思想貫穿程序設計,面向對象編程(Object Oriented Programming)是針對大型軟件設計提出的,它能使代碼更好滴複用,使程序更加的靈活。對象 是一個抽象的概念,萬事萬物皆可對象。對象一般可劃分爲兩個部分,靜態部分動態部分 ;【靜態部分】稱之爲 屬性,【動態部分】稱爲 方法

  面向對象編程中,將函數和變量進一步封裝成類,類纔是程序的基本元素,它將數據和操做緊密鏈接,並保護數據不被外界意外改變。

1. 面向對象術語

面向對象中的相關術語整理以下:
(1)類(class):用來描述具備相同【屬性】和【方法】的對象集合,定義了該集合中每一個對象所共有的屬性和方法,其中對象被稱爲類的實例;
(2)實例:也稱對象,經過類定義的初始化方法賦予具體的值;
(3)實例化:建立類的實例的過程;
(4)實例變量:定義在實例中的變量,只做用於當前實例;
(5)類變量:類變量是全部實例公有的變量。類變量定義在類中,但在方法體以外
(6)數據成員:類變量、實例變量、方法、類方法、靜態方法和屬性等的統稱;
(7)方法:類中定義的函數;
(8)靜態方法:不須要實例化就能夠有類執行的方法;
(9)類方法:類方法是將類自己做爲對象進行操做的方法;
(10)方法重寫:從父類繼承的方法不能知足子類的需求,可對父類的方法進行重寫;
(11)繼承:一個派生類繼承父類的變量和方法;
(12)多態:根據對象類型的不一樣以不一樣的方式進行處理
複製代碼
# (1)類
class OOPObject(object):
    # (5)類變量:定義在類中,方法以外的變量
    phone = 123456789
    address = "memory"

    # __init__方法的類在實例化的時候,會自動調用該方法,並傳遞對應的參數
    def __init__(self, name, age):
        # (4)實例變量,name 和 age就是實例變量
        self.name = name
        self.age = age

    # (7)實例方法
    def o_method(self):
        print("{0}:{1}".format(self.name, self.age))

    # (8)靜態方法:不須要實例化就能夠有類執行的方法
 @staticmethod
    def static_method():
        print("我是靜態方法")

    # (9)類方法:類方法是將類自己做爲對象進行操做的方法
    # 採用@classmethod裝飾,至少傳入一個cls(指類自己,相似於self)參數。
    # 執行類方法時,自動將調用該方法的類賦值給cls。
    # 使用類名.類方法的調用方式(也可使用實例名.類方法的方式調用)
 @classmethod
    def class_method(cls):
        print("我是類方法")


# (2)實例
# (3)實例化---這個過程
o1 = OOPObject("oj", 23)
# 實例方法的調用
o1.o_method()


# (6)數據成員:類變量、實例變量、方法、類方法、靜態方法和屬性等的統稱

# (8)靜態方法的調用
OOPObject.static_method()


# 類方法
OOPObject.class_method()
複製代碼

2. 面向對象三特徵

面向對象的三大特徵:封裝繼承多態

2.1 封裝

  封裝是指將 數據具體操做 的代碼放在某個對象內部。使這些代碼的實現細節不被外界發現,外界只能經過接口訪問該對象(外界也不能直接訪問類的變量和方法),而不能經過任何形式修改對象內部的實現。【GitHub代碼commits id:cc3bc98

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
""" @File : 62_OOPFeatures.py @Time : 2019/8/14 15:15 @Author : Crisimple @Github : https://crisimple.github.io/ @Contact : Crisimple@foxmail.com @License : (C)Copyright 2017-2019, Micro-Circle @Desc : None """

class ThisClass(object):
    class_name = 'This class'
    class_age = 12

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def print_class(self):
        print("{0}:{1}".format(self.name, self.age))


# 這就說明:外部不能直接調用類變量和類方法
# print(class_name) NameError: name 'class_name' is not defined
# print_class() NameError: name 'print_class' is not defined

# 使用:類名/實例名.變量/方法,來訪問類的變量或方法
print(ThisClass.class_name)
ThisClass.class_name = 'Change name value'
print(ThisClass.class_name)
ThisClass.class_add_attribute = 'Test add attribute'
print(ThisClass.class_add_attribute)
tc = ThisClass('A', 23)
print(tc.print_class())
複製代碼

2.2 繼承

  繼承實現了代碼的複用,多個類公用的代碼能夠只在一個類中提供,其餘類只需集成這個類便可。繼承最大的好處就是 子類(新定義的類) 得到了 父類(被繼承的類也可成爲基類或超類) 的所有變量和方法同時,又能夠根據需求進行修改和擴展。   繼承又分爲兩類:實現繼承(使用基類的屬性和方法無需額外編碼的能力)接口繼承(僅使用屬性和方法的名稱,子類必須提供實現的能力,即子類重構父類方法)。【GitHub代碼commits id:a7b3bee

2.2.1 構造方法的繼承

繼承構造方法的方式:

(1)經典繼承的寫法:父類名稱.__init__(self, 參數1, 參數2)
    (2)新式類的寫法:super(子類, self).__init__(self, 參數1,參數2)
    
    實例化對象b ---> b調用子類的構造方法__init__() ---> 子類的構造方法__init__()繼承父類的構造方法__init__() ---> 調用父類的構造方法__init__()
複製代碼
class FatherClass(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.country = 123

    def father_method(self):
        print('father is walking')


class BoyClass(FatherClass):
    # 先繼承再重構,反着來子類就不能繼承父類的屬性了
    def __init__(self, name, age, sex):
        # 繼承父類的構造方法
        # 經典繼承
        # FatherClass.__init__(self, name, age)
        # 新式類繼承
        super(BoyClass, self).__init__(name, age)
        # 定義子類自己的屬性
        self.sex = sex

    def child_method(self):
        print('child is walking')


class GirlClass(FatherClass):
    pass


# 子類構造方法繼承父類構造方法過程以下:
# 實例化對象b ---> b調用子類的構造方法__init__() ---> 子類的構造方法__init__()繼承父類的構造方法__init__() ---> 調用父類的構造方法__init__()
b = BoyClass('Boy', 25, 'male')
print(b.name)
print(b.age)
print(b.sex)
print(b.country)
複製代碼

2.2.2 子類對父類方法的重寫

若是要對父類的方法進行修改,而又不影響其餘繼承父類的類,咱們能夠再子類中重構該方法。

# 2.繼承
class FatherClass(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.country = '中國'

    def father_method(self):
        print('father is walking')

    def talk(self):
        print("I'am father. %s" % self.name)


class BoyClass(FatherClass):
    # 先繼承再重構,反着來子類就不能繼承父類的屬性了
    def __init__(self, name, age, sex):
        # 繼承父類的構造方法
        # 經典繼承
        # FatherClass.__init__(self, name, age)
        # 新式類繼承
        super(BoyClass, self).__init__(name, age)
        # 定義子類自己的屬性
        self.sex = sex
        print(self.name, self.age, self.country, self.sex)

    def child_method(self):
        print('child is walking...')

    def talk(self):
        print("I'am child. %s" % self.name)


class GirlClass(FatherClass):
    pass


# 2.1 構造方法繼承
# 子類構造方法繼承父類構造方法過程以下:
# 實例化對象b ---> b調用子類的構造方法__init__() ---> 子類的構造方法__init__()繼承父類的構造方法__init__() ---> 調用父類的構造方法__init__()
b = BoyClass('Boy', 25, 'male')
print(b.name)
print(b.age)
print(b.sex)
print(b.country)
# 2.2 子類重寫父類方法
f = FatherClass('A', 30)
f.talk()
b.talk()
複製代碼

2.3 多態

  多態是指一類事物具備多種形態。Python的多態性是指在不考慮實例類型的狀況使用實例,也就是說不一樣類型的實例有相同的調用方法。【GitHub代碼commits id:de62018

  使用多態的好處:

(1)增長了程序的靈活性:以不變應萬變,不論對象變幻無窮,使用同一種形式去調用,如show_say(animal)
(2)增長了程序的可擴展性:經過繼承Animal(下面代碼例子)類建立了一個新的類,使用者無需更改本身的代碼,仍是用show_say(animal)方法去調用。
複製代碼
class Animal(object):       # 同一類事物:動物
    def say(self):
        print("I'm animal.")


class Dog(Animal):          # 動物的形態之一:狗
    def say(self):
        print("Wang wang~")


class Cat(Animal):          # 動物的形態之一:貓
    def say(self):
        print("Miao miao~")


class Cow(Animal):          # 動物的形態之一:牛
    def say(self):
        print("Mou mou~")


d = Dog()
ca = Cat()
co = Cow()
# d, ca, co 都是動物,都屬於動物類,確定都有say_hi()方法,所以不用考慮他們具體是什麼類型,直接使用便可
d.say()
ca.say()
co.say()
# 咱們能夠統一一個接口來調用動物類的say_hi()方法
def show_say(animal):
    animal.say()


show_say(d)
show_say(ca)
show_say(co)
複製代碼

3. 元類

  Python中一切皆對象,那麼咱們用class關鍵字定義的類自己也是一個對象,負責產生該對象的類稱之爲元類。

  學習元類是爲了控制類的產生過程,還能控制對象的產生過程。 【GitHub示例

3.1 漸入元類

  類對象能夠用 class 關鍵字建立,類對象的類型是 type,也就是說能夠經過 type(元類)來建立。

# 默認的元類type實例化出一個對象Foo,實例化的結果也是一個對象
class Foo(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print("%s is eating." % self.name)


f1 = Foo('mi', 9)


number = 12
dicts = {
    "name": "crisimple",
    "age": 23
}


print("number的ID是:", id(number))
print("dicts的ID是:", id(dicts))
print("number的type是:", type(number))
print("dicts的type是:", type(dicts))

print("Foo的ID是:", id(Foo))
print("Foo的type是:", type(Foo))      # Foo的type是: <class 'type'>
print("f1的ID是:", id(f1))
print("f1的type是:", type(f1))        # f1的type是: <class '__main__.Foo'>
# --------------------------------------
# instance ---[instance of]---> class ---[instance of]---> metaclass
# f1 ----------------> Foo --------------> type【type就是元類,元類本身也是對象】
複製代碼

3.2 用元類建立類

Person = type("Person", (object, ), {"live": True, "name": 'crisimple'})
print(type(Person))
p1 = Person()
print(type(p1))
複製代碼

=================【Python高級編程】===========

相關文章
相關標籤/搜索