Python基礎筆記_Day10_Python面向物件、類和物件、__init__、__str__、訪問限制、set、get
Day10_Python面向物件、類和物件、init、str、訪問限制、set、get
10.01_Python語言基礎(面向物件思想)(理解) 10.02_Python語言基礎(類和物件)(掌握) 10.03_Python語言基礎(類的構成)(掌握) 10.04_Python語言基礎(類的抽象)(掌握) 10.05_Python語言基礎(定義類)(掌握) 10.06_Python語言基礎(經典類和新式類)(熟練) 10.07_Python語言基礎(建立物件)(掌握) 10.08_Python語言基礎(__init__方法和self的作用)(掌握) 10.09_Python語言基礎(__del__()方法(析構方法))(熟練) 10.10_Python語言基礎(建立多個物件)(掌握) 10.11_Python語言基礎(魔方方法)(掌握) 10.12_Python語言基礎(__str__和__repr__())(掌握) 10.13_Python語言基礎(構造方法)(掌握) 10.14_Python語言基礎(重寫__init__()和__str__()方法)(掌握) 10.15_Python語言基礎(理解self)(掌握) 10.16_Python語言基礎(應用-烤牛排)(掌握) 10.17_Python語言基礎(訪問限制)(掌握) 10.18_Python語言基礎(set()和get()方法)(掌握) 10.19_Python語言基礎(複習今天的內容)(掌握)
10.01_Python語言基礎(面向物件思想)(理解)
面向物件的思想
思考:
請用程式描述如下事件:
A同學報道等級資訊
B同學報道等級資訊
C同學報道等級資訊
A同學做自我介紹
B同學自我介紹
c同學自我介紹
""" 請用程式描述如下事件: A同學報道等級資訊 B同學報道等級資訊 C同學報道等級資訊 A同學做自我介紹 B同學自我介紹 c同學自我介紹 """ stu_a = {"name":"A","age":21} stu_b = {"name":"B","age":22} stu_c = {"name":"C","age":23} def stu_infor(stu): for key,value in stu.items(): print("key = %s,value = %d"%(key,value)) """
面向過程:
根據業務邏輯從上到下寫程式碼
面向物件:
將資料與函式繫結到一起,進行封裝,能夠更快速的開發程式,減少程式碼的重寫的過程
def 傳送郵件(內容):
# 連線郵箱伺服器
# 傳送郵件
# 關閉連線
10.02_Python語言基礎(類和物件)(掌握)
- 類和物件的概述
物件和類
物件是面向物件思想的核心
在使用物件的過程中,為了將具有共同特徵和行為的一組物件抽象定義-----》類
類---》製造飛機的圖紙
用它來建立的飛機就相當於物件
類
具有相似的內部狀態和運動規律的實體的集合(抽象) 或者具有相同的屬性和行為的統稱 定義: 類 抽象的 在使用的時候通常會找到這個類的具體的存在----》物件 特點: 使用這個具體的存在,一個類可以找到多個物件,一個類可以建立多個物件
物件
概述:
某一個具體事物的存在,在現實世界中可以看得見摸得著
可以直接使用
總結:
類和物件之間的關係:
就像利用玩具模型來建立多種不同的玩具
類就是建立物件的模板
區分類和物件
賓士汽車 類
賓士smart 類
張三的那輛賓士smart 物件
狗 類
大黃狗 類
李四家的那隻大黃狗 物件
水果 類
蘋果 類
紅蘋果 類 紅富士蘋果 類
張三嘴裡吃了一半的蘋果 物件
10.03_Python語言基礎(類的構成)(掌握)
類的構成
類(class):由3部分組成
類的名稱:類名
類的屬性:一組資料
類的方法:允許對其操作的方法(行為)
設計一個人類
"""
事物的名稱(類名):人(Person)
屬性:身高 年齡
方法(行為):跑,吃飯
"""
"""
狗 類
類名:dog
屬性:品種,毛色,性別,腿的數量
方法:叫,跑,咬人,搖尾巴
"""
10.04_Python語言基礎(類的抽象)(掌握)
如何把日常生活中的事物抽象成程式中的類?
類:
擁有相同屬性和行為的物件可以抽取出來-----》類
一般名稱提煉法
例如:
1.坦克發射了3顆炮彈炸掉了2架飛機
坦克----》抽象成類
炮彈---》抽象成類
飛機----》抽象成類
2.小明在公車上牽了一條叼著熱狗的狗
小明 -----》 人類
公車 -----》 交通工具類
熱狗 -----》 食物類
狗 -----》 狗類
遊戲中的類和物件
cf
人
槍
植物大戰殭屍:
向日葵 -----》類
類名:xrk
屬性:顏色,尺寸
行為:產生陽光
豌豆: ------》 類
類名: wd
屬性:顏色,髮型
行為:發射炮彈
殭屍:
類名:js
屬性:顏色,
行為:走,吃植物,啃
10.05_Python語言基礎(定義類)(掌握)
定義一個類的格式:
class 類名:
屬性1
屬性2
屬性3
... ...
方法1
方法2
方法3
... ...
定義類–貓
"""
貓:
類名:cat
屬性:毛色,性別
行為:跑,吃
"""
class Cat:
#屬性
#方法
def eat(self):
print("貓吃魚....")
def drink(self):
print("貓喝可樂....")
定義類–車
"""
車:
類名:Car
屬性:顏色,
行為:跑
"""
class Car:
#方法列表
def getCarInfo(self):
print("車的輪子數:%d,顏色%s"%())
def move(self):
print("車子在移動....")
10.06_Python語言基礎(經典類和新式類)(熟練)
新式類:
* Python2.2引入了新式類
* Python3.X之後預設都是新式類,採用了C3演算法,__MRO__可以檢視繼承順序
* 在類名後面(object),Car(object)
- 說明:
- 定義類的時候有兩種,新式類和經典類,上面定義Car為經典類
- 如class Car(object): 是新式類
- class Cat: 是經典類
注意:
定義類名時,儘量使用大駝峰命名法則
10.07_Python語言基礎(建立物件)(掌握)
python中,可以根據已經定義好的類來建立一個一個的物件
- 建立物件的格式:物件名 = 類名()
建立一個Car類
#建立一個Car類
class Car(object):
def move(self):
print("車子在移動....")
def toot(self):
print("車子在鳴笛....")
#建立車子的物件,並用變數進行儲存
BMW = Car()
BMW.color = "黑色"#車子的顏色
BMW.wheelNum = 4#車輪的數量
BMW.color = "白色"
BMW.move()
BMW.toot()
print(BMW.color)
print(BMW.wheelNum)
總結:
BMW = Car():這樣就產生了一個Car的例項物件,
此時可以通過例項物件BMW訪問屬性和行為
BMW—>物件,它擁有屬性和行為
為物件新增屬性
- 下面以Cat類為例子,新增屬性
class Cat:
def eat(self):
print("貓在吃魚.....")
def drink(self):
print("貓在和芬達....")
#建立一個Cat物件
tom = Cat()
#呼叫tom指向的物件中的方法
tom.eat()
tom.drink()
tom.name = "湯姆"
tom.age = 3
獲取物件的屬性
class Cat:
def eat(self):
print(“貓在吃魚…”)
def drink(self):
print(“貓在和芬達…”)
#建立一個Cat物件
tom = Cat()
#呼叫tom指向的物件中的方法
tom.eat()
tom.drink()
tom.name = "湯姆"
tom.age = 3
print("tom的中文名:%s,年齡:%d"%(tom.name,tom.age))
10.08_Python語言基礎(__init__方法和self的作用)(掌握)
init方法是初始化函式,用來完成一些物件預設的設定
- init方法格式
class 類名:
#初始化函式,用來完成一些預設的設定
def __init__(self):
函式體語句
- init()方法呼叫
- 下面以汽車類Car示例init方法的呼叫
# 第一種方式
class Car:
# 初始化方法
def __init__(self):
self.color = "黑色"
self.wheelNum = 4
# 普通的方法,移動
def move(self):
print("車子在移動.....")
# 建立物件
bmw = Car()
print("車子的顏色:%s" % bmw.color)
print("車子的輪子數:%d" % bmw.wheelNum)
bmw1 = Car()
print("車子的顏色:%s" % bmw1.color)
print("車子的輪子數:%d" % bmw1.wheelNum)
總結:
當建立Car物件後,在沒有呼叫__init__()函式的前提下,
bmw就預設擁有了兩個屬性color/wheelNum,
原因是__init__()函式在建立物件後,就立刻預設被呼叫
- 還有另一種方式能更靈活的使用init方法
#第二種方式
class Car:
#初始化方法
def __init__(self,newWheelNum,newColor):
self.wheelNum = newWheelNum
self.color = newColor
#普通的方法,移動
def move(self):
print("車子在移動.....")
#建立物件
bmw = Car(4,"黃色")
print("車子的顏色:%s"%bmw.color)
print("車子的輪子數:%d"%bmw.wheelNum)
bmw1 = Car(6,"綠色")
print("車子的顏色:%s"%bmw1.color)
print("車子的輪子數:%d"%bmw1.wheelNum)
總結:
init():在建立一個物件的時候預設被呼叫,不需要手動呼叫
init(self),預設一個引數名字為self,不需要開發者傳遞
python 直譯器會自動將當前的物件的引用傳遞進來
10.09_Python語言基礎(del()方法(析構方法))(熟練)
- 建立物件後,python直譯器預設呼叫__init__()
- 當刪除一個物件的時候,python直譯器也會預設呼叫__del__()
分析下面案例
import sys
class Cat(object):
def __init__(self):
self.color = "while"
self.weight = "8斤"
def __del__(self):
print("所有物件被幹掉啦")
def __str__(self):
return ("顏色%s-體重%s" % (self.color, self.weight))
Tom01 = Cat()
print("Tom01即將被幹掉,當前Tom01引用指向地址被引用數量%s" % sys.getrefcount(Tom01))
Tom02 = Tom01
Tom03 = Tom02
print(Tom01)
print(Tom02)
print(Tom03)
print("Tom01即將被幹掉,當前Tom01引用指向地址被引用數量%s" % sys.getrefcount(Cat))
print(id(Cat))
del Tom01
print("Tom02即將被幹掉,當前Tom02引用指向地址被引用數量%s" % sys.getrefcount(Tom02))
print("Tom02即將被幹掉,當前Tom03引用指向地址被引用數量%s" % sys.getrefcount(Tom03))
print("Tom02和Tom03引用指向地址是相同的嗎?", Tom02 == Tom03)
del Tom02
print("Tom02被幹掉啦")
# del Tom03
# print("Tom03被幹掉啦")
print("我是程式結尾的一句話")
print("-" * 30)
print(Tom03)
print(repr(Tom03))
print(eval(repr(Tom03)))
- 總結:
- 當有1個變數儲存了物件的引用,此時物件的引用計數加1
- 當使用__del__()函式的時候,刪除的是變數指向的物件時,
- 如果物件的引用計數不為1,比如3,那麼此時只會讓這個引用計數減1
- 即變為2,當再次呼叫del 此時會通用刪除引用計數,直到變數的引用計數為0
- 此時才會將變數指向的物件真正刪除
- 獲取物件計數:sys.getrefcount(object))
10.10_Python語言基礎(建立多個物件)(掌握)
同一個類可以建立多個物件,比如常見的貓有加菲和Tom
class Cat:
def eat(self):
print("貓吃魚....")
def drink(self):
print("貓喝水....")
#建立tom 物件
tom = Cat()
tom.eat()
tom.drink()
#給tom指向的物件新增兩個屬性
tom.name = "湯姆"
tom.age = 2
jiafei = Cat()
jiafei.eat()
jiafei.drink()
jiafei.name = "加菲"
jiafei.age = 3
同一個類建立的多個物件是相互獨立的
10.11_Python語言基礎(魔方方法)(掌握)
- 魔方方法:
- 魔法方法是Python中的特殊方法
- 魔方方法是指指被包含下劃線的方法或者所能呼叫的方法的統稱
- 這些統方法在特殊的情況下被呼叫,並且基本沒有手動呼叫它的必要
下面我們看一下使用Cat類編寫的案例
#定義類
class Car:
def init(self,newWheelNum,newColor):
self.wheelNum = newWheelNum
self.color = newColor
def __str__(self):
msg = "嘿嘿....我的顏色是"+self.color+"我有"+self.wheelNum+"個輪子"
return msg
def move(self):
print("車子在移動....")
#建立一個物件
bmw = Car("4","白色")
print(bmw)
總結:
在python中方法名如果是__XXX__那麼就具有特殊的功能,—》魔方
str():
當使用print輸出物件,只要定義了__str__()方法,
那麼就會返回這個方法中return 的資料
10.12_Python語言基礎(str__和__repr())(掌握)
- str__和__repr()
- repr()與__str__()函式的功能類似
- str()用於將數值轉化為人閱讀的形式
- repr()轉化為python直譯器讀取的形式
str():在呼叫print列印物件的時候自動呼叫,給使用者用的,是一個描述物件的方法
repr():給機器用的,供python的直譯器讀取
注意:
在沒有__str__()函式時,有__repr__(),str == repr
import datetime
now = datetime.datetime.now()
print(str(now))
print(repr(now))
print(eval(repr(now)))
說明:
datetime python的內建模組,import 載入匯入模組
now = datetime.datetime.now()系統當前的時間賦值給now變數
eval函式是把引數當做程式碼執行,驗證repr之後的字串可以被python識別執行
class Person(object):
def __init__(self,name,age,height,weight):
self.name = name
self.age = age
self.height = height
self.weight = weight
def __str__(self):
return "%s-%d-%d-%d"%(self.name,self.age,self.height,self.weight)
#建立人的物件
per = Person("hanmeimei",20,170,55)
print(per)
print(repr(per))
# print(eval(repr(per)))#eval函式中的引數為一個字串,如果不是一個字串會報錯
aa = "hello"
print(repr(aa))
print(eval(repr(aa)))
優點:
當一個物件的屬性過多,並且還要列印,重寫__str__()方法簡化程式碼的書寫
可讀性強
注意:
repr()函式得到的字串,通常可以用來獲得該物件,obj == eval(repr(obj))這個等式是成立的
返回的是一個字串
10.13_Python語言基礎(構造方法)(掌握)
- 定義:
- 構造方法類似__init__()函式,差別在於一個物件被構建好之後會自定呼叫該方法
- python中建立一個構造方法(使用__init__())
class Cat:
def __init__(self):
初始化屬性
10.14_Python語言基礎(重寫__init__()和__str__()方法)(掌握)
- 概述:
- Python中所有的類都直接或間接繼承object
- object中有__init__()和__str__()方法
- object中的這兩個方法大部分時間和我們使用時的需求不匹配
- 我們可以根據自己的需求對方法體進行更改,這就叫做重寫
- 更多內容在明天的知識點繼承中
- 重寫方法使用總結:
- 當兩個關聯的類,出現了相同的函式名,在呼叫該函式時,先在本類中找,
- 如果有,呼叫
- 如果沒有,在去父類找,如果有呼叫,
- 如果沒有,去基類,找不到報錯
重寫對於類很重要:
尤其對於構造 init
class Bird():
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print(".....")
self.hungry = False
else:
print("no thanks")
b = Bird()
b.eat()
b.eat()
重寫的定義:
在子類中定義了一個和父類同名的函式—》重寫
10.15_Python語言基礎(理解self)(掌握)
#定義一個類
class Animal:
def __init__(self,name):
self.name = name
def printName(self):
print("名字為:%s"%self.name)
#定義一個函式
def myPrint(animal):
animal.printName()
#建立物件
dog1 = Animal("西西")
myPrint(dog1)
dog2 = Animal("北北")
myPrint(dog2)
- 總結:
* 所謂self理解為自己,也就是物件自身
* 程式中的self是什麼?哪個物件呼叫了__init__(),self就代表誰
10.16_Python語言基礎(應用-烤牛排)(掌握)
"""
烤牛排:
類:
類名:
牛排:
屬性:
幾成熟
0--3表示生的,4--6表示半生不熟,7--9表示熟了,10及以上表示糊了
紅酒
胡椒
... ...
行為:
燒烤時間
新增佐料
__init__()
__str__()
"""
class CookSteak:
def __init__(self):
self.time = 0
self.cook_level = 0
self.cook_string = "生的"
self.condiments = []
def cook(self, time):
self.cook_level += time
if self.cook_level > 9:
self.cook_string = "扔了吧,都糊啦"
elif self.cook_level > 6:
self.cook_string = "熟了,味道應該很棒"
elif self.cook_level > 3:
self.cook_string = "半生不熟,快要熟了"
elif self.cook_level > 0:
self.cook_string = "牛排剛放進去,耐性等一會"
else:
print("沒有這個狀態")
print("牛排已經烤了很久了,現在達到%s成熟了," % self.cook_level)
def add_cendiments(self, cendiments):
self.condiments.append(cendiments)
def __str__(self):
return "牛排已經烤了很久了,現在達到%s成熟了,新增的佐料有%s" % (self.cook_level, self.condiments)
hui_ling_dun = CookSteak()
hui_ling_dun.cook(1)
hui_ling_dun.cook(1)
hui_ling_dun.cook(1)
hui_ling_dun.cook(1)
hui_ling_dun.add_cendiments("胡椒粉")
hui_ling_dun.cook(1)
hui_ling_dun.cook(1)
hui_ling_dun.add_cendiments("紅酒")
hui_ling_dun.cook(1)
print(hui_ling_dun)
10.17_Python語言基礎(訪問限制)(掌握)
- 如果有一個物件,當需要對其進行修改屬性:
- 方法2種
- #直接修改 物件名.屬性名 = 資料
- #間接修改 物件名.方法名()
將屬性定義為私有
格式:
__屬性名
屬性私有案例
# 定義一個類
class Person(object):
def __init__(self, name):
self.__name = name
def __str__(self):
return self.__name
def getName(self):
return self.__name
def setName(self, newName):
if len(newName) <= 5:
self.__name = newName
else:
print("名字的長度需要小於等於5")
person = Person("張三")
# print(person)
# #直接修改 物件名.屬性名 = 資料
# person.__name = "李四"
# print(person)
# 間接訪問 物件名.屬性名
# print(person.__name) #報錯
person.setName("李四")
print(person.getName())
person.setName("王五")
print(person.getName())
- python沒有c++或者Java中的public(公有) private(私有)區分公有和私有
- python以屬性的命名方式來進行區分:
- 如果在屬性名前面加上兩個下劃線“__”,則表明該屬性是私有屬性
- 否則就是公有屬性(方法的設定同屬性設定一致)
其實,Python並沒有真正的私有化支援,但可用下劃線得到偽私有。
儘量避免定義以下劃線開頭的變數!
(1)_xxx "單下劃線 " 開始的成員變數叫做保護變數,
意思是隻有類例項和子類例項能訪問到這些變數,
需通過類提供的介面進行訪問;不能用'from module import *'匯入
(2)__xxx 類中的私有變數/方法名 (Python的函式也是物件,
所以成員方法稱為成員變數也行得通。),
" 雙下劃線 " 開始的是私有成員,意思是隻有類物件自己能訪問,連子類物件也不能訪問到這個資料。
(3)__xxx__ 系統定義名字,前後均有一個“雙下劃線” 代表python裡特殊方法專用的標識,
如 __init__()代表類的建構函式。
10.18_Python語言基礎(set()和get()方法)(掌握)
- Python私有屬性修改
- 類中的屬性私有化之後,外部無法訪問
- 我們可以在類中定義公共的方法提供給外部,讓這個公共的方在類內部修改私有屬性
set()和get()使用案例:
class Person(object):
def __init__(self,name,age,height,weight,money):
self.name = name
self.__age__ = age
self.height = height
self.weight = weight
self.__money = money
def ss(self):
print(self.__money)
#通過內部的方法,去修改私有屬性
#通過自定義的方法實現對私有屬性的修改
def getMoney(self):
return self.__money
def setMoney(self,money):
#資料的過濾
if money < 0:
money = 0
self.__money = money
#建立物件
person = Person("張三",12,170,55,100)
# person.age = 15
# person.setMoney(200)
# print(person.getMoney())
# print(person.__money)#外部使用 不ok
print(person.ss)#內部 ok
思考,不能通過物件訪問私有屬性?
在python的直譯器把__money 變成_Person_money.
任然可以使用_Person_money去訪問,但是不建議這麼做,
"""
person._Person__money = 1
print(person.getMoney())
print(person.__age__)
"""
在python中__XXX__,屬於特殊的變數,可以直接訪問(公有)
"""