溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

python函數(shù)和面向?qū)ο髮?shí)例分析

發(fā)布時間:2022-02-15 13:39:42 來源:億速云 閱讀:148 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“python函數(shù)和面向?qū)ο髮?shí)例分析”,在日常操作中,相信很多人在python函數(shù)和面向?qū)ο髮?shí)例分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”python函數(shù)和面向?qū)ο髮?shí)例分析”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

    函數(shù)

    python中『一切皆對象』, 函數(shù)也不例外.

    在之前所學(xué)的C++Java中, 可以發(fā)現(xiàn)函數(shù)的返回值要么為空, 要么是某種數(shù)據(jù)類型, 但是在python中, 返回值可以是任何對象, 包括函數(shù).

    函數(shù)參數(shù)

    函數(shù)的參數(shù)種類比較多, 主要有:

    1.位置參數(shù) (positional argument): 就是最常見的x, y等

    2默認(rèn)參數(shù) (default argument): 給定一個默認(rèn)值, 用戶也可以傳入實(shí)參來調(diào)整.

    def func(x, y=3):
        print(x+y)
    
    func(1)  # 4
    func(1, 666)  # 667

    3.可變參數(shù) (variable argument): 不限制輸入?yún)?shù)的個數(shù), 傳入后自動保存為元組類型.

    1.*args 是可變參數(shù),args 接收的是一個 tuple

    def printinfo(arg1, *args):
        print(arg1)
        print(args, type(args))
    
    printinfo(10)  # 僅一個參數(shù), 沒有屬于args的.
    # 10
    # () <class 'tuple'>
    printinfo(70, 60, 50)  # 除arg1位置匹配的, 其他都傳入給可變參數(shù)
    # 70
    # (60, 50) <class 'tuple'>

    4.關(guān)鍵字參數(shù) (keyword argument): 不限制關(guān)鍵字的個數(shù)和命名, 傳入后自動保存為字典的形式.

    1.**kw 是關(guān)鍵字參數(shù),kw 接收的是一個 dict

    def printinfo(arg1, *args):
        print(arg1)
        print(args, type(args))
    
    printinfo(10)  # 僅一個參數(shù), 沒有屬于args的.
    # 10
    # () <class 'tuple'>
    printinfo(70, 60, 50)  # 除arg1位置匹配的, 其他都傳入給可變參數(shù)
    # 70
    # (60, 50) <class 'tuple'>

    5.命名關(guān)鍵字參數(shù) (name keyword argument)

    1.命名關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的『參數(shù)名』,也可以提供默認(rèn)值.

    2.與關(guān)鍵字參數(shù)不同的是, 關(guān)鍵字參數(shù)的名字和值都是任意的, 后續(xù)再進(jìn)行匹配使用, 而命名關(guān)鍵字則只能接受給定的關(guān)鍵字作為參數(shù).定義命名關(guān)鍵字參數(shù)

    3.不要忘了寫分隔符 *, 否則定義的是位置參數(shù), 命名關(guān)鍵字參數(shù)調(diào)用函數(shù)時必須給定參數(shù)名.

    def person(name, *, age, height=1.90):
        print(f'{name}今年{age}歲, 身高{height:.2f}m')
    
    
    person('張三', age=18, height=1.80)  # 張三今年18歲, 身高1.80m
    person('李四', age=18)  # 李四今年18歲, 身高1.90m
    person('王五')  # TypeError, 需要傳入給定關(guān)鍵字

    6.參數(shù)組合

    Python中定義函數(shù)時, 以上這5種參數(shù)都可以使用, d但最多可以使用4種, 并且要注意順序:

    1.位置參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù).

    2.位置參數(shù)、默認(rèn)參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù).

    變量作用域

    在python程序中, 處于不同位置的變量, 有不同的作用域.

    • 定義在函數(shù)內(nèi)部的變量擁有局部作用域, 該變量稱為局部變量.

    • 定義在函數(shù)外部的變量擁有全局作用域, 該變量稱為全局變量.

    • 局部變量只能在其被聲明的函數(shù)內(nèi)部訪問, 而全局變量可以在整個程序范圍內(nèi)訪問.

    需要注意的是:

    • 當(dāng)局部變量試圖訪問全局變量時, 一定要在函數(shù)內(nèi)聲明global.

    • 當(dāng)局部變量與全局變量命名沖突時, 程序會優(yōu)先選擇局部變量.

    內(nèi)嵌函數(shù)和閉包

    內(nèi)嵌函數(shù)就是在外層函數(shù)內(nèi)定義內(nèi)層函數(shù).

    def outer():
        print('outer函數(shù)在這被調(diào)用')
    
        def inner():
            print('inner函數(shù)在這被調(diào)用')
    
        inner()  # 該函數(shù)只能在outer函數(shù)內(nèi)部被調(diào)用
    
    
    outer()
    # outer函數(shù)在這被調(diào)用
    # inner函數(shù)在這被調(diào)用

    閉包是一個比較重要的語法結(jié)構(gòu), 結(jié)構(gòu)上與內(nèi)嵌函數(shù)類似, 區(qū)別在于返回值, 閉包的外層函數(shù)返回值是一個函數(shù).

    如果在一個內(nèi)部函數(shù)里對外層非全局作用域的變量進(jìn)行引用, 那么內(nèi)部函數(shù)就被認(rèn)為是閉包.

    通過閉包可以訪問外層非全局作用域的變量, 這個作用域稱為閉包作用域.

    def funX(x):
        def funY(y):
            print('使用funY(y)')
            return x * y
    
        return funY
    
    
    i = funX(8)
    print(type(i))  # <class 'function'>
    print(i(5))  # 40

    注意到上述代碼中, 內(nèi)部函數(shù)FunY中使用了外部非全局作用域的變量x.

    同樣是, 函數(shù)內(nèi)嵌套的函數(shù)作用域也需要特別注意, 若我們需要修改閉包內(nèi)的變量, 需要使用nonlocal關(guān)鍵字.

    num = 999
    
    
    def outer():
        num = 10
    
        def inner():
            nonlocal num  # nonlocal關(guān)鍵字聲明
            num = 100
            print(f'inner中num = {num}')
    
        inner()
        print(f'outer中num = {num}')
    
    
    outer()
    # inner中num = 100
    # outer中num = 100
    print(f'全局中num = {num}')
    # 全局中num = 999

    lambda 表達(dá)式

    lambda需要注意的是:

    • 匿名函數(shù)沒有return, 表達(dá)式本身就是返回值.

    • 匿名函數(shù)擁有『自己的命名空間』, 不能訪問參數(shù)列表之外或全局變量.

    匿名函數(shù)主要適用于函數(shù)式編程(函數(shù)不會影響函數(shù)之外的內(nèi)容)的一些高階函數(shù)中. 例如map映射和filter過濾, 當(dāng)然也可以在自己自定義函數(shù)中使用.

    odd = lambda x: x % 2 == 1
    templist = filter(odd, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    print(list(templist))  # [1, 3, 5, 7, 9]
    
    m1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
    print(list(m1))  # [1, 4, 9, 16, 25]

    面向?qū)ο?/h3>

    三大特性

    面向?qū)ο缶捅仨毩私馊筇匦?

    • 封裝: 把客觀事物封裝成抽象的類, 讓數(shù)據(jù)和方法給信任的類或?qū)ο蟛僮? 而隱藏部分信息.

    • 繼承: 子類自動共享父類的屬性和方法.

      • 一般認(rèn)為一個類是自身的子類;

      • 可以使用issubclass(B, A)查看B是否是A的子類.

      • python也支持多繼承, 但會使得類的整體層次復(fù)雜, 所以并不建議使用.

    • 多態(tài): 同一個方法的調(diào)用, 會由于不同對象而得到不同的結(jié)果.

      • 必要條件是繼承方法的重寫.

    類、類對象 和 實(shí)例對象

    • 類: 就是指對類的定義

    • 類對象: 是在創(chuàng)建類的時候, 在內(nèi)存開辟的一個空間, 一個類只有一個類對象.

    • 實(shí)例對象: 通過實(shí)例化類創(chuàng)建的對象, 可以有多個.

    類屬性 和 對象屬性

    • 類屬性: 類定義內(nèi), 類方法外定義的變量稱為類屬性, 類屬性屬于類對象, 可以被多個實(shí)例化對象所共享, 就像我們都有一個家, 名字叫中國一樣.

    • 對象屬性: 對象屬性和具體創(chuàng)建的對象實(shí)例直接相關(guān), 并且相互之間不共享屬性, 就像我的老婆只是我的一樣.

    class A():
        a = 0  #類屬性
        def __init__(self, xx):
            A.a = xx  #使用類屬性可以通過 (類名.類屬性)調(diào)用。

    有一些操作屬性的方法:

    • 使用hasattr(object, name)來判斷對象是否包含對應(yīng)的屬性或方法.

    • 使用getattr(object, name)來獲取屬性或方法.

    • 使用setattr(object, name, value)來修改屬性值, 或創(chuàng)建新的屬性和值.

    • 使用delattr(object, name)來刪除屬性.

    class A(object):
        name = '張三'
        def set(self, a, b):
            x = a
            a = b
            b = x
            print(a, b)
    
    
    a = A()
    print(hasattr(a, 'name'))  # 判斷是否有name屬性 True
    print(hasattr(a, 'set'))  # 判斷是否有set方法 True
    x = getattr(a, 'name')  # 獲取屬性值
    print(x)  # 張三
    c = getattr(a, 'set')  # 獲取方法
    c(a='1', b='2')  # 2 1

    私有

    私有屬性和方法僅需在定義命名的時候加上兩個下劃線"__"即可.

    相對于公有屬性和公有方法來說, 私有屬性和私有方法更加的安全. 從定義上來說, 將需要安全保護(hù)的屬性和方法封裝為私有, 可以阻止外部直接調(diào)用, 而必須使用實(shí)例化對象方法類方法進(jìn)行調(diào)用, 從而提高安全性.

    但在python中的私有是『偽私有』, 即可以使用類名, 通過 object._className__attrName 訪問私有屬性,用 object._className__func() 訪問私有方法.

    class JustCounter:
        __secretCount = 0  # 私有變量
        publicCount = 0  # 公開變量
    
        def count(self):
            self.__secretCount += 1
            self.publicCount += 1
            print(self.__secretCount)
    
    
    counter = JustCounter()
    counter.count()  # 1
    print(counter.publicCount)  # 1
    # 特殊方法依舊可以訪問
    print(counter._JustCounter__secretCount)  # 1
    # 直接訪問則會報錯.
    print(counter.__secretCount)

    實(shí)例直接使用點(diǎn)就可以增加屬性了, 這點(diǎn)需要注意一下.

    class B:
        def func(self):
            print('調(diào)用func方法')
    
    
    b = B()
    print(b.__dict__)  # 查看屬性 {}
    b.name = '張三'
    b.age = 18
    print(b.__dict__)  # 查看屬性{'name': '張三', 'age': 18}
    
    b1 = B()
    print(b1.__dict__)  # 查看屬性 {}

    魔法方法

    基本的魔法方法

    魔法方法基本上是被下劃線包圍的一些特殊方法. 相比于普通的方法, 它能夠在適當(dāng)?shù)臅r候自動調(diào)用. 第一個參數(shù)一般是cls『類方法』或者self『實(shí)例方法』.

    • __init__(self[, ...]) 構(gòu)造器, 當(dāng)一個實(shí)例被創(chuàng)建的時候調(diào)用的初始化方法.

    • __new__(cls[, ...]) 在一個對象實(shí)例化的時候所調(diào)用的第一個方法, 在調(diào)用__init__初始化前, 先調(diào)用__new__.

      • 需要注意的是, __new__的返回值必須為當(dāng)前類的實(shí)例, 否則將不會調(diào)用__init__初始化.

      • 主要是在繼承一些不可變的class(比如int, str, tuple)時, 提供一個自定義該類實(shí)例化過程的途徑. 

    • __del__(self) 析構(gòu)器, 當(dāng)一個對象將要被系統(tǒng)回收之時調(diào)用的方法.

    • __str__(self): 當(dāng)你打印一個對象、使用%s格式化或使用str強(qiáng)轉(zhuǎn)數(shù)據(jù)類型的時候,觸發(fā)__str__.

    • __repr__(self)__str__(self)的備胎, 情況類似, 不過自定義時往往更加準(zhǔn)確, 主要用于調(diào)試.

    算術(shù)運(yùn)算符

    普通的計算在對象中是無法進(jìn)行的, 需要自定義計算方式.

    __add__(self, other)定義加法的行為: +

    __sub__(self, other)定義減法的行為: -

    __mul__(self, other)定義乘法的行為: *

    __truediv__(self, other)定義真除法的行為: /

    __floordiv__(self, other)定義整數(shù)除法的行為: //

    __mod__(self, other) 定義取模算法的行為: %

    __divmod__(self, other)定義當(dāng)被 divmod() 調(diào)用時的行為 

    divmod(a, b)把除數(shù)和余數(shù)運(yùn)算結(jié)果結(jié)合起來,返回一個包含商和余數(shù)的元組(a // b, a % b)。 

    __pow__(self, other[, module])定義當(dāng)被 power() 調(diào)用或 ** 運(yùn)算時的行為

    __lshift__(self, other)定義按位左移位的行為: <<

    __rshift__(self, other)定義按位右移位的行為: >>

    __and__(self, other)定義按位與操作的行為: &

    __xor__(self, other)定義按位異或操作的行為: ^

    __or__(self, other)定義按位或操作的行為: |

    還有對應(yīng)的反運(yùn)算符, 在之前加上r即可, 例如__rsub__. 對應(yīng)增量賦值運(yùn)算符, 在之前加上i即可, 例如__isub__.

    屬性訪問 

    __getattr__(self, name): 定義當(dāng)用戶試圖獲取一個不存在的屬性時的行為.

    __getattribute__(self, name): 定義當(dāng)該類的屬性被訪問時的行為(先調(diào)用該方法, 查看是否存在該屬性, 若不存在, 接著去調(diào)用__getattr__).

    __setattr__(self, name, value): 定義當(dāng)一個屬性被設(shè)置時的行為.

    __delattr__(self, name): 定義當(dāng)一個屬性被刪除時的行為.

    描述符

    描述符就是將某種特殊類型的類的實(shí)例指派給另一個類的屬性.

    __get__(self, instance, owner): 用于訪問屬性, 它返回屬性的值.

    __set__(self, instance, value): 將在屬性分配操作中調(diào)用, 不返回任何內(nèi)容.

    __del__(self, instance): 控制刪除操作, 不返回任何內(nèi)容.

    迭代器和生成器

    迭代器

    迭代是Python最強(qiáng)大的功能之一, 是訪問集合元素的一種方式.

    • 迭代器是一個可以記住遍歷的位置的對象.

    • 迭代器對象從集合的第一個元素開始訪問, 直到所有的元素被訪問完結(jié)束.

    • 迭代器只能往前不會后退.

    • 字符串, 列表或元組對象都可用于創(chuàng)建迭代器.

    迭代器有兩個基本的方法: iter() 和 next():

    • iter(object) 函數(shù)用來生成迭代器.

    • next(iterator[, default]) 返回迭代器的下一個項目. 在元素為空時返回默認(rèn)值, 若沒有則會觸發(fā) StopIteration 異常. 在元組推導(dǎo)式和next中使用過, 不過是下面的『生成器』.

    把一個類作為一個迭代器使用需要在類中實(shí)現(xiàn)兩個魔法方法 __iter__() 與 __next__() .

    • __iter__(self)定義當(dāng)?shù)萜髦械脑氐男袨? 返回一個特殊的迭代器對象, 這個迭代器對象實(shí)現(xiàn)了 __next__() 方法并通過 StopIteration 異常標(biāo)識迭代的完成.

    • __next__() 返回下一個迭代器對象. 

      • StopIteration 異常用于標(biāo)識迭代的完成,防止出現(xiàn)無限循環(huán)的情況,在 __next__() 方法中我們可以設(shè)置在完成指定循環(huán)次數(shù)后觸發(fā) StopIteration 異常來結(jié)束迭代。

    class Fibs:
        def __init__(self, n=10):
            self.a = 0
            self.b = 1
            self.n = n
    
        def __iter__(self):
            return self
    
        def __next__(self):
            self.a, self.b = self.b, self.a + self.b
            if self.a > self.n:
                raise StopIteration
            return self.a
    
    
    fibs = Fibs(100)
    for each in fibs:
        print(each, end=' ')
    
    # 1 1 2 3 5 8 13 21 34 55 89

    生成器

    在 Python 中,使用了 yield 的函數(shù)被稱為生成器(generator)。

    • 跟普通函數(shù)不同的是, 生成器是一個返回迭代器的函數(shù), 只能用于迭代操作, 更簡單點(diǎn)理解生成器就是一個迭代器.

    • 在調(diào)用生成器運(yùn)行的過程中, 每次遇到 yield 時函數(shù)會暫停并保存當(dāng)前所有的運(yùn)行信息, 返回 yield 的值, 并在下一次執(zhí)行 next() 方法時從當(dāng)前位置繼續(xù)運(yùn)行.

    • 調(diào)用一個生成器函數(shù), 返回的是一個迭代器對象.

    def libs(n):
        a = 0
        b = 1
        while True:
            a, b = b, a + b
            if a > n:
                return
            yield a
    
    
    for each in libs(100):
        print(each, end=' ')
    
    # 1 1 2 3 5 8 13 21 34 55 89

    到此,關(guān)于“python函數(shù)和面向?qū)ο髮?shí)例分析”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI