Python快速入門(八)面向對象1:類、對象和封裝
前言:之前的《Python快速入門》一到七個章節中用到的都是面向過程的編程方式,面相過程和麪相對象,是兩種不同的編程方式。面向過程:簡單的理解就是把完成某一個需求的所有步驟從頭到尾逐步實現的過程。面向對象:簡單的理解就是面向對象是更大的封裝,根據 職責在一個對象中封裝多個方法(注意:如果你有Java基礎,會很好理解的)。
1.類和對象
1)類的定義
- 定義:是對一羣具有相同特徵或者行爲的事物的一個統稱,是抽象的,不能直接使用
- 特徵 被稱爲 屬性。
- 行爲 被稱爲 方法
2)對象的定義
- 定義:對象是由類創建出來的一個具體存在,可以直接使用。
- 由 哪一個類創建出來的對象,就擁有在哪一個類中定義的屬性和方法。
3)類和對象的關係
- 類是模板,對象 是根據 類 這個模板創建出來的,應該 先有類,再有對象。
- 類 只有一個,而 對象 可以有很多個(注意:不同的對象 之間 屬性 可能會各不相同)。
- 類 中定義了什麼 屬性和方法,對象 中就有什麼屬性和方法,不可能多,也不可能少。
4)類的設計
- 類名 這類事物的名字,滿足大駝峯命名法(注意:每一個單詞的首字母大寫,單詞與單詞之間沒有下劃線)
- 屬性 這類事物具有什麼樣的特徵
- 方法 這類事物具有什麼樣的行爲
2.第一個面向對象案列
代碼1
解析:創建了一個Dog類,Dog類裏面有兩個函數(也稱方法),然後通過創建Dog的對象wang,調用類裏面的方法,完成輸出。
class Dog:
def eat(self):
print("狗啃骨頭")
def drink(self):
print("狗喝水")
# 創建狗對象
wang = Dog()
wang.eat()
wang.drink()
print(wang)
#打印狗這個對象的地址
addr = id(wang)
print("%x" % addr)
輸出:
代碼2
同樣我們可以創建多個對象,來調用類的方法。可以從輸出的兩個對象的地址不同,判斷創建了兩個對象。
class Dog:
def eat(self):
print("狗啃骨頭")
def drink(self):
print("狗喝水")
# 創建狗1對象
wang1 = Dog()
wang1.eat()
wang1.drink()
print(wang1)
#打印狗1這個對象的地址
addr1 = id(wang1)
print("%x" % addr1)
# 創建狗2對象
wang2 = Dog()
wang2.eat()
wang2.drink()
print(wang2)
#打印狗2這個對象的地址
addr2 = id(wang2)
print("%x" % addr2)
輸出:
3.設置對象屬性
代碼:
class Cat:
def eat(self):
# 哪一個對象調用的方法,self就是哪一個對象的引用
print("%s 愛喫魚" % self.name)
def drink(self):
print("%s 要喝水" % self.name)
# 創建貓對象
tom = Cat()
# 可以使用 .屬性名 利用賦值語句就可以了
tom.name = "Tom"
tom.eat()
tom.drink()
print(tom)
# 再創建一個貓對象
lazy_cat = Cat()
lazy_cat.name = "大懶貓"
lazy_cat.eat()
lazy_cat.drink()
print(lazy_cat)
輸出:
注意:如果在設置屬性之前,就先調用函數,則會出錯。
代碼:
# 創建貓對象
tom = Cat()
# 可以使用 .屬性名 利用賦值語句就可以了
# tom.name = "Tom" #放到函數的後面
tom.eat()
tom.drink()
tom.name = "Tom"
print(tom)
輸出:
4.init初始化方法
- 使用類名()創建對象的時候,會自動調用初始化方法 init
代碼:
class Cat:
def __init__(self):
print("這是一個初始化方法")
# self.屬性名 = 屬性的初始值
self.name = "Tom"
def eat(self):
print("%s 愛喫魚" % self.name)
tom = Cat()
print(tom.name)
輸出:
5.利用參數設置屬性初始值
代碼:
class Cat:
def __init__(self, new_name):
print("這是一個初始化方法")
self.name = new_name
def eat(self):
print("%s 愛喫魚" % self.name)
tom = Cat("Tom")
tom.eat()
lazy_cat = Cat("大懶貓")
lazy_cat.eat()
輸出:
6.del方法
代碼:
class Cat:
def __init__(self, new_name):
self.name = new_name
print("%s 來了" % self.name)
def __del__(self):
print("%s 我去了" % self.name)
# tom 是一個全局變量
tom = Cat("Tom")
print(tom.name)
# del 關鍵字可以刪除一個對象
del tom
# print(tom)# 出錯
輸出:
7.str方法
直接打印對象的名字,如果這個類裏面重寫str方法,則打印對象的名字,則會調用str方法返回的字符串。
代碼:
class Cat:
def __init__(self, new_name):
self.name = new_name
print("%s 來了" % self.name)
def __str__(self):
# 必須返回一個字符串
return "我是小貓[%s]" % self.name
# tom 是一個全局變量
tom = Cat("湯姆")
print(tom)
輸出:
8.封裝(跑步案列)
- 封裝 是面向對象編程的一大特點
- 面向對象編程的 第一步 —— 將 屬性 和 方法 封裝 到一個抽象的 類 中
- 外界 使用 類 創建 對象,然後 讓對象調用方法
- 對象方法的細節 都被 封裝 在 類的內部
代碼:
class Person:
def __init__(self, name, weight):
# self.屬性 = 形參
self.name = name
self.weight = weight
def __str__(self):
return "我的名字叫 %s 體重是 %.2f 公斤" % (self.name, self.weight)
def run(self):
print("%s 愛跑步,跑步鍛鍊身體" % self.name)
self.weight -= 0.5
def eat(self):
print("%s 是喫貨,喫完這頓再減肥" % self.name)
self.weight += 1
xiaoming = Person("小明", 75.0)
xiaoming.run()
xiaoming.eat()
print(xiaoming)
# 小美愛跑步
xiaomei = Person("小美", 45)
xiaomei.eat()
xiaomei.run()
print(xiaomei)
print(xiaoming)
輸出:
9.封裝(傢俱案例)
代碼:
class HouseItem:
def __init__(self, name, area):
self.name = name
self.area = area
def __str__(self):
return "[%s] 佔地 %.2f" % (self.name, self.area)
class House:
def __init__(self, house_type, area):
self.house_type = house_type
self.area = area
# 剩餘面積
self.free_area = area
# 傢俱名稱列表
self.item_list = []
def __str__(self):
# Python 能夠自動的將一對括號內部的代碼連接在一起
return ("戶型:%s\n總面積:%.2f[剩餘:%.2f]\n傢俱:%s"
% (self.house_type, self.area,
self.free_area, self.item_list))
def add_item(self, item):
print("要添加 %s" % item)
# 1. 判斷傢俱的面積
if item.area > self.free_area:
print("%s 的面積太大了,無法添加" % item.name)
return
# 2. 將傢俱的名稱添加到列表中
self.item_list.append(item.name)
# 3. 計算剩餘面積
self.free_area -= item.area
# 1. 創建傢俱
bed = HouseItem("席夢思", 40)
chest = HouseItem("衣櫃", 2)
table = HouseItem("餐桌", 20)
print(bed)
print(chest)
print(table)
# 2. 創建房子對象
my_home = House("兩室一廳", 60)
my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)
print(my_home)
輸出:
10.私有屬性和方法
在定義屬性或方法時,在屬性名或者方法名前增加兩個下劃線,定義的就是私有屬性或方法。但是我們可以藉助這個類的其他非私有方法來訪問私有方法和屬性。
代碼:
class Women:
def __init__(self, name):
self.name = name
self.__age = 18
def __secret(self):
# 在對象的方法內部,是可以訪問對象的私有屬性的
print("%s 的年齡是 %d" % (self.name, self.__age))
def open_secret(self):
self.__secret()
xiaofang = Women("小芳")
xiaofang.open_secret()
# 私有屬性,在外界不能夠被直接訪問
# print(xiaofang.__age)
# 私有方法,同樣不允許在外界直接訪問
# xiaofang.__secret()
輸出:
也可以使用另外一種方法來訪問私有屬性和方法
代碼:
class Women:
def __init__(self, name):
self.name = name
self.__age = 18
def __secret(self):
# 在對象的方法內部,是可以訪問對象的私有屬性的
print("%s 的年齡是 %d" % (self.name, self.__age))
xiaofang = Women("小芳")
# 僞私有屬性,在外界不能夠被直接訪問
print(xiaofang._Women__age)
# 僞私有方法,同樣不允許在外界直接訪問
xiaofang._Women__secret()
輸出:
結束!下一章節講解面向對象的繼承、多態和接口。