06-Python類和對象

Python類和對象

Python類和對象思維導圖

1、面向對象編程介紹

面向對象編程——Object Oriented Programming,簡稱OOP,是一種程序設計思想。OOP把對象作爲程序的基本單元,一個對象包含了數據和操作數據的函數。面向對象是一種對現實世界理解和抽象的方法

“面向過程”(Procedure Oriented)是一種以過程爲中心的編程思想。“面向過程”也可稱之爲“面向記錄”編程思想,他們不支持豐富的“面向對象”特性(比如繼承、多態、封裝),並且它們不允許混合持久化狀態和域邏輯。

就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。
面向過程是一件事“該怎麼做“,面向對象是一件事“該讓誰來做”,然後那個“誰”就是對象,他要怎麼做是他自己的事,反正最後一羣對象合力能把事做好就行了

面向對象三個特性:

  • 繼承
  • 封裝
  • 多態

2、類和對象

面向對象編程的2個非常重要的概念:類和對象

    • 人以類聚 物以羣分。 具有相似內部狀態和運動規律的實體的集合(或統稱爲抽象)。 具有相同屬性和行爲事物的統稱
    • 類是抽象的,在使用的時候通常會找到這個類的一個具體的存在,使用這個具體的存在
    1. 對象
    • 某一個具體事物的存在 ,在現實世界中可以是看得見摸得着的。 可以是直接使用的
    1. 類和對象之間的關係
    • 關係

類的構成

  • 類(Class) 由3個部分構成

    • 類的名稱:類名
    • 類的屬性:一組數據
    • 類的方法:允許對進行操作的方法 (行爲)

3、定義類與創建對象

1、類的定義

  • 語法:

    • class 類名: 方法列表
  • 說明:

    • 1、定義類時有2種:新式類和經典類,上面的Car爲經典類,如果是Car(object)則爲新式類
    • 2、類名的命名規則按照"大駝峯"

2、創建對象

  • 語法:

    • 對象名 = 類名()

4、self

1.、理解self

  • 看如下示例:

定義一個類

class Animal:

方法

def init(self, name):
self.name = name
def printName(self):
print(‘名字爲:%s’%self.name)

定義一個函數

def myPrint(animal):
animal.printName()
dog1 = Animal(‘西西’)

  • 總結:

    • 1、所謂的self,可以理解爲自己
    • 2、可以把self當做C++中類裏面的this指針一樣理解,就是對象自身的意思
    • 3、某個對象調用其方法時,python解釋器會把這個對象作爲第一個參數傳遞給self,所以開發者只需要傳遞後面的參數即可

2、init()方法

  • <1>使用方式

    • def 類名:
      #初始化函數,用來完成一些默認的設定
      def__init__():pass
  • <2>init()方法的調用

    • 定義汽車類

classCar:
def__init__(self):
self.wheelNum = 4
self.color = ‘藍色’
defmove(self):
print(‘車在跑,目標:夏威夷’)

創建對象

BMW = Car()
print(‘車的顏色爲:%s’%BMW.color)
print(‘車輪胎數量爲:%d’%BMW.wheelNum)

  • 總結1:

    • 當創建Car對象後,在沒有調用__init__()方法的前提下,BMW就默認擁有了2個屬性wheelNum和color,原因是__init__()方法是在創建對象後,就立刻被默認調用了
  • 總結2:

    • 1、init()方法,在創建一個對象時默認被調用,不需要手動調用
    • 2、init(self)中,默認有1個參數名字爲self,如果在創建對象時傳遞了2個實參,那麼__init__(self)中出了self作爲第一個形參外還需要2個形參,例如__init__(self,x,y)
    • 3、init(self)中的self參數,不需要開發者傳遞,python解釋器會自動把當前的對象引用傳遞進去

3、__new__方法

  • classA(object):
    def__init__(self):
    print(“這是 init 方法”)
    def__new__(cls):
    print(“這是 new 方法”)
    return object.new(cls)
    A()

  • 總結:

    • 1、__new__至少要有一個參數cls,代表要實例化的類,此參數在實例化時由Python解釋器自動提供
    • 2、__new__必須要有返回值,返回實例化出來的實例,這點在自己實現__new__時要特別注意,可以return父類__new__出來的實例,或者直接是object的__new__出來的實例
    • 3、__init__有一個參數self,就是這個__new__返回的實例,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要返回值
    • 4、我們可以將類比作製造商,__new__方法就是前期的原材料購買環節,__init__方法就是在有原材料的基礎上,加工,初始化商品環節

4、del()方法

  • 實例:

    • import time
      classAnimal(object):

初始化方法

創建完對象後會自動被調用

def__init__(self, name):
print(’__init__方法被調用’)
self.__name = name

析構方法

當對象被刪除時,會自動被調用

def__del__(self):
print("__del__方法被調用")
print("%s對象馬上被幹掉了…"%self.__name)

創建對象

dog = Animal(“哈皮狗”)

刪除對象

del dog
cat = Animal(“波斯貓”) cat2 = cat
cat3 = cat
print("—馬上 刪除cat對象")
del cat
print("—馬上 刪除cat2對象")
del cat2
print("—馬上 刪除cat3對象")
del cat3
print(“程序2秒鐘後結束”)
time.sleep(2)

  • 創建對象後,python解釋器默認調用__init__()方法;

  • 當刪除一個對象時,python解釋器也會默認調用一個方法,這個方法爲__del__()方法

  • 當內存中構建一個對象數據的時候回調__init__()方法,

  • 當內存中銷燬(釋放)一個對象時回調__del__()方法

  • 總結:

    • 1、當有1個變量保存了對象的引用時,此對象的引用計數就會加1
    • 2、當使用del刪除變量指向的對象時,如果對象的引用計數不是1,比如3,那麼此時只會讓這個引用計數減1,即變爲2,當再次調用del時,變爲1,如果再調用1次del,此時會真的把對象進行刪除

5、定義__str__()方法

  • 實例:

    • classCar:
      def__init__(self, newWheelNum, newColor):
      self.wheelNum = newWheelNum
      self.color = newColor
      def__str__(self):
      msg = “嘿,我的顏色是” + self.color + “我有” + str(self.wheelNum) + “個輪胎…”
      return msg
      def move(self):
      print(‘車在跑,目標:夏威夷’)
      BMW = Car(4, “白色”)
      print(BMW)
  • 總結

    • 1、在python中方法名如果是__xxxx__()的,那麼就有特殊的功能,因此叫做“魔法”方法
    • 2、當使用print輸出對象的時候,只要自己定義了__str__(self)方法,那麼就會打印從在這個方法中return的數據

特殊方法:

  • 特殊方法名 默認的參數 功能描述
  • init() self 已經創建了對象,初始化對象回調方法
  • str() self 和toString
  • del() self 對象回收時候回調
  • new() cls 對象創建的回調方法

總結:

  • 1、__init__完成對象的初始化操作,在對象被創建完成後之後,立刻被調用執行,隱式調用,創建對象時的參數要跟init方法的參數保持一致
  • 2、__new__時構造方法,創建對象時,首先調用的是new方法,new方法必須要有返回值,參數必須跟創建對象傳遞的參數一致
  • 3、無論什麼情況,iinit和new方法的參數都要保持一致
  • 4、先new再init、del

5、保護對象的屬性

如果有一個對象,當需要對其進行修改屬性時,有2種方法

  • 對象名.屬性名 = 數據 ---->直接修改
  • 對象名.方法名() ---->間接修改

爲了更好的保存屬性安全,即不能隨意修改,一般的處理方式爲

  • 將屬性定義爲私有屬性
  • 添加一個可以調用的方法,供調用

實例:

  • classPeople(object):
    def__init__(self, name):
    self.__name = name
    defgetName(self):
    return self.__name
    defsetName(self, newName):
    if len(newName) >= 5:
    self.__name = newName
    else:
    print(“error:名字長度需要大於或者等於5”)
    xiaoming = People(“bin”)
    print(xiaoming.__name)

總結:

  • 1、Python中沒有像C++中public和private這些關鍵字來區別公有屬性和私有屬性
  • 2、它是以屬性命名方式來區分,如果在屬性名前面加了2個下劃線’__’,則表明該屬性是私有屬性,否則爲公有屬性(方法也是一樣,方法名前面加了2個下劃線的話表示該方法是私有的,否則爲公有的)

6、繼承

1. 繼承的概念

  • 在現實生活中,繼承一般指的是子女繼承父輩的財產,在程序中,繼承描述的是事物之間的所屬關係,例如貓和狗都屬於動物,程序中便可以描述爲貓和狗繼承自動物;同理,波斯貓和巴釐貓都繼承自貓,而沙皮狗和斑點狗都繼承足夠,如下如圖所示

2. 繼承示例

  • 定義一個父類,如下:

class Cat(object):
def init(self, name, color=“白色”):
self.name = name
self.color = color
def run(self):
print("%s–在跑"%self.name)

定義一個子類,繼承Cat類,如下:

classBosi(Cat):
def setNewName(self, newName):
self.name = newName
def eat(self):
print("%s–在喫"%self.name)
bs = Bosi(“印度貓”)
print(‘bs的名字爲:%s’%bs.name)
print(‘bs的顏色爲:%s’%bs.color)
bs.eat()
bs.setNewName(‘波斯’)
bs.run()

  • 說明:

    • 雖然子類沒有定義__init__方法,但是父類有,所以在子類繼承父類的時候這個方法就被繼承了,所以只要創建Bosi的對象,就默認執行了那個繼承過來的__init__方法
  • 總結:

    • 1、子類在繼承的時候,在定義類時,小括號()中爲父類的名字
    • 2、父類的屬性、方法,會被繼承給子類
  • 實例:

    • class Animal(object):
      def init(self, name=‘動物’, color=‘白色’):
      self.__name = name
      self.color = color
      def __test(self):
      print(self.__name)
      print(self.color)
      def test(self):
      print(self.__name)
      print(self.color)
      class Dog(Animal):
      def dogTest1(self):
      #print(self.__name)
      #不能訪問到父類的私有屬性
      print(self.color)
      def dogTest2(self):
      #self.__test()
      #不能訪問父類中的私有方法
      self.test()
      A = Animal()
      #print(A.__name)
      #程序出現異常,不能訪問私有屬性
      print(A.color)
      #A.__test()
      #程序出現異常,不能訪問私有方法
      A.test()
      print("------分割線-----")
      D = Dog(name = “小花狗”, color = “黃色”)
      D.dogTest1()
      D.dogTest2()

3. 注意點:

  • 1、私有的屬性,不能通過對象直接訪問,但是可以通過方法訪問
  • 2、私有的方法,不能通過對象直接訪問
  • 3、私有的屬性、方法,不會被子類繼承,也不能被訪問
  • 4、一般情況下,私有的屬性、方法都是不對外公佈的,往往用來做內部的事情,起到安全的作用

7、多繼承

1. 多繼承:

  • 實例:

    • 定義一個父類

classA:
def printA(self):
print(’----A----’)

定義一個父類

classB:
def printB(self):
print(’----B----’)

定義一個子類,繼承自A、B

class C(A,B):
def printC(self):
print(’----C----’)
obj_C = C()
obj_C.printA()
obj_C.printB()
- 說明:

	- 1、python中是可以多繼承的
	- 2、父類中的方法、屬性,子類會繼承

2、重寫:

  • <1>重寫父類方法

    • 所謂重寫,就是子類中,有一個和父類相同名字的方法,在子類中的方法會覆蓋掉父類中同名的方法
    • #coding=utf-8
      class Cat(object):
      def sayHello(self):
      print(“halou-----1”)
      class Bosi(Cat):
      def sayHello(self):
      print(“halou-----2”)
      bosi = Bosi() bosi.sayHello()
  • <2> 調用父類的方法

    • #coding=utf-8
      class Cat(object):
      def init(self,name):
      self.name = name
      self.color = ‘yellow’
      class Bosi(Cat):
      def init(self,name):

調用父類的__init__方法1(python2)

#Cat.init(self,name)

調用父類的__init__方法2

#super(Bosi,self).init(name)

調用父類的__init__方法3

super().init(name)
def getName(self):
return self.name
bosi = Bosi(‘xiaohua’)
print(bosi.name)
print(bosi.color)

8、多態

多態的概念是應用於Java和C#這一類強類型語言中,而Python崇尚“鴨子類型”

所謂多態:定義時的類型和運行時的類型不一樣,此時就成爲多態

Python僞代碼實現Java或C#的多態

  • classF1(object):
    def show(self):
    print’F1.show’
    classS1(F1):
    def show(self):
    print’S1.show’
    classS2(F1):
    defshow(self):
    print’S2.show’

由於在Java或C#中定義函數參數時,必須指定參數的類型# 爲了讓Func函數既可以執行S1對象的show方法,又可以執行S2對象的show方法,所以,定義了一個S1和S2類的父類# 而實際傳入的參數是:S1對象和S2對象

def Func(F1 obj):
“”“Func函數需要接收一個F1類型或者F1子類的類型”""
print obj.show()
s1_obj = S1()
Func(s1_obj) # 在Func函數中傳入S1類的對象 s1_obj,執行 S1 的show方法,結果:S1.show
s2_obj = S2() Func(s2_obj)

在Func函數中傳入Ss類的對象 ss_obj,執行 Ss 的show方法,結果:S2.show

Python “鴨子類型”

  • class F1(object):
    def show(self):
    print’F1.show’
    class S1(F1):
    def show(self):
    print’S1.show’
    class S2(F1):
    def show(self):
    print’S2.show’
    def Func(obj):
    print obj.show()
    s1_obj = S1()
    Func(s1_obj)
    s2_obj = S2()
    Func(s2_obj)

9、類屬性與實例屬性

類屬性:所屬類,這個類下所有的對象都可以共享這個類屬性。 相當於java中靜態屬性

1、類屬性

  • class People(object):
    name = ‘Tom’#公有的類屬性
    __age = 12#私有的類屬性
    p = People() print(p.name) #正確
    print(People.name) #正確
    print(p.__age) #錯誤,不能在類外通過實例對象訪問私有的類屬性
    print(People.__age) #錯誤,不能在類外通過類對象訪問私有的類屬性

2、實例屬性(對象屬性)

  • classPeople(object):
    address = ‘山東’#類屬性
    def__init__(self):
    self.name = ‘xiaowang’#實例屬性
    self.age = 20#實例屬性
    p = People()
    p.age =12#實例屬性
    print(p.address) #正確
    print(p.name) #正確
    print(p.age) #正確
    print(People.address) #正確
    print(People.name) #錯誤
    print(People.age) #錯誤

3、通過實例(對象)去修改類屬性

  • classPeople(object):
    country = ‘china’#類屬性
    print(People.country)
    p = People()
    print(p.country)
    p.country = ‘japan’
    print(p.country) #實例屬性會屏蔽掉同名的類屬性
    print(People.country)
    del p.country #刪除實例屬性
    print(p.country)

總結

  • 如果需要在類外修改類屬性,必須通過類對象去引用然後進行修改。如果通過實例對象去引用,會產生一個同名的實例屬性,這種方式修改的是實例屬性,不會影響到類屬性,並且之後如果通過實例對象去引用該名稱的屬性,實例屬性會強制屏蔽掉類屬性,即引用的是實例屬性,除非刪除了該實例屬性。

10、類方法和靜態方法

1. 類方法

  • 是類對象所擁有的方法,需要用修飾器@classmethod來標識其爲類方法,對於類方法,第一個參數必須是類對象,一般以cls作爲第一個參數(當然可以用其他名稱的變量作爲其第一個參數,但是大部分人都習慣以’cls’作爲第一個參數的名字,就最好用’cls’了),能夠通過實例對象和類對象去訪問

  • classPeople(object):
    country = ‘china’#類方法,用classmethod來進行修飾
    @classmethod
    def getCountry(cls):
    return cls.country
    p = People() print
    p.getCountry() #可以用過實例對象引用
    print People.getCountry() #可以通過類對象引用

  • 類方法還有一個用途就是可以對類屬性進行修改:

    • classPeople(object):
      country = ‘china’#類方法,用classmethod來進行修飾 @classmethod
      def getCountry(cls):
      return cls.country
      @classmethod
      Def setCountry(cls,country):
      cls.country = country
      p = People()
      print p.getCountry() #可以用過實例對象引用
      print People.getCountry() #可以通過類對象引用
      p.setCountry(‘japan’)
      print p.getCountry()
      print People.getCountry()

2. 靜態方法

  • 需要通過修飾器@staticmethod來進行修飾,靜態方法不需要多定義參數

    • classPeople(object):
      country = ‘china’
      @staticmethod#靜態方法
      Def getCountry():
      return People.country
      print People.getCountry()

總結:

  • 從類方法和實例方法以及靜態方法的定義形式就可以看出來,類方法的第一個參數是類對象cls,那麼通過cls引用的必定是類對象的屬性和方法;而實例方法的第一個參數是實例對象self,那麼通過self引用的可能是類屬性、也有可能是實例屬性(這個需要具體分析),不過在存在相同名稱的類屬性和實例屬性的情況下,實例屬性優先級更高。靜態方法中不需要額外定義參數,因此在靜態方法中引用類屬性的話,必須通過類對象來引用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章