主頁 > 後端開發 > Python:函式與面向物件編程總結

Python:函式與面向物件編程總結

2021-08-09 08:09:21 後端開發

文章目錄

  • 函式
    • 函式的定義
    • 函式的引數
    • 用模塊管理函式
    • 高階函式
    • Lambda函式
    • 遞回呼叫
    • 例題
      • 例題1:漢諾塔問題
      • 例題2:爬樓梯
      • 例題3:冒泡排序
      • 例題4:撰寫實作查找元素的函式
      • 例題5:判斷快樂數
  • 面向物件編程
    • 面向物件編程的程序
    • 定義類
    • 創建物件
    • 給物件發訊息
    • 面向物件的支柱
    • 靜態方法和類方法
    • 繼承和多型
    • 魔術方法
    • 類和類之間的關系

函式

函式的定義

函式就是對實作某一特定功能的代碼的封裝,

在Python中可以使用def關鍵字來定義函式,函式的命名規則跟變數的命名規則是一致的,

# 定義函式:def是定義函式的關鍵字、fac是函式名,num是引數(自變數)
def fac(num):
    """求階乘"""
    result = 1
    for n in range(1, num + 1):
        result *= n
    # 回傳num的階乘(因變數)
    return result

函式的引數

  • 位置引數:傳入引數的時候對號入座即可;也可以通過引數名=引數值的方式傳入函式所需的引數,因為指定了引數名,傳入引數的順序可以進行調整,
  • 命名關鍵字引數:在函式的引數串列中,寫在*之后的引數,傳參時,只能以引數名=引數值的方式傳參,
  • 關鍵字引數:Python中可以通過*kwargs運算式語法傳入0個或任意多個引數名=引數值形式的引數,關鍵字引數會將傳入的帶引數名的引陣列裝成一個字典,引數名就是字典中鍵值對的鍵,而引數值就是字典中鍵值對的值,
  • 可變引數:可以實作向一個函式中傳0個或任意多個引數,Python中可以通過*args運算式語法來支持可變引數,(不能接收帶引數名的引數

注意:不帶引數名的引數(位置引數)必須出現在帶引數名的引數(關鍵字引數)之前

def add(*args, **kwargs):
    """加法"""
    total = 0
    for arg in args:
        if type(arg) in (int, float):
            total += arg
    for value in kwargs.values():
        if type(value) in (int, float):
            total += value
    return total
# 傳入0個引數
print(add())
# 只傳入可變引數
print(add(1, 2, 3))
# 只傳入關鍵字引數
print(add(a=1, b=2, c=3))
# 傳入位置引數和關鍵字引數,關鍵字引數在*args的‘*’之后,因此也是命名關鍵字引數
print(add(1, 2, c=3, d=4))

用模塊管理函式

Python中每個檔案就代表了一個模塊(module),在不同模塊可以有同名的函式,在使用函式時,通過import關鍵字匯入指定的模塊,再使用完全限定名的呼叫方式就可以區分是哪個模塊中的函式,

高階函式

函式的引數和回傳值可以是任意型別的物件,這就意味著函式本身也可以作為函式的引數或回傳值,這就是所謂的高階函式

# 中間兩個引數是命名關鍵字引數,必須帶上引數名
def calculate(*args, init_value, op, **kwargs):
    """可以做任意二元運算的函式

    :param init_value:初始值
    :param op: 一個實作二元運算(+、*)的函式
    :param args: 位置引數
    :param kwargs: 關鍵字引數
    :return: 運算結果
    """
    total = init_value
    for arg in args:
        if type(arg) in (int, float):
            total = op(total, arg)
    for value in kwargs.values():
        if type(value) in (int, float):
            total = op(total, value)
    return total


def add(a, b):
    return a + b


def mul(a, b):
    return a * b


print(calculate(1, 2, 30, init_value=0, op=add))
print(calculate(1, 2, 3, init_value=0, op=mul))
print(calculate(15, 20, init_value=100, op=add, c=5))

Lambda函式

在使用高階函式的時候,如果作為引數或者回傳值的函式本身非常簡單,一行代碼就能夠完成,那么我們可以使用Lambda函式來表示,如上面的add函式和mul函式

# 中間兩個引數是命名關鍵字引數,必須帶上引數名
def calculate(*args, init_value, op, **kwargs):
    """可以做任意二元運算的函式

    :param init_value:初始值
    :param op: 一個實作二元運算(+、-、*、/)的函式
    :param args: 位置引數
    :param kwargs: 關鍵字引數
    :return: 運算結果
    """
    total = init_value
    for arg in args:
        if type(arg) in (int, float):
            total = op(total, arg)
    for value in kwargs.values():
        if type(value) in (int, float):
            total = op(total, value)
    return total

# 呼叫calculate函式,通過lambda函式給op引數賦值
print(calculate(1, 2, 30, init_value=0, op=lambda x, y: x + y, a=5))
print(calculate(1, 2, 3, init_value=1, op=lambda x, y: x * y))
print(calculate(15, 20, init_value=100, op=lambda x, y: x - y))

遞回呼叫

Python中允許函式嵌套定義,也允許函式之間相互呼叫,而且一個函式還可以直接或間接的呼叫自身,

遞回函式的要點:
1.遞回公式:(第n次與第n-1次的關系)
2.收斂條件(什么時候停止遞回呼叫)

例題

例題1:漢諾塔問題

a柱上有n個盤子,要把所有盤子搬到b柱上,借用c柱幫助搬運,大盤不能壓在小盤上面,

def move(n, a, c, b):
    if n == 1:
        print(f'{a}->{b}')
    else:
        move(n - 1, a, b, c)
        move(1, a, c, b)
        move(n - 1, c, a, b)


if __name__ == '__main__':
    n = int(input('請輸入盤子數:'))
    move(n, 'a', 'c', 'b')

例題2:爬樓梯

有一個小孩爬樓梯,一次可以爬1個臺階、2個臺階或3個臺階,問爬完10個臺階,有多少種走法?

def step(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    elif n == 3:
        return 4
    else:
        return step(n - 1) + step(n - 2) + step(n - 3)


if __name__ == '__main__':
    print(step(10))

例題3:冒泡排序

def bubble_sort(nums, ascending=True, gt=lambda x, y: x > y):
    """冒泡排序

    :param nums: 待排序的串列
    :param ascending: 是否使用升序
    :param gt: 比較兩個元素大小的函式
    :return: 排序后的串列
    """
    sort_nums = nums[:]
    for i in range(1, len(sort_nums)):
        swapped = False
        for j in range(0, len(sort_nums) - i):
            if gt(sort_nums[j], sort_nums[j + 1]):
                sort_nums[j + 1], sort_nums[j] = sort_nums[j], sort_nums[j + 1]
                swapped = True
        if not swapped:
            break
    if not ascending:
        return sort_nums[::-1]
    return sort_nums


nums = [15, 20, 10, 15, 12, 30, 65]
# 使用默認的gt函式
print(bubble_sort(nums, False))
print(nums)

words = ['apple', 'watermelon', 'hello', 'zoo', 'internationalization']
# 修改gt函式根據字串長度排序
print(bubble_sort(words, gt=lambda x, y: len(x) > len(y), ascending=False))

例題4:撰寫實作查找元素的函式

若串列元素無序,使用順序查找;若串列元素有序,使用二分查找(折半查找),

def seq_search(items, key):
    for index, i in enumerate(items):
        if i == key:
            return index
    return -1


def bin_search(items, key, cmp=lambda x, y: x - y):
    """折半查找(漸進時間復雜度:(log2 n))

    :param cmp: 比較兩個元素的大小
    :param items: 一個有序串列
    :param key: 查找的元素
    :return: 找到了回傳元素下標,沒找到回傳-1
    """
    high = len(items) - 1
    low = 0
    while low <= high:
        mid = (high + low) // 2
        if cmp(items[mid], key) > 0:
            high = mid - 1
        elif cmp(items[mid], key) < 0:
            low = mid + 1
        else:
            return mid
    return -1


if __name__ == '__main__':
    nums1 = [78, 58, 93, 42, 45, 66, 12, 15]
    nums2 = [1, 15, 25, 40, 80, 92, 98, 99]
    print(seq_search(nums1, 58))
    print(seq_search(nums1, 40))
    print(bin_search(nums2, 99))
    print(bin_search(nums2, 85))

例題5:判斷快樂數

對于一個正整數,每一次將該數替換為它每個位置上的數字的平方和,然后重復這個程序,如果數字變成了1,這個數就是快樂數,如果無限回圈始終變不到1,這個數就不是快樂數,

def is_happy_num(num):
    temp = []
    while num not in temp:
        temp.append(num)
        total = 0
        while num != 0:
            total += (num % 10) ** 2
            num //= 10
        if total == 1:
            return True
        num = total
    return False


for i in range(100, 1001):
    if is_happy_num(i):
        print(i, end=' ')

面向物件編程

面向物件編程:把一組資料和處理資料的方法組成物件,把行為相同的物件歸納為,通過封裝隱藏物件的內部細節,通過繼承實作類的特化與泛化,通過多型實作基于物件型別的動態分派,

面向物件編程的程序

  1. 定義類

    —資料抽象:找到物件相關的靜態特征(屬性)—>找名詞

    —行為抽象:找到和物件相關的動態特征(方法)—>找動詞

  2. 創建物件

  3. 給物件發訊息

定義類

在Python中,可以使用class關鍵字加上類名來定義類,通過縮進我們可以確定類的代碼塊,就如同定義函式那樣,

class Student:

	def __init__(self, name, age):
        """初始化方法"""
        self.name = name
        self.age = age
    def study(self, course_name):
        print(f'{self.name}正在學習{course_name}.')

    def play(self, game_name):
        print(f'{self.name}正在玩{game_name}游戲.')

創建物件

stu1 = Student('小青', 20)
stu2 = Student('小白', 22)

給物件發訊息

# 通過“類.方法”呼叫方法,第一個引數是接收訊息的物件,第二個引數是學習的課程名稱
Student.study(stu1, 'Python程式設計')
# 通過“物件.方法”呼叫方法,點前面的物件就是接收訊息的物件,只需要傳入第二個引數
stu1.study('Python程式設計') 
stu2.play('王者榮耀')

一般使用“物件.方法”呼叫方法

面向物件的支柱

面向物件編程的四大支柱:

  • 抽象:提取共性(定義類就是一個抽象程序,需要做資料抽象和行為抽象),
  • 封裝:把資料和操作資料的函式從邏輯上組成一個整體(物件),隱藏實作細節,暴露簡單的呼叫介面
  • 繼承:擴展已有的類創建新類,實作對已有類的代碼復用,
  • 多型:給不同的物件發出同樣的訊息,不同的物件執行了不同的行為,

靜態方法和類方法

使用staticmethod裝飾器宣告某個方法是某個類的靜態方法,如果要宣告類方法,可以使用classmethod裝飾器,可以直接使用類名.方法名的方式來呼叫靜態方法和類方法,二者的區別在于,類方法的第一個引數是類物件本身,而靜態方法則沒有這個引數,簡單的總結一下,物件方法、類方法、靜態方法都可以通過類名.方法名的方式來呼叫,區別在于方法的第一個引數到底是普通物件還是類物件,還是沒有接受訊息的物件

繼承和多型

繼承的語法是在定義類的時候,在類名后的圓括號中指定當前類的父類,在子類的初始化方法中,我們可以通過super().__init__()來呼叫父類初始化方法,super函式是Python內置函式中專門為獲取當前物件的父類物件而設計的,子類除了可以通過繼承得到父類提供的屬性和方法外,還可以定義自己特有的屬性和方法,所以子類比父類擁有的更多的能力,
子類繼承父類的方法后,還可以對方法進行重寫(重新實作該方法),
多型就是呼叫相同的方法不同的子類物件做不同的事情

魔術方法

魔術方法(魔法方法):有特殊用途和意義的方法,
Python中有很多魔法方法,下面是幾個常用的:
__init__ —> 初始化方法,在呼叫構造器語法創建物件的時候會被自動呼叫
__str__ —> 獲得物件的字串表示,在呼叫print函式輸出物件時會被自動呼叫
__repr__ —> 獲得物件的字串表示,把物件放到容器中呼叫print輸出時會自動呼叫
__lt__ —> 在使用 < 運算子比較兩個物件大小時會自動呼叫

類和類之間的關系

類和類之間的關系可以粗略的分為is-a關系(繼承)has-a關系(關聯)use-a關系(依賴)

  • is-a關系:繼承
  • has-a關系:關聯 —>把一個類的物件作為另一個類的物件的屬性
    —普通關聯
    —強關聯:整體和部分的關聯,聚合和合成
  • use-a關系:依賴 —> 一個類的物件作為另一個類的方法的引數或回傳值

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/292502.html

標籤:python

上一篇:學習python第十六天, 一周總結

下一篇:Pytorch深度學習50篇·······第二篇:人臉識別(1)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more