04-python中的面向對象編程-01
概念引入
首先面向對象編程 不是在python 中有,幾乎大部分的高級編程語言都是支持的。 面向對象編程 是一種編程思想,是一種寫代碼的一種思維, 這裏 我們就以python語言爲例 來介紹 什麼是 面向對象編程 。
說到面向對象編程,就要提到面向過程編程 這是兩種編程思想。
面向過程 一般比較好理解,比如 我要實現一個功能,函數 。我首先 就要知道 我第一步 要做什麼,第二步做什麼 ,第三步做什麼,最後做什麼。
舉個例子:
比如我每天早上 去上班,我需要怎麼做呢?
第一 我要早早的先起牀,雖然我很懶,但是還是要起來。
第二 我要開始準備洗漱吃飯,
第三 我要去公交站臺。
第四步 等車,然後上車,
第五步 等指定站臺下車,步行到公司。
上面的思考問題的過程 其實 就是 面向過程一種思考模型, 按照步驟,一步 一步 最後完成 任務。
根據上面的思考,我們很容易寫出來 下面的代碼,清晰流暢。沒有任何問題。
# -*- coding: utf-8 -*-
import time
def go_office():
"""
比如我每天早上 去上班,我需要怎麼做呢?
第一 我要早早的先起牀,雖然我很懶,但是還是要起來。
第二 我要開始準備洗漱吃飯,
第三 我要去公交站臺。
第四步 等車,然後上車,
第五步 等指定站臺下車,步行到公司。
:return:
"""
print("我要早早的先起牀,雖然我很懶,但是還是要起來。")
time.sleep(1)
print("我要開始準備洗漱吃飯")
time.sleep(1)
print("我要去公交站臺。")
time.sleep(1)
print("等車,然後上車,")
time.sleep(1)
print("等指定站臺下車,步行到公司")
time.sleep(1)
if __name__ == '__main__':
go_office()
下面 來談談 面向對象 的思考方式 ,
在面向對象的編程思想的方式中 ,是這樣 思考的,我要去 到公司,我要怎麼做呢? 我需要有一輛車,我啓動車開車到公司。 或者 是 我需要有輛 公交車,帶我去公司去。 就這樣, 這就是面向對象 要思考的事情。
這裏 可以 把 我, 公司, 一輛車 , 公交車 這樣的名詞 ,在面向對象的世界裏面,這些都可以稱作一個叫類
的一個東西。
在python中如何定義一個類呢?
只要一個關鍵字 class
定義一個類
class Frank:
pass
上面的方法,定義了一個類 ,只是這個類就只有一個類名。好,現在 開始 按照面向對象的方法,來實現 去公司這個操作。
# -*- coding: utf-8 -*-
import time
class Car:
"""
出租車
"""
pass
def start(self):
time.sleep(1)
print("開車 去公司")
class Bus:
"""
公交車
"""
def start(self):
time.sleep(1)
print("做公交 去公司")
class Frank:
bus = Bus()
pass
@classmethod
def go_office(cls):
cls.bus.start()
if __name__ == '__main__':
# go_office()
Frank.go_office()
這裏 我定義了一個類 Car, Bus 這些類中 有一個方法 start , 還有一個Frank 類 這個裏面 有一個 Bus 類創建的一個對象bus
, 然後 在 Frank 類中 有一個 go_office 方法, 這個方法 完成了 Frank 去公司這個操作。
這個例子可能 沒有那麼恰當 來解釋清楚 面向對象 和麪向過程 這兩種編程思想 的 好處,或者缺點。
我在來舉個例子 我感覺相對好一些來說明這個問題。
那麼如何面向對象編程呢?
從 面向過程
到 面向對象
的一些思考過程?
假如 現在要求一個四邊形的周長,知道四個點座標,來求 這個四邊形的周長
只要把 四個點 兩個點之間的距離 算出來,然後相加,就可以了, 假設有以下 4個點 ,
在 square 的list 中,好 很快 就能寫好了代碼。如下
square = [(1, 1), (1, 2), (2, 2), (2, 1)]
def distance(p1, p2):
return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
def perimeter(polygon): # polygon 多邊形
perimeter = 0
points = polygon + [polygon[0]]
# print(f'{points}')
for i in range(len(polygon)):
print(f"{i},{points[i]},{points[i+1]}")
perimeter += distance(points[i], points[i+1])
return perimeter
perimeter(square) # 4
我們用面向 對象思想來思考
首先思考 求周長, 首先 計算四個點之間的距離, 然後 把邊長加起來就可以了。 那我們 可不可以,把點這個 東西 抽象 出來作爲一個類呢?
記住面對對象 編程 首先 要思考 在完成一個任務裏面 可以抽象出一個類
,然後用這個類 來完成 對數據的操作。
首先 我想把 點 這個 東西 可以抽象一個類,這個類裏面有 一個座標(x,y)
, 然後 可以通過這個類 來計算 另一個點的距離, 其實 就是 剛剛寫的 求距離的函數 。
我們還要 思考 求周長 能不能 想辦法 抽象一個類出來呢, 如果你想不到 也沒有關係,其實可以抽象 一個 多邊形的類, 然後 由這個多邊形 來計算周長,這樣計算周長 就被封裝在 類中了。
看下面的例子:
import math
class Point:
def __init__(self, x=0, y=0):
self.reset(x, y)
def move(self, x, y):
self.x = x
self.y = y
def reset(self, x, y):
self.x = x
self.y = y
def cal_distance(self, point):
"""
求兩點之間的距離
:param point:
:return:
"""
return math.sqrt((self.x - point.x) ** 2 + (self.y - point.y) ** 2)
class Polygon:
def __init__(self):
self.vertices = []
def add_point(self, point):
self.vertices.append(point)
def perimeter(self):
perimeter = 0
points = self.vertices + [self.vertices[0]]
for i in range(len(self.vertices)):
perimeter += points[i].cal_distance(points[i + 1])
return perimeter
if __name__ == '__main__':
square = Polygon()
square.add_point(Point(1, 1))
square.add_point(Point(1, 2))
square.add_point(Point(2, 2))
square.add_point(Point(2, 1))
ret = square.perimeter()
print(f"{ret}")
Polygon 通過這個類 ,然後添加 point , 然後添加 perimeter 這個方法 。 這樣寫 其實 就是 把 面向過程 寫的 代碼 放在了 一個類中, 然後通過類中的一些 數據,然後通過實現方法來操作數據,最後 獲取結果。
上面的結果 和上面面向過程的結果是一樣的。
你可能有疑問了? 面向對象的寫法 ,把代碼寫多了,沒有什麼呀?
其實不然, 其實在寫代碼,最終要給你人來看的, 後期要考慮維護成本。面向對象 的方式 首先 本身 就是具有描述行爲的,比如 Point
類,本身代表了一個點,大家一個就能知道。
但是 如果按照面向過程中 定義一個list square = [(1, 1), (1, 2), (2, 2), (2, 1)]
我相信 如果過了一個月後 ,你再看 square 這個東西,你可能不理解 我這裏寫的 元祖 裏面的數字 代表什麼意思?
看到了嗎, 這就是區別,在面向對象的思想中 代碼的可讀性 更強,可維護更強。
python3中面向對象編程
通過上面的例子 你應該大概理解了面向對象思考過程。 對象 其實就是一個封裝, 對象 是 數據和行爲的一個集合,對象中的屬性 我一般喜歡叫數據,方法 就是用來來操作這些數據的。
對象 本身的行爲 叫 方法 。
以我舉個例子, 比如我現在 要封裝一個我這個類,我有一個方法 叫做飯,吃飯,還有一個方法叫游泳 。
我中還有一些屬性, 姓名 ,身高,體重。
class Person:
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight
person = Person(name='frank', height=165, weight=55)
這裏 就是通過 Person
來創建了一個對象 , Person(name='frank', height=165, weight=55)
這裏 的意思 就是 調用了 __init__
方法 , 把三個屬性拷貝到了 person 的對象上面。
>>> person = Person(name='frank', height=165, weight=55)
>>> person.name
'frank'
>>> person.height
165
>>> person.weight
55
現在 你已經掌握瞭如何創建一個對象的方法。 你可能 會有疑問 爲啥 __init__()
方法裏面 爲啥會有self 參數,其實這個self 就是你將來 賦給的那個對象,這個self 你就可以這樣理解。 這裏 self 就相當於 你創建每創建一個新的對象,它就會指向這個對象。
person = Person(name='frank', height=165, weight=55)
比如這裏 self 就代指 person .
現在 來繼續實現一些方法
這裏只是舉例, 假設 eat 後 我體重會重, 游泳後,我體重會變輕。
class Person:
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight
def cook(self):
print(f"{self.name} is cooking")
def eat(self):
print(f"{self.name} is eating")
self.weight = self.weight + 2
def swim(self):
print(f"{self.name} is swimming")
self.weight = self.weight - 1
>>> person.name,person.height,person.weight
('frank', 165, 55)
>>> person.cook()
frank is cooking
>>> person.eat()
frank is eating
>>> person.weight
57
>>> person.eat()
frank is eating
>>> person.weight
59
>>> person.swim()
frank is swimming
>>> person.swim()
frank is swimming
>>> person.weight
57
看上面的例子 ,當我吃飯的 時候 體重就會變重,游泳體重就會下降。這就是 面向對象 編程。
類和對象的關係,區別是什麼?
類 是用來 描述對象的。 它們就像用來創造對象的藍圖。 類相當於 是一個 模板 這個模板來創建一個對象。
類是對象的一個抽象,對象 就是一個具體的
類,對象 就是由類 創建出來的。
class Person:
def __init__(self, name):
self.name = name
p = Person(name='frank')
lily = Person(name='lily')
上面 定義Person 類,然後 由類 生成一個對象 p 和一個對象 lily 。 這一個對象 創建了兩個對象。
程序員 就是 每天都要面對很多對象,整天和這些對象打交道。
對象隨時有,只要你肯new。
你看程序員 沒有對象是不可能的,每天都和很多對象打交道。
簡單總結:
我們通過方法 來實現不同的功能,屬性 就是 對象中的一些 數據, 通過 方法 可以操作這些數據,來完成一些操作 這就是面向對象編程。
面向對象編程的好處 有哪些呢?
第一代碼比較清晰,通過名稱 大概知道 是做什麼。
第二 代碼 複用性更強, 因爲 類是可以繼承的。(以後會講到)
第三 更加 方便的維護 一些比較大的項目。
總結
這篇 文章 主要簡單介紹了面向對象的基礎知識,瞭解面向對象思想。之後我會在寫一下 更好的使用面向對象的思想 進行編程 。 好了,有了這篇文章,你可以嘗試一下 把一些函數 變成一個類中的方法,改成面向對象的代碼。然後來感受一下,不同的編程方法。