摘要:類對(duì)象被創(chuàng)建時(shí)存在于類命名空間內(nèi)的所有名稱都是有效的屬性名稱。類的實(shí)例化,是使用函數(shù)表示法,可以把類對(duì)象看做是會(huì)返回一個(gè)新的類實(shí)例的函數(shù)。這就是可變對(duì)象作為類變量時(shí)的特性。類變量是所有類的實(shí)例共享的屬性和方法,實(shí)例變量是每個(gè)實(shí)例獨(dú)有的數(shù)據(jù)。
Python是面向?qū)ο蟮母呒?jí)編程語(yǔ)言,在Python里面“一切都是對(duì)象”:數(shù)字、字符串、元組、列表、字典、集合等內(nèi)置數(shù)據(jù)類型,以及函數(shù)、方法、類、模塊都是對(duì)象。
語(yǔ)言本身提供了上述的基本對(duì)象,但在實(shí)際編程中,我們要?jiǎng)?chuàng)造各種各樣的對(duì)象,Python就為我們提供了創(chuàng)造我們自己的對(duì)象的方法:類。
類(Class),就是組合數(shù)據(jù)和功能的方法,它讓我們創(chuàng)建一個(gè)新類型的對(duì)象,并可以創(chuàng)建該類型的新實(shí)例。類組合的數(shù)據(jù),就是保存自己狀態(tài)的屬性,而它組合的功能(函數(shù))就是改變自己狀態(tài)的(定義在類中的)方法。類內(nèi)部定義的函數(shù),稱為類的方法。
Python中的類和其它語(yǔ)言(比如C++)有很多相似的特征但也有些區(qū)別。如果你已了解其它語(yǔ)言的類的概念,可以在學(xué)習(xí)Python類時(shí)做一定的對(duì)比進(jìn)行學(xué)習(xí);如果你沒有學(xué)過(guò)其它語(yǔ)言也不要緊,學(xué)過(guò)之后你會(huì)發(fā)現(xiàn),類的概念是如此簡(jiǎn)單。
類的定義類的定義是通過(guò)關(guān)鍵字class實(shí)現(xiàn)的,下面是最簡(jiǎn)單的類的定義的樣子:
class ClassName: 語(yǔ)句1 ... 語(yǔ)句n
是不是這個(gè)形式跟函數(shù)的定義(def 語(yǔ)句)很像。因?yàn)轭愂菙?shù)據(jù)和功能的組合,所以語(yǔ)句1可能是內(nèi)部變量(數(shù)據(jù))的定義和賦值語(yǔ)句,也可能是內(nèi)部方法(函數(shù))的定義語(yǔ)句。類內(nèi)部的函數(shù)定義通常具有一種特別形式的參數(shù)列表,這是方法調(diào)用的約定規(guī)范里面指明的。這個(gè)特別形式就是第一個(gè)參數(shù)必須是self,后面將詳細(xì)介紹。
進(jìn)入類定義時(shí),就會(huì)創(chuàng)建一個(gè)新的命名空間,并把它用作局部作用域。因此,所有對(duì)局部變量的賦值都是在這個(gè)新命名空間內(nèi)進(jìn)行的。特別的,函數(shù)定義會(huì)綁定到這個(gè)局部作用域里的新函數(shù)名稱。
正常離開(從結(jié)尾出)類定義時(shí),就會(huì)創(chuàng)建一個(gè)類對(duì)象。它基本上是一個(gè)包圍在類定義所創(chuàng)建的命名空間內(nèi)容周圍的包裝器。元素的(在進(jìn)入類定義之前起作用的)局部作用域?qū)⒅匦律В悓?duì)象將在這里被綁定到類定義頭給出的類名稱(在上面的例子中就是ClassName)。
類對(duì)象類對(duì)象(比如上面例子的ClassName)支持兩種操作:屬性引用和實(shí)例化。
屬性引用的語(yǔ)法跟Python中所有屬性引用的方法一樣:obj.name。類對(duì)象被創(chuàng)建時(shí)存在于類命名空間內(nèi)的所有名稱都是有效的屬性名稱。下面是一個(gè)包含數(shù)據(jù)和方法的簡(jiǎn)單的類定義:
class YuanRenXue: """A demo of class""" name = "猿人學(xué)" def say_hi(self): print("Hello world!")
對(duì)這個(gè)類的有效的屬性引用就是:YuanRenXue.name和YuanRenXue.say_hi,它們分別返回一個(gè)字符串和一個(gè)函數(shù)對(duì)象。
類屬性也可以被賦值,因此可以通過(guò)賦值來(lái)更改Yuanrenxue.name的值。
類的__doc__也是一個(gè)有效的屬性,對(duì)他的引用會(huì)返回所屬類的文檔字符串:"A demo of class"。
類的實(shí)例化,是使用函數(shù)表示法,可以把類對(duì)象看做是會(huì)返回一個(gè)新的類實(shí)例的函數(shù)。比如上面類對(duì)象的實(shí)例化就是:
yrx = YuanRenXue()
這就創(chuàng)建了一個(gè)類的新實(shí)例并將詞對(duì)象分配給局部變量yrx。
實(shí)例化操作可以看成是“調(diào)用”類對(duì)象。但我們?cè)趧?chuàng)建類實(shí)例時(shí)都想要做些初始化操作,為此類定義時(shí)可以定義一個(gè)名為__init__()的特殊方法。它是類實(shí)例化的初始化方法,跟C++語(yǔ)言中 的構(gòu)造函數(shù)類似。
def __init__(self): self.data = None
定義了__init__()方法后,類的實(shí)例化操作會(huì)自動(dòng)調(diào)用該方法。
當(dāng)然,__init__()方法也可以有額外(除self之外)的參數(shù)以實(shí)現(xiàn)更靈活的初始化操作。類對(duì)象實(shí)例化時(shí)(“調(diào)用”類對(duì)象)傳遞的參數(shù)會(huì)被傳遞給__init__()方法。例如:
In [27]: class Point: ...: def __init__(self, x, y): ...: self.x = x ...: self.y = y ...: In [28]: p = Point(7, 8) In [29]: p.x, p.y Out[29]: (7, 8)實(shí)例對(duì)象
類實(shí)例化后我們就得到了實(shí)例對(duì)象,對(duì)它的操作就是:屬性引用。這里的有效屬性名稱是數(shù)據(jù)屬性和方法。
o
數(shù)據(jù)屬性,對(duì)應(yīng)C++中的“數(shù)據(jù)成員”,不懂C++也沒關(guān)系,“數(shù)據(jù)成員”這名字字面上就很形象。數(shù)據(jù)屬性不需要聲明,它像普通變量一樣,在第一次賦值時(shí)產(chǎn)生。比如p是聲明創(chuàng)建的Point的實(shí)例,則以下代碼會(huì)打印數(shù)值8:
p.times = 1 while p.times < 5: p.times = p.times * 2 print(p.times) del p.times
雖然p.times并沒有在類定義時(shí)聲明(數(shù)據(jù)屬性不需要聲明),但在任何時(shí)候,我們可以給實(shí)例賦值一個(gè)新的數(shù)據(jù)屬性(這里是p.times),并可以隨時(shí)刪除實(shí)例的數(shù)據(jù)屬性(del p.times)。
方法,是“從屬于”對(duì)象的函數(shù)。方法這個(gè)術(shù)語(yǔ)并不是類實(shí)例獨(dú)有的,其它對(duì)象也可以有方法。比如,列表對(duì)象有append(), insert(), sort()等方法。
實(shí)例對(duì)象的有效方法名稱依賴于其所屬的類。 根據(jù)定義,一個(gè)類中所有是函數(shù)對(duì)象的屬性都是定義了其實(shí)例的相應(yīng)方法。 因此在我們的示例中,yrx.say_hi是有效的方法引用,因?yàn)?b>YuanRenXue.say_hi是一個(gè)函數(shù);而yrx.name不是方法,因?yàn)?b>YuanRenXue.name不是一個(gè)函數(shù)。這里要注意,yrx.say_hi與YuanRenXue.say_hi并不是一回事,它是一個(gè)方法對(duì)象,不是函數(shù)對(duì)象,通俗講,前者是實(shí)例的方法,后者是類的函數(shù)。
方法對(duì)象通常,調(diào)用方法的方法是:
yrx.say_hi()
在YuanRenXue 示例中,這將打印字符串Hello World。但是,調(diào)用一個(gè)方法也可以換另外一種形式,把它賦值給一個(gè)變量后再調(diào)用。例如:
yrx_say = yrx.say_hi yrx_say()
當(dāng)我們調(diào)用yrx.say_hi()時(shí)并沒有帶參數(shù),但say_hi()函數(shù)定義時(shí)指定了一個(gè)參數(shù)。實(shí)際上,方法的特殊之處就是實(shí)例對(duì)象會(huì)作為函數(shù)的第一個(gè)參數(shù)(self)被傳入。調(diào)用yrx.say_hi()其實(shí)就相當(dāng)于YuanRenXue.say_hi(yrx)。
類變量和實(shí)例變量一般來(lái)說(shuō),類變量用于類的所有實(shí)例共享的屬性和方法,而實(shí)例變量用于每個(gè)實(shí)例的唯一數(shù)據(jù):
In [33]: class Tiger: ...: kind = "feline" ...: def __init__(self, name) File "", line 3 def __init__(self, name) ^ SyntaxError: invalid syntax In [34]: class Tiger: ...: kind = "feline" ...: def __init__(self, name): ...: self.name = name ...: In [35]: a = Tiger("Kiro") In [36]: b = Tiger("Zim") In [37]: a.kind Out[37]: "feline" In [38]: b.kind Out[38]: "feline" In [39]: a.name Out[39]: "Kiro" In [40]: b.name Out[40]: "Zim"
如果類變量是列表或字典這種可變對(duì)象會(huì)導(dǎo)致令人驚訝的結(jié)果,我們要明白這種結(jié)果,從而可以在需要的時(shí)候利用這個(gè)特性,也可以在不需要的時(shí)候避免這個(gè)特性。是取是舍,全在于我們?cè)诰幊虝r(shí)要定義的類的作用。下面,我們看看這個(gè)“令人驚訝”的結(jié)果是什么:
In [42]: class Tiger: ...: places = [] ...: def __init__(self, name): ...: self.name = name ...: def go_place(self, place): ...: self.places.append(place) ...: In [43]: a = Tiger("Kiro") In [44]: b = Tiger("Zim") In [45]: a.go_place("北京") In [46]: b.go_place("上海") In [47]: a.places Out[47]: ["北京", "上海"]
這里,把places定義為類變量,它就記錄了所有老虎(Kiro和Zim,以及后面實(shí)例化出來(lái)個(gè)各個(gè)老虎)去過(guò)的地方,所以,盡管a只去過(guò)北京,但是當(dāng)我們通過(guò)a查看places,也看到了上海。這就是可變對(duì)象作為類變量時(shí)的特性。如果我們就是想記錄所有老虎實(shí)例對(duì)象去過(guò)的地方,這樣的用法就是恰到好處。
如果,我們只想記錄每一只老虎去過(guò)的地方,那么就應(yīng)該把places定義為實(shí)例變量,也就是在__init__()中進(jìn)行初始化賦值。
需要注意的地方(1)數(shù)據(jù)屬性會(huì)覆蓋掉具有相同名稱的方法屬性,因此寫程序時(shí)為了避免名稱沖突,可以使用某些規(guī)范來(lái)減少?zèng)_突,比如:
方法名稱使用大寫字母;
屬性名稱加上特殊的前綴(或加一個(gè)下劃線);
用動(dòng)詞來(lái)命名方法,用名詞來(lái)命名數(shù)據(jù)屬性。
這些規(guī)范稱為“代碼規(guī)范”,一個(gè)好的代碼規(guī)范讓代碼可讀性更高,也更利用團(tuán)隊(duì)合作。有名的Python代碼規(guī)范有“PEP 8”,也有Google的Python風(fēng)格規(guī)范。
(2)數(shù)據(jù)屬性可以被方法以及對(duì)象之外的任何用戶(使用該類的人)所引用。也就是說(shuō),Python不行C++類那樣有私有成員,Python沒有任何對(duì)象能強(qiáng)制隱藏?cái)?shù)據(jù)。
(3)類對(duì)象的用戶應(yīng)該謹(jǐn)慎使用數(shù)據(jù)屬性,直接操作數(shù)據(jù)屬性可能破壞其中的固定變量。但我們可以想一個(gè)實(shí)例對(duì)象添加我們自己的數(shù)據(jù)屬性,但要避免與原有的名稱沖突。
(4)方法的第一個(gè)參數(shù)常常被命名為self,代表實(shí)例對(duì)象。但這只是大家普通認(rèn)同的一個(gè)約定。你可以用任何單詞來(lái)替代它,但是你的代碼讓氣體程序員讀起來(lái)就很費(fèi)勁,也會(huì)對(duì)VS Code這樣的編輯器造成困惑。
總結(jié)類是組合數(shù)據(jù)和功能的方法,其中:
數(shù)據(jù),是類的屬性,從屬于類的各種數(shù)據(jù)對(duì)象;
功能,是類的方法,定義在類內(nèi)部的各種函數(shù)。
定義好一個(gè)類我們就創(chuàng)建了一個(gè)類對(duì)象,類對(duì)象支持兩種操作:屬性引用和實(shí)例化。
類對(duì)象實(shí)例化后就得到了實(shí)例對(duì)象,它有兩種屬性名稱:數(shù)據(jù)屬性和方法。
類變量是所有類的實(shí)例共享的屬性和方法,實(shí)例變量是每個(gè)實(shí)例獨(dú)有的數(shù)據(jù)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/43844.html
摘要:類的繼承,說(shuō)明了不同類直接的關(guān)系,派生類復(fù)用了基類的代碼同時(shí)也繼承了基類的屬性和方法。派生類的實(shí)例化會(huì)創(chuàng)建該類的一個(gè)新實(shí)例。派生類既可以單獨(dú)繼承一個(gè)基類,也可以多重繼承多個(gè)基類。 面向?qū)ο笳Z(yǔ)言的一個(gè)特性就是類的繼承。繼承的關(guān)系跟人類繁衍的關(guān)系相似,被繼承的類稱為基類(也叫做父類),繼承而得的類叫派生類(也叫子類),這種關(guān)系就像人類的父子關(guān)系。 showImg(https://segme...
摘要:語(yǔ)句就是幫助我們拋出知道異常的,比如的使用很簡(jiǎn)單,它的語(yǔ)法如下如果它后面不帶表達(dá)式參數(shù),它會(huì)重新引發(fā)當(dāng)前作用域內(nèi)最后一個(gè)激活的異常。,用于異常的串聯(lián)。自定義的異常類的名稱通常以錯(cuò)誤結(jié)尾,類似與內(nèi)置標(biāo)準(zhǔn)異常的命名。 前面我們講到的Python編程過(guò)程中,在可能出現(xiàn)異常的地方使用嘗試語(yǔ)句,來(lái)正確的處理一些異常,可以保證程序不中斷繼續(xù)運(yùn)行。 showImg(https://segmentfa...
摘要:以下這些項(xiàng)目,你拿來(lái)學(xué)習(xí)學(xué)習(xí)練練手。當(dāng)你每個(gè)步驟都能做到很優(yōu)秀的時(shí)候,你應(yīng)該考慮如何組合這四個(gè)步驟,使你的爬蟲達(dá)到效率最高,也就是所謂的爬蟲策略問(wèn)題,爬蟲策略學(xué)習(xí)不是一朝一夕的事情,建議多看看一些比較優(yōu)秀的爬蟲的設(shè)計(jì)方案,比如說(shuō)。 (一)如何學(xué)習(xí)Python 學(xué)習(xí)Python大致可以分為以下幾個(gè)階段: 1.剛上手的時(shí)候肯定是先過(guò)一遍Python最基本的知識(shí),比如說(shuō):變量、數(shù)據(jù)結(jié)構(gòu)、語(yǔ)法...
摘要:學(xué)習(xí)筆記七數(shù)學(xué)形態(tài)學(xué)關(guān)注的是圖像中的形狀,它提供了一些方法用于檢測(cè)形狀和改變形狀。學(xué)習(xí)筆記十一尺度不變特征變換,簡(jiǎn)稱是圖像局部特征提取的現(xiàn)代方法基于區(qū)域圖像塊的分析。本文的目的是簡(jiǎn)明扼要地說(shuō)明的編碼機(jī)制,并給出一些建議。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 開始之前,我們先來(lái)看這樣一個(gè)提問(wèn): pyth...
閱讀 2024·2021-09-30 09:47
閱讀 703·2021-09-22 15:43
閱讀 1981·2019-08-30 15:52
閱讀 2431·2019-08-30 15:52
閱讀 2540·2019-08-30 15:44
閱讀 903·2019-08-30 11:10
閱讀 3372·2019-08-29 16:21
閱讀 3296·2019-08-29 12:19