溫馨提示×

溫馨提示×

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

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

Python面向?qū)ο缶幊淘趺蠢斫?/h1>
發(fā)布時間:2021-11-30 15:17:38 來源:億速云 閱讀:220 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“Python面向?qū)ο缶幊淘趺蠢斫狻?,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Python面向?qū)ο缶幊淘趺蠢斫狻卑?

面向?qū)ο缶幊淌且环N非常流行的編程范式(programming paradigm),所謂編程范式就是程序設(shè)計的方法學(xué),也就是程序員對程序的認(rèn)知和理解。

類和對象

如果要用一句話來概括面向?qū)ο缶幊蹋艺J(rèn)為下面的說法是相當(dāng)精準(zhǔn)的。

面向?qū)ο缶幊蹋喊岩唤M數(shù)據(jù)和處理數(shù)據(jù)的方法組成對象,把行為相同的對象歸納為類,通過封裝隱藏對象的內(nèi)部細(xì)節(jié),通過繼承實(shí)現(xiàn)類的特化和泛化,通過多態(tài)實(shí)現(xiàn)基于對象類型的動態(tài)分派。

這句話對初學(xué)者來說可能難以理解,但是我們先為大家圈出幾個關(guān)鍵詞:對象(object)、類(class)、封裝(encapsulation)、繼承(inheritance)、多態(tài)(polymorphism)。

我們先說說類和對象這兩個詞。在面向?qū)ο缶幊讨?,類是一個抽象的概念,對象是一個具體的概念。我們把同一類對象的共同特征抽取出來就是一個類,比如我們經(jīng)常說的人類,這是一個抽象概念,而我們每個人就是人類的這個抽象概念下的具體的實(shí)實(shí)在在的存在,也就是一個對象。簡而言之,類是對象的藍(lán)圖和模板,對象是類的實(shí)例。

在面向?qū)ο缶幊痰氖澜缰校磺薪詾閷ο?,對象都有屬性和行為,每個對象都是獨(dú)一無二的,而且對象一定屬于某個類。對象的屬性是對象的靜態(tài)特征,對象的行為是對象的動態(tài)特征。按照上面的說法,如果我們把擁有共同特征的對象的屬性和行為都抽取出來,就可以定義出一個類。

定義類

在Python中,可以使用class關(guān)鍵字加上類名來定義類,通過縮進(jìn)我們可以確定類的代碼塊,就如同定義函數(shù)那樣。在類的代碼塊中,我們需要寫一些函數(shù),我們說過類是一個抽象概念,那么這些函數(shù)就是我們對一類對象共同的動態(tài)特征的提取。寫在類里面的函數(shù)我們通常稱之為方法,方法就是對象的行為,也就是對象可以接收的消息。方法的第一個參數(shù)通常都是self,它代表了接收這個消息的對象本身。

class Student:

   def study(self, course_name):
       print(f'學(xué)生正在學(xué)習(xí){course_name}.')

   def play(self):
       print(f'學(xué)生正在玩游戲.')

創(chuàng)建和使用對象

在我們定義好一個類之后,可以使用構(gòu)造器語法來創(chuàng)建對象,代碼如下所示。

stu1 = Student()
stu2 = Student()
print(stu1)    # <__main__.Student object at 0x10ad5ac50>
print(stu2)    # <__main__.Student object at 0x10ad5acd0>
print(hex(id(stu1)), hex(id(stu2)))    # 0x10ad5ac50 0x10ad5acd0

在類的名字后跟上圓括號就是所謂的構(gòu)造器語法,上面的代碼創(chuàng)建了兩個學(xué)生對象,一個賦值給變量stu1,一個復(fù)制給變量stu2。當(dāng)我們用print函數(shù)打印stu1和stu2兩個變量時,我們會看到輸出了對象在內(nèi)存中的地址(十六進(jìn)制形式),跟我們用id函數(shù)查看對象標(biāo)識獲得的值是相同的。現(xiàn)在我們可以告訴大家,我們定義的變量其實(shí)保存的是一個對象在內(nèi)存中的邏輯地址(位置),通過這個邏輯地址,我們就可以在內(nèi)存中找到這個對象。所以stu3 = stu2這樣的賦值語句并沒有創(chuàng)建新的對象,只是用一個新的變量保存了已有對象的地址。

接下來,我們嘗試給對象發(fā)消息,即調(diào)用對象的方法。剛才的Student類中我們定義了study和play兩個方法,兩個方法的第一個參數(shù)self代表了接收消息的學(xué)生對象,study方法的第二個參數(shù)是學(xué)習(xí)的課程名稱。Python中,給對象發(fā)消息有兩種方式,請看下面的代碼。

# 通過“類.方法”調(diào)用方法,第一個參數(shù)是接收消息的對象,第二個參數(shù)是學(xué)習(xí)的課程名稱
Student.study(stu1, 'Python程序設(shè)計')    # 學(xué)生正在學(xué)習(xí)Python程序設(shè)計.
# 通過“對象.方法”調(diào)用方法,點(diǎn)前面的對象就是接收消息的對象,只需要傳入第二個參數(shù)
stu1.study('Python程序設(shè)計')             # 學(xué)生正在學(xué)習(xí)Python程序設(shè)計.

Student.play(stu2)    # 學(xué)生正在玩游戲.
stu2.play()           # 學(xué)生正在玩游戲.

初始化方法

大家可能已經(jīng)注意到了,剛才我們創(chuàng)建的學(xué)生對象只有行為沒有屬性,如果要給學(xué)生對象定義屬性,我們可以修改Student類,為其添加一個名為__init__的方法。在我們調(diào)用Student類的構(gòu)造器創(chuàng)建對象時,首先會在內(nèi)存中獲得保存學(xué)生對象所需的內(nèi)存空間,然后通過自動執(zhí)行__init__方法,完成對內(nèi)存的初始化操作,也就是把數(shù)據(jù)放到內(nèi)存空間中。所以我們可以通過給Student類添加__init__方法的方式為學(xué)生對象指定屬性,同時完成對屬性賦初始值的操作,正因如此,__init__方法通常也被稱為初始化方法。

我們對上面的Student類稍作修改,給學(xué)生對象添加name(姓名)和age(年齡)兩個屬性。

class Student:
   """學(xué)生"""

   def __init__(self, name, age):
       """初始化方法"""
       self.name = name
       self.age = age

   def study(self, course_name):
       """學(xué)習(xí)"""
       print(f'{self.name}正在學(xué)習(xí){course_name}.')

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

修改剛才創(chuàng)建對象和給對象發(fā)消息的代碼,重新執(zhí)行一次,看看程序的執(zhí)行結(jié)果有什么變化。

# 由于初始化方法除了self之外還有兩個參數(shù)
# 所以調(diào)用Student類的構(gòu)造器創(chuàng)建對象時要傳入這兩個參數(shù)
stu1 = Student('駱昊', 40)
stu2 = Student('王大錘', 15)
stu1.study('Python程序設(shè)計')    # 駱昊正在學(xué)習(xí)Python程序設(shè)計.
stu2.play()                    # 王大錘正在玩游戲.

打印對象

上面我們通過__init__方法在創(chuàng)建對象時為對象綁定了屬性并賦予了初始值。在Python中,以兩個下劃線__(讀作“dunder”)開頭和結(jié)尾的方法通常都是有特殊用途和意義的方法,我們一般稱之為魔術(shù)方法或魔法方法。如果我們在打印對象的時候不希望看到對象的地址而是看到我們自定義的信息,可以通過在類中放置__repr__魔術(shù)方法來做到,該方法返回的字符串就是用print函數(shù)打印對象的時候會顯示的內(nèi)容,代碼如下所示。

class Student:
   """學(xué)生"""

   def __init__(self, name, age):
       """初始化方法"""
       self.name = name
       self.age = age

   def study(self, course_name):
       """學(xué)習(xí)"""
       print(f'{self.name}正在學(xué)習(xí){course_name}.')

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

   def __repr__(self):
       return f'{self.name}: {self.age}'stu1 = Student('駱昊', 40)
print(stu1)        # 駱昊: 40
students = [stu1, Student('王小錘', 16), Student('王大錘', 25)]
print(students)    # [駱昊: 40, 王小錘: 16, 王大錘: 25]

面向?qū)ο蟮闹е?/h4>

面向?qū)ο缶幊逃腥笾е褪俏覀冎敖o大家劃重點(diǎn)的時候圈出的三個詞:封裝、繼承和多態(tài)。后面兩個概念在下一節(jié)課中會詳細(xì)說明,這里我們先說一下什么是封裝。我自己對封裝的理解是:隱藏一切可以隱藏的實(shí)現(xiàn)細(xì)節(jié),只向外界暴露簡單的調(diào)用接口。我們在類中定義的對象方法其實(shí)就是一種封裝,這種封裝可以讓我們在創(chuàng)建對象之后,只需要給對象發(fā)送一個消息就可以執(zhí)行方法中的代碼,也就是說我們在只知道方法的名字和參數(shù)(方法的外部視圖),不知道方法內(nèi)部實(shí)現(xiàn)細(xì)節(jié)(方法的內(nèi)部視圖)的情況下就完成了對方法的使用。

舉一個例子,假如要控制一個機(jī)器人幫我倒杯水,如果不使用面向?qū)ο缶幊?,不做任何的封裝,那么就需要向這個機(jī)器人發(fā)出一系列的指令,如站起來、向左轉(zhuǎn)、向前走5步、拿起面前的水杯、向后轉(zhuǎn)、向前走10步、彎腰、放下水杯、按下出水按鈕、等待10秒、松開出水按鈕、拿起水杯、向右轉(zhuǎn)、向前走5步、放下水杯等,才能完成這個簡單的操作,想想都覺得麻煩。按照面向?qū)ο缶幊痰乃枷耄覀兛梢詫⒌顾牟僮鞣庋b到機(jī)器人的一個方法中,當(dāng)需要機(jī)器人幫我們倒水的時候,只需要向機(jī)器人對象發(fā)出倒水的消息就可以了,這樣做不是更好嗎?

在很多場景下,面向?qū)ο缶幊唐鋵?shí)就是一個三步走的問題。第一步定義類,第二步創(chuàng)建對象,第三步給對象發(fā)消息。當(dāng)然,有的時候我們是不需要第一步的,因?yàn)槲覀兿胗玫念惪赡芤呀?jīng)存在了。之前我們說過,Python內(nèi)置的list、set、dict其實(shí)都不是函數(shù)而是類,如果要創(chuàng)建列表、集合、字典對象,我們就不用自定義類了。當(dāng)然,有的類并不是Python標(biāo)準(zhǔn)庫中直接提供的,它可能來自于第三方的代碼,如何安裝和使用三方代碼在后續(xù)課程中會進(jìn)行討論。在某些特殊的場景中,我們會用到名為“內(nèi)置對象”的對象,所謂“內(nèi)置對象”就是說上面三步走的第一步和第二步都不需要了,因?yàn)轭愐呀?jīng)存在而且對象已然創(chuàng)建過了,直接向?qū)ο蟀l(fā)消息就可以了,這也就是我們常說的“開箱即用”。

經(jīng)典案例

例子1:定義一個類描述數(shù)字時鐘。

import time
# 定義數(shù)字時鐘類
class Clock(object):
   """數(shù)字時鐘"""

   def __init__(self, hour=0, minute=0, second=0):
       """初始化方法
       :param hour: 時
       :param minute: 分
       :param second: 秒
       """
       self.hour = hour
       self.min = minute
       self.sec = second

   def run(self):
       """走字"""
       self.sec += 1
       if self.sec == 60:
           self.sec = 0
           self.min += 1
           if self.min == 60:
               self.min = 0
               self.hour += 1
               if self.hour == 24:
                   self.hour = 0

   def show(self):
       """顯示時間"""
       return f'{self.hour:0>2d}:{self.min:0>2d}:{self.sec:0>2d}' # 創(chuàng)建時鐘對象
clock = Clock(23, 59, 58)
while True:
   # 給時鐘對象發(fā)消息讀取時間
   print(clock.show())
   # 休眠1秒鐘
   time.sleep(1)
   # 給時鐘對象發(fā)消息使其走字
   clock.run()

例子2:定義一個類描述平面上的點(diǎn),要求提供計算到另一個點(diǎn)距離的方法。

class Point(object):
   """屏面上的點(diǎn)"""

   def __init__(self, x=0, y=0):
       """初始化方法
       :param x: 橫坐標(biāo)
       :param y: 縱坐標(biāo)
       """
       self.x, self.y = x, y

   def distance_to(self, other):
       """計算與另一個點(diǎn)的距離
       :param other: 另一個點(diǎn)
       """
       dx = self.x - other.x
       dy = self.y - other.y
       return (dx * dx + dy * dy) ** 0.5

   def __str__(self):
       return f'({self.x}, {self.y})'p1 = Point(3, 5)
p2 = Point(6, 9)
print(p1, p2)
print(p1.distance_to(p2))

到此,相信大家對“Python面向?qū)ο缶幊淘趺蠢斫狻庇辛烁畹牧私猓环羴韺?shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向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