日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【python 3】 面向对象

發(fā)布時間:2023/12/15 python 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【python 3】 面向对象 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 一、面向對象之屬性
    • 二、面向對象之方法
        • 1)普通方法
        • 2)類方法
        • 3)靜態(tài)方法
        • 4)魔術方法
    • 三、私有化
    • 四、裝飾器
    • 五、繼承
    • 六、多態(tài)
    • 七、單例模式

python 是面向對象的變成預研,面向對象編程(Object-oriented Programming,簡稱 OOP)是一種封裝代碼的方法,面向對象的變成可以更好的模擬真實世界里的事物(將其視為對象),并把描述特征的數(shù)據(jù)和代碼框(函數(shù))封裝到一起。

面向對象的常用概念:

  • 類:可以理解成一個模板,通過它可以創(chuàng)造出無數(shù)個具體實例,可以復用且靈活性高。將類創(chuàng)建出實例的過程又稱為類的實例化
  • 對象:類不能直接使用,通過類創(chuàng)建出來的實例(對象)才能使用,表示具體的事物
  • 屬性:類中的所有變量稱為屬性
  • 方法:類中的所有函數(shù)稱為方法,不過和函數(shù)不同的是,類方法至少要包含一個 self 參數(shù),類方法無法單獨使用,只能和類實例化出來的對象一起使用。

多個對象——>提取對象的特征和動作——>封裝到一個類中

先有需求——>找出特征——>定義類

類:所有對象都要有共同的特征和共同的方法

  • 所有的類要求首字母大寫,多個單詞使用駝峰式命名
  • 所有的類都從 object 中繼承過來的
class 類名(父類):屬性:特性...方法:動作...

一、面向對象之屬性

只要遇到 class,就在內存里邊開辟空間,但可以不放東西。然后使用類來構建出一個個實際的對象。

# 定義類 class Phone():pass # 用類來生成實際的對象,類名加() 就找到原來的類地址,創(chuàng)建一個和類相同的空間,地址不同 xiaohua = Phone() print(xiaohua) xiaoming = Phone() print(xiaoming) >>> <__main__.Phone object at 0x00000197A0D6A208> <__main__.Phone object at 0x00000197A0D6A128> # 定義類 class Phone():brand = 'huawei' # 直接用類里邊的屬性 xiaohua = Phone() print(xiaohua.brand) xiaoming = Phone() print(xiaoming.brand) >>> huawei huawei # 定義類 class Phone():brand = 'huawei' # 修改類中的屬性 xiaohua = Phone() xiaohua.brand = 'iPhone' print(xiaohua.brand) xiaoming = Phone() print(xiaoming.brand) >>> iPhone huawei

類屬性:類自帶的屬性
對象屬性:對象在調用了這個類生成對象以后,動態(tài)生成的自己的屬性。

# 定義類和屬性,只要定義類,就會產(chǎn)生一個空間,空間中有有屬性,定義類只是得到一個初始的,但并不是實際的對象 class Student:# 類屬性name = 'xiaoming'age = 3# 使用類來構建一個對象,先定義類,再使用類 # 對象屬性找的時候,先去這個對象空間里邊找,找不到,就去類屬性里邊找 # 對象屬性可以修改,但不會改動類的屬性 xiaoming = Student() # 賦值操作,在xiaoming的空間里新動態(tài)創(chuàng)建一個屬性,這個屬性只屬于xiaoming這個空間,不屬于類空間 # 屬于這個對象自己的屬性,稱為 對象屬性 xiaoming.age = 18 print(xiaoming.age) >>> 18 xiaohua = Student() print(xiaohua.name) # 只要有賦值操作,就會在 xiaohua 的空間里邊增加一個屬性,原本是空的 xiaohua.name = 'xiaohua' xiaohua.age = 1 print(xiaohua.name) print(xiaohua.age) >>> xiaoming xiaohua 1

怎么訪問類屬性:一定要用類名來訪問

Student.name = 'Jack' print(Student.name) >>> Jack

二、面向對象之方法

方法:動作部分

方法的分類:

  • 普通方法,屬于類里邊的方法,依賴于 self,
def 方法名(self[,參數(shù)])方法體...
  • 類方法(就屬于這個類的方法)
  • 靜態(tài)方法
  • 魔術方法

1)普通方法

class Phone:brand = 'xiaomi'price = 4999type = 'mate 80'# 普通方法def call(self):print('正在打電話...')# 當構造的對象叫 phone1 時,self指向 phone1 這個對象print('self: ',self) phone1 = Phone() print('phone1:',phone1) # 輸出內存地址 phone1.call() print('*********************************') phone2 = Phone() print('phone2:',phone2) # 輸出內存地址 phone2.call() >>> phone1: <__main__.Phone object at 0x00000197A0D5C978> 正在打電話... self: <__main__.Phone object at 0x00000197A0D5C978>*********************************phone2: <__main__.Phone object at 0x00000197A0D63518> 正在打電話... self: <__main__.Phone object at 0x00000197A0D63518>

哪個對象調用 call,就會把這個對象作為參數(shù)傳給 self 。就叫做自身。我自己調用 call,就把自己扔進去了。

class Phone:brand = 'xiaomi'price = 4999type = 'mate 80'# 普通方法def call(self):# 當構造的對象叫 phone1 時,self指向 phone1 這個對象print('note: ',self.note) phone1 = Phone() phone1.note = '我是 phone1 的 note' phone1.call() # 往括號里邊傳的就是 phone1 print('*********************************') phone2 = Phone() phone2.note = '我是 phone2 的 note' phone2.call() >>> note: 我是 phone1 的 note ********************************* note: 我是 phone2 的 note

self 的好處:誰調用,self 就是誰

這樣操作可能出現(xiàn)的問題:不是每個對象的屬性都是相同的,或者說有的對象沒有某些屬性。

下面這個例子,就是說不能保證每個被傳進來的 self 都有 address_book.

class Phone:brand = 'xiaomi'price = 4999type = 'mate 80'# 普通方法def call(self):# 當構造的對象叫 phone1 時,self指向 phone1 這個對象 print('正在訪問通訊錄...')for person in self.address_book:print(person.items())phone1 = Phone() phone1.address_book = [{'15900889976':'xiaoming'},{'13457889999':'xiaohua'}] phone1.call() # 往括號里邊傳的就是 phone1 print('\n*********************************\n') phone2 = Phone() phone2.call() >>> 正在訪問通訊錄... dict_items([('15900889976', 'xiaoming')]) dict_items([('13457889999', 'xiaohua')])*********************************正在訪問通訊錄... ... AttributeError: 'Phone' object has no attribute 'address_book'

解決上述問題:

魔術方法:只要用了類的名,系統(tǒng)默認就會執(zhí)行

先定義一個類,會創(chuàng)建一個類,用類創(chuàng)建一個對象。

p = Phone() # 1、先找有沒有 Phone 這個空間 # 2、申請和 Phone 一樣的空間,地址不同 # 3、回到類里邊看,如果類里邊提供了魔術方法__init__ # 如果沒有,不用管,則執(zhí)行將得到的內存空間給到 p # 如果有,則進入 __init__,執(zhí)行里邊的動作,此時 init 里邊的 self 是當這個對象 p 的地址,會把init里邊的屬性放到對象空間里邊。之后就不能改類里邊的屬性了,可以改對象里邊的屬性。 # 4、執(zhí)行完 init 之后,才給對象 p 賦值

init 作用:做一個標準化,保證每個通過這個類得到的對象,都有這些屬性

class Phone:# 魔術方法之一(魔術方法:前后有 __ 的)def __init__(self): # 初始化# self 是創(chuàng)建的對象# self. ... 就表示動態(tài)的給 self 空間中添加了兩個屬性self.brand = 'huawei'self.price = '4999'def call(self):# 當構造的對象叫 phone1 時,self指向 phone1 這個對象 print('正在訪問通訊錄...')for person in self.address_book:print(person.items()) p = Phone()

在 init 中直接傳參:

class Phone:# 魔術方法之一(魔術方法:前后有 __ 的)def __init__(self, name, age): self.name = nameself.age = agedef call(self):print('{}今年{}歲了!'.format(self.name, self.age)) p = Phone('xiaoming',22) p.call() >>> xiaoming今年22歲了!

創(chuàng)建對象的時候,只要傳值了,默認就會把值送到 init 里邊。

class Cat:type = 'cat'# 通過__init__ 初始化特征def __init__(self, nickname, age, color):self.nickname = nicknameself.age = ageself.color = color# 動作:方法def eat(self, food):print('{}喜歡吃{}'.format(self.nickname,food))def catch_mouse(self, color, weight):print('{}抓了一只{}kg的老鼠,{}色的!'.format(self.nickname, weight, color))def sleep(self,hour):if hour<5:print('繼續(xù)睡吧!')else:print('快起來抓老鼠!')def show(self):print('貓的詳情:')print(self.nickname, self.color, self.age) # 創(chuàng)建對象:利用 cat 這個類,構建一個真實的貓 cat1 = Cat('xiaoguai', 2, 'white') # 調用這個類的方法 cat1.catch_mouse('黑','2') cat1.eat('小金魚') cat1.sleep(5) cat1.show() >>> xiaoguai抓了一只2kg的老鼠,黑色的! xiaoguai喜歡吃小金魚 快起來抓老鼠! 貓的詳情: xiaoguai white 2

普通方法的相互調用,要加 self

class Dog:def __init__(self,nickname):self.nickname = nicknamedef run(self):print('{}在院子里跑來跑去'.format(self.nickname))def eat(self):print('{}吃了很多'.format(self.nickname))self.run() d = Dog('大黃') d.eat() >>> 大黃吃了很多 大黃在院子里跑來跑去

2)類方法

普通方法的 self 就是對象,要依靠對象來調用。

類方法直接用類就可以調用。

類方法,調用的時候往這里穿的不是對象,而是類。

特點:

  • 定義需要依賴裝飾器 @classmethod
  • 類方法中的參數(shù)不是一個對象,而是當前的類
  • 類方法只能使用類屬性
  • 類方法不能調用普通方法
  • 類方法,在對象還沒有創(chuàng)建的時候,就可以訪問,直接用類名調用類方法就可以了。

作用:

  • 因為只能訪問類屬性和類方法,可以在對象創(chuàng)建之前,如果需要完成一些功能,就可以放到類方法里邊來。
class Dog:color = 'White'def __init__(self,nickname):self.nickname = nicknamedef run(self):print('{}在院子里跑來跑去'.format(self.nickname))@classmethoddef test(cls): print(cls) # <class '__main__.Dog'> # 類方法的調用 Dog.test() >>> <class '__main__.Dog'>

類方法不能調用有self的方法,因為有self的方法的調用都要依賴于self。

類方法的作用例子:

# 非私有屬性,可以在外邊直接訪問到 class Person:age = 18def show(self):print('---------->',Person.age)print('---------->',self.age)@classmethoddef test(cls):print('---------->類方法') Person.test() Person.age >>> ---------->類方法 18

私有類:只能在類里邊改這個屬性,在外邊不能訪問以及修改

怎么操作呢?只能依賴于類方法對其進行修改

class Person:__age = 18def show(self):print('---------->',Person.age)@classmethoddef test(cls):print('---------->類方法')cls.__age = 20print('修改后的年齡是:', cls.__age)# 不創(chuàng)建對象,就想要改屬性的需求 Person.test() >>> ---------->類方法 修改后的年齡是: 20

3)靜態(tài)方法

靜態(tài)方法:類似于類方法

  • 需要裝飾器 @staticmethod
  • 沒有參數(shù)
  • 只能訪問類的屬性和方法,無法訪問對象的屬性和方法
  • 加載時機和類方法相同
class Person:__age = 18def __init__(self, name):self.name = namedef show(self):print('---------->',Person.age)@staticmethoddef test():print('---------->靜態(tài)方法')print(Person.__age) Person.test() >>> ---------->靜態(tài)方法 18

類方法和靜態(tài)方法的不同:

  • 裝飾器不同
  • 參數(shù)不同,類有參數(shù),靜態(tài)方法沒有參數(shù)

相同之處:

  • 都只能訪問類的屬性和方法
  • 都可以通過類名調用訪問
  • 都可以在創(chuàng)建對象之前來使用,因為都是不依賴于對象的。

普通方法和上述兩者的不同:

  • 普通方法沒有裝飾器
  • 普通方法依賴于對象,因為每個普通方法都有一個self,而self表示對象本身
  • 只有創(chuàng)建了對象,才可以調用普通方法

4)魔術方法

魔術方法就是一個類/對象中的方法,和普通方法唯一的不同是,普通方法需要調用,而魔術方法是在特定時刻自動觸發(fā)。只要你寫了這個魔術方法,不用調也能自動觸發(fā)。

1、_ init _:初始化魔術方法

觸發(fā)時機:初始化對象時觸發(fā),不是實例化觸發(fā),但和實例化在一個操作中

2、_ new _:實例化的魔術方法
觸發(fā)時機:在實例化時,進行觸發(fā)

3、_ call _:將對象當成函數(shù)調用的魔術方法
觸發(fā)時機:將對象當做函數(shù)調用時觸發(fā)

4、_ del :delete的縮寫,析構魔術方法
觸發(fā)時機:當對象沒引用的時候被觸發(fā),也就是沒有任何變量引用的時候。
5、_ str_ :打印對象名
觸發(fā)時機:打印對象名的時候,自動觸發(fā),調用__str_ 里邊的內容。

一定要在這個方法中加return,return 后面的內容就是打印對象看到的內容

單純打印對象的名稱,對開發(fā)者沒有太大的意義,但使用__str__ 就可以直接打印變量名。

class Person:def __init__(self, name):self.name = name p = Person('nana') print(p) >>> <__main__.Person object at 0x00000197A0D96EF0> class Person:def __init__(self, name):self.name = namedef __str__(self):return '姓名是:'+self.name p = Person('nana') print(p) >>> 姓名是:nana

三、私有化

class Student:def __init__(self, name, age):self.__score = 59self.name = nameself.age = agedef __str__(self):return '姓名:{}, 年齡:{}, 分數(shù):{}'.format(self.name, self.age, self.__score) student = Student('nana',18) print(student) >>> 姓名:nana, 年齡:18, 分數(shù):59

能改嗎?下面沒有改成功

student.age = 21 student.__score = 95 print(student) >>> 姓名:nana, 年齡:21, 分數(shù):59

面向對象有一種封裝操作:

  • 私有化屬性
  • 定義共有的 set 和 get 方法

為什么要私有化:

  • 不希望外界來改我的屬性
  • 也可以修改,通過 def setXXX(self,XXX)來修改,
  • 還可以通過范圍限制修改。不希望外界用不合適的值進行修改,就可以在 set 里邊判斷,是否符合我的范圍,如果在內,則可以賦值成功。
  • 如果想獲取具體的某一個屬性,就可以使用 getXXX()

因為外界改不了,所以如果要改的話,要向外界暴露一個公有的東西,set 和 get。

  • set :賦值,也就是將外界給的值給到私有的屬性
  • get:取值
class Student:def __init__():...# setAge() 給私有屬性賦新值def setAge(self,age):self.__age = age# getAge() 可以在外邊直接調用 p.getAge() 來訪問def getAge(self):return self.__age nana = Student() nana.SetAge(21) nana.getAge() class Student:def __init__(self, name, age):self.__score = 59self.__name = nameself.__age = agedef setName(self,name):if len(name)>6:self.__name = nameelse:print('姓名長度必須大于6位!')def setAge(self,age):if age>0 and age<100:self.__age = ageelse:print('年齡不在規(guī)定范圍內!')def getAge(self):return self.__agedef getName(self):return self.__namedef setScore(self,score):if score<100 and score>0:self.__score = scoreelse:print('成績不符合規(guī)范,請重新輸入')def getScore(self):return self.__scoredef __str__(self):return '姓名:{}, 年齡:{}, 分數(shù):{}'.format(self.__name, self.__age, self.__score) nana = Student('nana',18) print(nana)nana.setAge(21) print(nana) print('\n---------------------------\n') nana = Student('nana',25) print(nana) nana.setScore(95) print(nana) print('\n---------------------------\n') print(nana.getName()) print(nana.getAge()) print(nana.getScore()) >>>姓名:nana, 年齡:18, 分數(shù):59 姓名:nana, 年齡:21, 分數(shù):59---------------------------姓名:nana, 年齡:25, 分數(shù):59 姓名:nana, 年齡:25, 分數(shù):95---------------------------nana 25 95

只要加了__name,底層就會給你改名成 _類名__name。

四、裝飾器

在開發(fā)中的私有化處理,裝飾器

給setAge和getAge加一層裝飾器,讓外界用起來和沒有私有化是一樣的,但功能還能和私有化一樣,加一些限制。

class Student:def __init__(self, name, age):self.__score = 59self.__name = nameself.__age = age@propertydef age(self):return self.__age@age.setterdef age(self, age):if age>0 and age<100:self.__age = ageelse: print('年齡不在規(guī)定范圍內!')def __str__(self):return '姓名:{}, 年齡:{}, 分數(shù):{}'.format(self.__name, self.__age, self.__score) nana = Student('nana',18) nana.age = 130 print(nana.age) print(nana) >>> 年齡不在規(guī)定范圍內! 18 姓名:nana, 年齡:18, 分數(shù):59

五、繼承

公路(Road):屬性:公路名稱,公路長度 車(Car):屬性:車名,時速方法:1、求車名在哪條公路上以多少的時速行駛了多長時間2、初始化車輛屬性信息3、打印對象顯示車的屬性信息 import random class Road:def __init__(self, name, len):self.name = nameself.len = lenclass Car:def __init__(self,brand, speed):self.brand = brandself.speed = speeddef get_time(self, road):ran_time = random.randint(1,10)msg = '{}品牌的車在{}上以{}速度行駛{}個小時!'.format(self.brand,road.name,self.speed,ran_time)print(msg)def __str__(self):return '{}品牌的車,速度:{}'.format(self.brand,self.speed) #創(chuàng)建實例化對象 r = Road('京藏高速',12000) print(r.name) audi = Car('Audi',120) print(audi) audi.get_time(r) >>> 京藏高速 Audi品牌的車,速度:120 Audi品牌的車在京藏高速上以120速度行駛2個小時!

1)has a 關系:

has a:一個類里邊有另一個類,不完全是繼承關系,但是是一種包含關系。

# 創(chuàng)建三個類,則系統(tǒng)開辟三個空間,分別存這三個類的信息 # 然后調用的時候,就是創(chuàng)建三個對象 # student對象,需要name,computer # 這里的computer也是一種類型,不過是自定義類型 # list、int 等都是系統(tǒng)提供的類型 # class Computer:pass class Book:pass class Student:pass class Computer:def __init__(self, brand, type, color):self.brand = brandself.type = typeself.color = colordef online(self):print('正在使用電腦上網(wǎng)...')def __str__(self):return self.brand + '---' + self.type + '---' + self.colorclass Book:def __init__(self, bname, author, number):self.bname = bnameself.author = authorself.number = numberdef __str__(self):return self.name + '---' + self.author + '---' + str(self.number)class Student: # has a def __init__(self,name,computer,book):self.name = nameself.computer = computerself.books=[]self.books.append(book)def borrow_book(self, book):for book1 in self.books:if book1.bname == book.bname:print('已經(jīng)借過了')breakelse:# 將這本書加到列表中self.books.append(book)print('添加成功!')def show_book(self):for book in self.books:print(book.bname)def __str__(self):return self.name + '---' + str(self.computer) + '---' + str(self.books)# 創(chuàng)建對象 computer = Computer('mac','mac pro 2018','深灰色') book = Book('盜墓筆記','南派三叔',10) student = Student('nana',computer,book) print(student) book1 = Book('鬼吹燈','天下霸唱',8) student.show_book() student.borrow_book(book1) print('--------------') student.show_book() >>> nana---mac---mac pro 2018---深灰色---[<__main__.Book object at 0x000001F0F2343668>] 盜墓筆記 添加成功! -------------- 盜墓筆記 鬼吹燈

知識點:

  • 理解 has a,一個類里邊使用了另外一種自定義類型
    • student 里邊使用了 computer 和 book
  • 類型:
    • 系統(tǒng)類型:str int float list dict tuple set 等
    • 自定義類型:自定義的類,都可以看做一種類型
      s = Student() s是Student類的對象

2)is a 的關系:

如果 A 是 B,那么 B 就是 A 的基類,基類就是父類。

為什么要層層繼承:

很多類中的方法是重復的,所以把每個類中間都具備的共同特征或共同屬性,放到一個大類里邊,其他的類直接繼承來用就好啦。

# 基類:父類 base class class Student:def __init__(self, name, age):self.name = nameself.age = agedef eat(self):print(self.name + '正在吃飯!')def run(self):print(self.name + '正在跑步!') class Employee:def __init__(self, name, age):self.name = nameself.age = age class Doctor:pass

使用繼承的方法:把父類里邊的東西都繼承過來了,調用的時候是跑到父類里邊去調用的。

所有的類默認繼承的就是 Object,是所有類的父類。

class 子類(父類):...

什么時候需要繼承:

  • 多個類屬于相同的大類
  • 多個類有相同的代碼,冗余,代碼可讀性不高

如何繼承:

  • 將相同的代碼提取出來,得到一個基類
  • 讓子類繼承基類 class Student(Person): ...

特點:

  • 如果類中不定義 init,去父類找
  • 如果需要定義自己的 init,需要在子類的 init 中調用父類的
  • 如何調用父類的 init:
    • super().init(參數(shù))
    • super(類名,self).init(參數(shù))
  • 如果父類的方法無法滿足子類的需求,子類中會重寫一個同名方法,這個方法會把父類的方法覆蓋。也就是如果父類有 eat,子類也有eat,默認先找自己的,再找父類,會把父類的覆蓋。
class Person:def __init__(self, name, age):self.name = nameself.age = agedef eat(self):print(self.name + '正在吃飯!')def run(self):print(self.name + '正在跑步!') class Students(Person):pass class Employee(Person):pass class Dctor(Person):passs = Students('nana',14) # 執(zhí)行步驟,先調 __new__,產(chǎn)生新空間傳給 __init__,student什么都沒有,就會到其父類里邊找 s.run() >>> nana正在跑步!

子類定義 init:都要把父類的 init 調用一下才可以

所有的類傳參數(shù)都是傳到 init 去了,所以,super 傳參也就傳到 init去了。

super其實是一個類,既然是個類,那么就要傳參數(shù),往init傳參數(shù)。

調用的目的:保證把共同的特征拿過來。

# super() 表示父類對象 super().__init__()

無參數(shù)情況下定義 init:

class Person:def __init__(self):self.name = 'nana'self.age = 14def eat(self):print(self.name + '正在吃飯!')def run(self):print(self.name + '正在跑步!') class Students(Person):def __init__(self):print('-----> student 的 init')super().__init__() s = Students() # 執(zhí)行步驟,先調 __new__,產(chǎn)生新空間傳給 __init__,student什么都沒有,就會到其父類里邊找 s.run() >>> -----> student 的 init nana正在跑步!

有參數(shù)情況下定義 init:

為什么要在每個子類定義 init:因為每個子類都會有他的特有屬性和方法。

class Person:def __init__(self, name, age):self.name = nameself.age = agedef eat(self):print(self.name + '正在吃飯!')def run(self):print(self.name + '正在跑步!') class Students(Person):def __init__(self, name, age):print('-----> student 的init')super().__init__(name, age) class Employee(Person):pass class Dctor(Person):passs = Students('Jack',18) # 執(zhí)行步驟,先調 __new__,產(chǎn)生新空間傳給 __init__,student什么都沒有,就會到其父類里邊找 s.run() e = Employee('lily',13) e.run() >>> -----> student 的init Jack正在跑步! lily正在跑步!

并非所有類的屬性都是共有的,類都會有自己特有的東西,所以,需要定義個體的不同之處:

class Person:def __init__(self, name, age):self.name = nameself.age = agedef eat(self):print(self.name + '正在吃飯!')def run(self):print(self.name + '正在跑步!')class Students(Person):def __init__(self, name, age, classes):super().__init__(name, age) # 利用 super 把父類有的屬性拿過來self.classes = classes # 自己定義的屬性def study(self, course):print('{}正在學{}'.format(self.name, course))def eat(self, food): # super().eat()print('{}正在吃飯,喜歡吃{}'.format(self.name, food))class Employee(Person):def __init__(self, name, age, salary, manager):super().__init__(name, age)self.salary = salaryself.manager = managerclass Doctor(Person):def __init__(self, name, age, patients):super().__init__(name, age) # super(Doctor, self).__init__(name, age) # 和上面等價,不過底層會做一個 isinstance 的判斷,判斷傳進來的是不是 Doctorself.patients = patientss = Students('Jack',18, '1611') # 執(zhí)行步驟,先調 __new__,產(chǎn)生新空間傳給 __init__,student什么都沒有,就會到其父類里邊找 s.run() s.study('python基礎') s.eat('紅燒肉') e = Employee('lily',23, 10000, 'king') e.run() list1 = ['tom','jack','json','lili'] d = Doctor('lucy', 30, list1) d.run() >>> Jack正在跑步! Jack正在學python基礎 Jack正在吃飯,喜歡吃紅燒肉 lily正在跑步! lucy正在跑步!

練習:工資管理程序

編寫一個工資管理程序,管理以下四類人: worker, salesman, manager, salemanager。 所有員工都具有工號,姓名,工資等屬性,有設置姓名,獲取姓名,獲取員工號,計算工資等方法。 1)worker:具有工作小時數(shù)和時薪的屬性,工資 = 小時*時薪 2)salesman:具有銷售額和提成比例的屬性,工資 = 銷售額*提成 3)manager:固定月薪 4)salasmanager:工資 = 銷售額*提成比例*月薪 請完成以下功能: 1)添加所有類型的人員 2)計算月薪 3)顯示所有人工資 class Person:def __init__(self, no, name, salary):self.no = noself.name = nameself.salary = salarydef __str__(self):msg = '工號:{}, 姓名:{}, 本月工資:{}'.format(self.no, self.name, self.salary)return msgdef getSalary(self):return self.salary class Worker(Person):def __init__(self, no, name, salary, hours, per_hour_money):super().__init__(no, name, salary)self.hours = hoursself.per_hour_money = per_hour_moneydef getSalary(self):money = self.hours*self.per_hour_moneyself.salary += moneyreturn self.salary class Salesman(Person):def __init__(self, no, name, salary, salemoney, percent):super().__init__(no, name, salary)self.salemoney = salemoneyself.percent = percentdef getSalary(self):money = self.salemoney*self.percentself.salary += moneyreturn self.salary # 創(chuàng)建對象 worker = Worker('001','king',2000,160,50) S = worker.getSalary() print('月薪是:',S) print(worker) saler = Salesman('002','lucy',5000,5000000,0.003) s = saler.getSalary() print('月薪是:',s) print(saler) >>> 月薪是: 10000 工號:001, 姓名:king, 本月工資:10000 月薪是: 20000.0 工號:002, 姓名:lucy, 本月工資:20000.0

有重名的方法,后面的會把前面的覆蓋掉:

class Person:def __init__(self, name):self.name = namedef eat(self):print('--------eat1')def eat(self,food):print('--------eat',food) p = Person() p.eat() >>> TypeError: eat() missing 1 required positional argument: 'food'p = Person('jack') p.eat('紅燒肉') >>> --------eat 紅燒肉

python 允許多繼承:

class A:def test(self):print('AAAAAAAAA') class B:def test1(self):print('BBBBBBBBB') class C(A,B):def test2(self):print('CCCCCCCCC') c = C() c.test1() c.test() >>> BBBBBBBBB AAAAAAAAA

多繼承的搜索順序:

class Base:def test(self):print('-------Base---------') class A(Base):def test(self):print('AAAAAAAAAAAAAAAAAAAA') class B(Base):def test(self):print('BBBBBBBBBBBBBBBBBBBB') class C(Base):def test(self):print('CCCCCCCCCCCCCCCCCCCC') class D(A, B, C):pass d = D() d.test() import inspect print(inspect.getmro(D)) print(D.__mro__) # 獲取搜索順序方法二 >>> AAAAAAAAAAAAAAAAAAAA (<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Base'>, <class 'object'>)

python 允許多繼承:

def 子類(父類1,父類2:pass

父類中有相同的方法時,搜索順序:從左至右,深度優(yōu)先

六、多態(tài)

python 類似于多態(tài),但是是依賴于 isinstance 來判斷的。

isinstance(obj,): 判斷obj是不是該類的對象或該類子類的對象 class Person:def __init__(self,name):self.name = namedef feed_pet(self, pet):if isinstance(pet, Pet): print('{}喜歡養(yǎng)寵物:{},昵稱是:{}'.format(self.name,pet.role, pet.nickname))else:print('不是寵物,不能養(yǎng)!')class Pet:role = 'Pet'def __init__(self, nickname, age):self.nickname = nicknameself.age = agedef show(self):print('昵稱:{},年齡:{}'.format(self.nickname, self.age)) class Cat(Pet):role = 'Cat'def catch_mouse(self):print('抓老鼠...') class Dog(Pet):role = 'Dog'def whatch_house(self):print('看家高手...') class Tiger:def eat(self):print('太可怕了...') # 創(chuàng)建對象 cat = Cat('huahua', 2) dog = Dog('dahuang', 4) tiger = Tiger() person = Person('nana') person.feed_pet(cat) person.feed_pet(tiger) >>> nana喜歡養(yǎng)寵物:Cat,昵稱是:huahua 不是寵物,不能養(yǎng)!

七、單例模式

開發(fā)模式:單例模式

單個對象就叫單例模式

class Student:pass s = Student() s1 = Student() s2 = Student()

上面這種創(chuàng)建對象的模式,會導致每次調用這個類,系統(tǒng)都會給這個對象分配一個空間,多個地址。

單例模式,開發(fā)過程中,一個實例就搞定的,不需要每次實例化的時候都開辟一個空間。也就是每次調用這個類的時候,都指向同一個地址,不會占用很多空間。

調用的時候底層的操作:

  • 先找 new,幫我們產(chǎn)生內存地址,產(chǎn)生后賦值給 __instance,返回給 init
  • 再找 init,如果找不到,就找父類的init
  • 最后賦值地址給對象
class Singleton:# __instance 就是保存變量空間的私有變量# 私有化# 保證單例的地址都存在在這里,別人也沒法改__instance = None# __new__ 是開辟空間的方法,所以要單例化,就要重寫這個方法# 重寫父類,把__new__修改了def __new__(cls):print('----->instance:', cls.__instance)if cls.__instance is None:print('------->1')cls.__instance = object.__new__(cls)return cls.__instanceelse:print('------->2')return cls.__instance # 調實例化對象,先判斷__instance是否為 None,如果為 None,則調用父類的 new 給分配空間,且修改了__instance s = Singleton() # 再次實例化對象,__instance 已經(jīng)不是 None了,所有會走 else 分支 s1 = Singleton() print(s) print(s1) >>> ----->instance: None ------->1 ----->instance: <__main__.Singleton object at 0x000001F0F2746390> ------->2 <__main__.Singleton object at 0x000001F0F2746390> <__main__.Singleton object at 0x000001F0F2746390>

總結

以上是生活随笔為你收集整理的【python 3】 面向对象的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。