天天看點

python類和對象基礎詳解

類和對象

1 面向對象的思想

面向過程:面向處理理,更多的是從計算機⻆角度思考,注重計算每⼀一個步驟,程式更

像是⼀一本cpu操作⼿手冊。

面向對象:以日常生活的角度思考問題的解決,更接近人的思維方式,讓人以從

更高的層面考慮系統的建構

以你請朋友吃飯為例:

python類和對象基礎詳解

面向對象的優點:

面向對象更加适合做應用的開發

面向對象可以使你的代碼更加優雅和緊湊

面向對象開發效率更高

面向對象代碼複用度更高、可維護性更好

面向對象是⼀一種思維方式,它認為萬事萬物皆對象,程式是由多個對象協作共同完

成功能的,是以以後我們要從面向過程轉向面向對象。以⾯向對象的方式考慮程式

的建構。面向對象的核心是: 類和對象

問題->面向對象分析(OOA)->發現對象->類->用類實例化對象->對象協作完成功能

2. 類和對象

2.1 類和對象的概念

生活角度

類:具有相同特征和行為的對象的集合,是一個概念

對象:客觀存在的一切事物,是類的實例

類: 汽車 超級英雄 電腦 杯子

對象: 紅色的寶馬 美國隊長 桌上的mac pro 老王的⿊色杯⼦

程式角度

類:使用者自定義的資料類型,是模闆,不占⽤用記憶體

對象:由類定義的變量,占用記憶體

類:

成員屬性(成員變量) 描述對象的靜态特征,諸如,名字、身高體重

成員方法 描述對象的動态特征,例如:吃飯、睡覺、打⾖豆

2.2 類的定義

#文法:

class 類名:

類體

注意:

類定義必須以關鍵字class開頭

類名要符合辨別符的規範

類名⼀一般用大駝峰風格: 每個單詞首字⺟母大寫,其它⼩小寫 ,例如MyBook

YouMoney

類體必須縮進

在python3中類預設繼承object,是以可以這樣寫 class Dog:,它等價于class

Dog(object):

一個檔案里隻放⼀一個類

2.3 成員方法

成員方法其實就是函數,作用域在類内,成員方法的第一個參數必須是self,self

代表目前對象,也就是調⽤用這個方法的對象,這個參數由系統傳遞。

class Dog(object):
def bark(self): #成員方法,第一個參數必須是self,代表目前調用對象
print('我是小可愛--丁丁')
dingding = Dog() #實例化一個對象
#調用方法,不需要傳參數,self是系統傳遞的
#調用形式: 對象.方法([實參])
dingding.bark() #等價調用形式:bark(dingding)
           

注意:

self參數在調用的時候不必傳值,由系統傳值

self隻能在實例方法中使用

方法和函數的差別:

方法作用域屬于類,是以即便和普通函數重名,也不會被覆寫

方法的第一個參數必須是self,但函數不要求

方法必須通過對象調用,而函數不需要

方法的第一個參數self其實可以使任何合法辨別符,不過一般約定俗成都是self

方法的連貫調用

class Dog:
def bark(self):
print("汪汪汪")
return self #傳回self
def eat(self):
print("愛啃大骨頭")
return self
dog = Dog()
dog.eat().bark() #方法的連貫調用,方法要傳回self
           

2.4 對象的建立

對象的建立過程也稱之為對象的實例化過程,也就是定義了了一個類型的變量或者

稱之為實例(instance)的過程

#文法: 對象 = 類名([實參])
dingding = Dog() #實例化一個對象
print(dingding) #<__main__.Dog object at 0x00000000023F40B8>
print(type(dingding)) #<class '__main__.Dog'>
#檢視對象的類名
print(dingding.__class__)
           

2.5 成員屬性

成員屬性描述的是對象的靜态特征,比如說狗名字、品種等,其實就是一個變量,

作用域屬于對象,不會和類外的全局變量沖突。python中成員屬性可以在構造函

數中添加。成員屬性屬于對象,每個對象的成員屬性的值都不同

在構造函數中添加的屬性屬于所有對象(重點)

#添加屬性文法:
對象.成員屬性 = 值
#引⽤⽅式:對象.成員屬性
class Dog(object):
def __init__(self,name,kind,age):
self.name = name
self.kind = kind
self.age = age
def bark(tmp):
print('我是小可愛--丁丁')
dingding = Dog('丁丁','泰迪',3)
print('我是可愛的%s⽝犬,%s,我今年%d歲了了' % (dingding.kind,
dingding.name, dingding.age))
#檢視執行個體屬性
print(dingding.__dict__) #__dict__屬性可以用來檢視實例屬性
print(dir(dingding)) #檢視Dog的屬性,包括執行個體屬性
           

3.封裝

隐藏對象的屬性和實作細節,僅對外公開接口,控制在程式中屬性的讀取和修改的

通路級别。

#文法: 對象 = 類名([實參])

dingding = Dog() #執行個體例化⼀一個對象

print(dingding) #<main.Dog object at 0x00000000023F40B8>

print(type(dingding)) #<class ‘main.Dog’>

#檢視對象的類名

print(dingding.class)

#添加屬性文法:

對象.成員屬性 = 值

#引用方式:對象.成員屬性

class Dog(object):

def init(self,name,kind,age):

self.name = name

self.kind = kind

self.age = age

def bark(tmp):

print(‘我是小可愛–丁丁’)

dingding = Dog(‘丁丁’,‘泰迪’,3)

print(‘我是可愛的%s⽝犬,%s,我今年%d歲了了’ % (dingding.kind,

dingding.name, dingding.age))

#檢視執行個體屬性

print(dingding.dict) #__dict__屬性可以用來檢視實例屬性

print(dir(dingding)) #檢視Dog的屬性,包括執行個體屬性

類本身就是⼀一種封裝,通過類可以将資料(屬性)和行行為(方法)相結合,形成一

個有機的整體,也就是将資料與對資料的操作有機的結合。封裝的目的是增強安全

性和簡化程式設計,使用者不必了了解具體的實作細節,而隻是要通過外部接口,以特定

的通路權限來使用類的成員。成員私有化是實作封裝的手段。所有的成員預設是公

有。

3.1 屬性私有化

如果想讓類的内部屬性不被外界直接通路,可以在這個屬性的前面加兩個下劃線__

,在Python中,如果一個屬性的前面出現 __,就表示這個屬性隻能在目前類的方法中

被直接通路,不能通過對象直接通路,這個變量量就被稱為私有變量

class Dog:
def __init__(self,name,gender,age):
self.name = name
self._gender = gender #'保護'變量
self.__age = age #私有變量
#定義一個公開的方法,間接通路私有變量
def get_age(self):
return self.__age
#定義⼀一個公開方法,間接設定私有變量
def set_age(self,age):
self.__age = age
ding = Dog('丁丁','公',5)
print(ding.name)
# print(ding.__age) #AttributeError: 'Dog' object has no attribute
'__age'
print(ding.get_age()) #5 擷取私有屬性的值
ding.set_age(10) #設定私有屬性的值
print(ding.get_age()) #10
print(ding._gender)
#可以通過 _Dog__age通路私有變量,但不不建議
print(ding._Dog__age)
【⾯面試題】
常見的在變量的前後加下劃線的問題:
單下劃線:_age ----->受保護的 可以通路,當約定俗稱,當你看到一個下劃線開頭
的成員時不應該使⽤用它
雙下劃線:__age ------>私有的
兩邊都雙下劃線:__age__ ------->系統内置變量
           

3.2 屬性裝飾器器

對于私有屬性的通路,使用公開方法間接通路的方法太麻煩,python提供了一種

便捷文法,屬性裝飾器,通過屬性裝飾器,可以很方便的對私有屬性進通路,屬性

修飾器可以把方法屬性化。

class Dog:
def __init__(self,name,gender,age):
self.name = name
self._gender = gender
self.__age = age
@property
def age(self):
return self.__age
@age.setter
def age(self,age):
self.__age =age
ding = Dog('丁丁','公',5)
print(ding.name)
print(ding.age)
ding.age =10
print(ding.age)
print(ding._gender)
           

3.3 成員方法私有化

如果一個方法的名字前面加__,聲明該方法為私有方法,隻能在目前類中被調用,

在外界不能通過對象直接調用,這就是私有方法

class Dog:
def __init__(self,name,age):
self.name = name
self.age = age
def __pee(self):
print('這是我的地頭')
dog = Dog('dingding',5)
#dog.__pee() #AttributeError: 'Dog' object has no attribute '__pee'
           

4 構造和析構

4.1 構造方法

目的:構造方法用于初始化對象(不建立對象),可以在構造方法中添加成員屬

時機:實例化對象的時候自動調用

參數:第一個參數必須是self,其它參數根據需要自己定義

傳回值:不傳回值,或者說傳回None,不應該傳回任何其他值

文法:
def __init__(self,arg1,arg2....):
函數體
#參數:arg1,agr2...根據需要自己定義
#如果自己不定義構⽅方法,系統自動生成一個構造函數
def __init__(self):
     pass
           

注意:

如果沒有定義構造方法,系統會生成一個無參構造方法,如果自己定義了構造

方法,則系統不會自動生成

class 類名:
def __init__(self):
pass

``
一個類隻能有一個構造方法,如果定義多個,後面的會覆寫前面的
構造函數由系統在實例化對象時自動調用,不要自己調用

           

class Dog(object):

def init(self,name,kind,age):

self.name = name #定義對象屬性,這個類所有的對象都具有該屬性

self.kind = kind #成員屬性必須通過self.引⽤用,否則是普通變量

self.age = age

def bark(tmp):

print(‘我是小可愛–丁丁’)

dingding = Dog(‘丁丁’,‘泰迪’,3)

print(‘我是可愛的%s⽝犬,%s,我今年%d歲了了’ % (dingding.kind,

dingding.name, dingding.age))

4.2 析構方法

目的:對象銷毀時,釋放資源
時機:對象銷毀時由系統自動調用
參數:除了self外,沒其他參數
傳回值:不傳回值,或者說傳回None。
文法:

           

def del(self):

#to do

class Dog(object):

#構造

def init(self,name,kind,age):

self.name = name

self.kind = kind

self.age = age

#析構

def del(self):

print(‘拜拜了,二十年後又是一條好漢’)

def bark(tmp):

print(‘我是小可愛–丁丁’)

dingding = Dog(‘丁丁’,‘泰迪’,3)

print(‘我是可愛的%s犬,%s,我今年%d歲了’ % (dingding.kind,

dingding.name, dingding.age))

del dingding #銷毀對象,自動調用析構方法

#在函數中對象,當函數結束運行時,自動析構

def test():

td = Dog(‘當當’,‘泰迪’,3)

4.3 __str__ __str__

目的:将對象轉化為字元串
時機:凡是涉及對象向字元串轉換的都會調用(print,str)
參數:self
傳回值:字元串
__repr__ 作用同 __str__ 不過是給解釋器看的

           

class Animal:

def init(self,name,age):

self.name = name

self.__age =age

def str(self):

return “name : {} age : {}”.format(self.name,self.__age)

def repr(self):

return self.str()

a1 = Animal(‘zhu’,3)

print(a1)

print('我是⼀一頭可愛的 ’ + str(a1)