摘要:面向?qū)ο缶幊讨镁幊淌鞘裁创蠹液?,作為小白,最近學(xué)習(xí)了很多編程的知識(shí),因?yàn)槟X容量有限,特此一一按照學(xué)習(xí)順序記錄下來,如果哪里有錯(cuò)誤,還請(qǐng)大神盡快指出,以免誤導(dǎo)他人。。。繼承也允許把一個(gè)派生類的對(duì)象作為一個(gè)基類對(duì)象對(duì)待。
Python面向?qū)ο缶幊讨?/b> OOP編程是什么
大家好,作為小白,最近學(xué)習(xí)了很多Python OOP編程的知識(shí),因?yàn)槟X容量有限,特此一一按照學(xué)習(xí)順序記錄下來,如果哪里有錯(cuò)誤,還請(qǐng)大神盡快指出,以免誤導(dǎo)他人。。。
首先讓我們簡(jiǎn)單了解一下何為面向?qū)ο缶幊蹋?/p>
把一組數(shù)據(jù)結(jié)構(gòu)和處理它們的方法組成對(duì)象(object),把相同行為的對(duì)象歸納為類(class),通過類的封裝(encapsulation)隱藏內(nèi)部細(xì)節(jié),通過繼承(inheritance)實(shí)現(xiàn)類的特化(specialization)和泛化(generalization),通過多態(tài)(polymorphism)實(shí)現(xiàn)基于對(duì)象類型的動(dòng)態(tài)分派。
這樣一說貌似有些復(fù)雜,簡(jiǎn)單來看的話可以參考下面的解釋:
常見概念一覽概念 | 解釋 |
---|---|
類(Class) | 用來描述具有相同的屬性和方法的對(duì)象的集合。它定義了該集合中每個(gè)對(duì)象所共有的屬性和方法。對(duì)象是類的實(shí)例 |
類變量 | 類變量在整個(gè)實(shí)例化的對(duì)象中是公用的。類變量定義在類中且在函數(shù)體之外。類變量通常不作為實(shí)例變量使用 |
數(shù)據(jù)成員 | 類變量或者實(shí)例變量, 用于處理類及其實(shí)例對(duì)象的相關(guān)的數(shù)據(jù) |
方法重寫 | 如果從父類繼承的方法不能滿足子類的需求,可以對(duì)其進(jìn)行改寫,這個(gè)過程叫方法的覆蓋(override),也稱為方法的重寫 |
局部變量 | 定義在方法中的變量,只作用于當(dāng)前實(shí)例的類 |
實(shí)例變量 | 在類的聲明中,屬性是用變量來表示的。這種變量就稱為實(shí)例變量,是在類聲明的內(nèi)部但是在類的其他成員方法之外聲明的 |
繼承 | 即一個(gè)派生類(derived class)繼承基類(base class)的字段和方法。繼承也允許把一個(gè)派生類的對(duì)象作為一個(gè)基類對(duì)象對(duì)待。例如,有這樣一個(gè)設(shè)計(jì):一個(gè)Dog類型的對(duì)象派生自Animal類,這是模擬"是一個(gè)(is-a)"關(guān)系(例圖,Dog是一個(gè)Animal) |
實(shí)例化 | 創(chuàng)建一個(gè)類的實(shí)例,類的具體對(duì)象 |
方法 | 類中定義的函數(shù) |
對(duì)象 | 通過類定義的數(shù)據(jù)結(jié)構(gòu)實(shí)例。對(duì)象包括兩個(gè)數(shù)據(jù)成員(類變量和實(shí)例變量)和方法 |
下面讓我們簡(jiǎn)單定義一個(gè)汽車類:
class Car: def __init__(self, color, model, year): self.color = color self.model = model self.year = year
這里我們創(chuàng)建了一個(gè)汽車類Car,它有三個(gè)公共屬性,分別是color(顏色),model(型號(hào)),year(生產(chǎn)年份)
創(chuàng)建實(shí)例對(duì)象,訪問屬性現(xiàn)在讓我們新建一個(gè)對(duì)象my_car:
my_car = Car("yellow", "beetle", 1967)
查看一下my_car的屬性
print(f" My {my_car.color} car {my_car.model} is made in {my_car.year}") # My yellow car beetle is made in 1967添加新屬性
我們想要給my_car添加一個(gè)新屬性wheels
my_car.wheels = 5 print(f"Wheels: {my_car.wheels}") # Wheels: 5
使用dir(my_car)可以讓我們確認(rèn)一下屬性是否存在:
dir(my_car) Out: ["__class__", "__delattr__", "__dict__", "__dir__", "__doc__", "__eq__", "__format__", "__ge__", "__getattribute__", "__gt__", "__hash__", "__init__", "__init_subclass__", "__le__", "__lt__", "__module__", "__ne__", "__new__", "__reduce__", "__reduce_ex__", "__repr__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "__weakref__", "color", "model", "wheels", <====已經(jīng)添加成功啦 "year"]類變量,修改類變量的值
在Python中,我們?cè)陬愅饴暶饕粋€(gè)類變量,下面讓我們修改一下Car類:
class Car: wheels = 0 def __init__(self, color, model, year): self.color = color self.model = model self.year = year
這樣的話,我們?cè)谡{(diào)用wheels這個(gè)變量時(shí),可以通過實(shí)例,或者直接調(diào)用Car.wheels:
my_car = Car("yellow", "beetle", 1967) print(f"My car is {my_car.color}") print(f"It has {Car.wheels} wheels") print(f"It has {my_car.wheels} wheels") Out: My car is yellow It has 0 wheels It has 0 wheels
這里需要注意一下,如果想要通過my_car.wheels =xxx來修改wheels的值,不會(huì)真正修改類變量wheels的值,我們來看一個(gè)具體的例子:
my_car = Car("yellow", "Beetle", "1966") my_other_car = Car("red", "corvette", "1999") print(f"My car is {my_car.color}") print(f"It has {my_car.wheels} wheels") print(f"My other car is {my_other_car.color}") print(f"It has {my_other_car.wheels} wheels") Out: My car is yellow It has 0 wheels My other car is red It has 0 wheels
我們首先創(chuàng)建兩個(gè)實(shí)例my_car 和my_other_car ,默認(rèn)的wheels=0,下面我們首先直接通過Car這個(gè)類來修改類變量的值:
# Change the class variable value Car.wheels = 4 print(f"My car has {my_car.wheels} wheels") print(f"My other car has {my_other_car.wheels} wheels") Out: My car has 4 wheels My other car has 4 wheels
可以看到這樣修改的話,Car類擁有的所有實(shí)例中的wheels值會(huì)被全部修改,如果我們通過my_other_car 來修改呢?
# Change the instance variable value for my_car my_car.wheels = 5 print(f"My car has {my_car.wheels} wheels") print(f"My other car has {my_other_car.wheels} wheels") Out: My car has 5 wheels My other car has 4 wheels
現(xiàn)在大家可以發(fā)現(xiàn)區(qū)別了,僅僅是修改了my_car中wheels的值,對(duì)類本身不會(huì)造成影響
私有和公有屬性在Python中的所有屬性都是public,可能有c++和java的同學(xué)覺得神奇,其實(shí)python最初規(guī)定了一種特殊的命名方式來區(qū)分public還是private,那就是下劃線_
我還是拿一樣的例子說明:
class Car: wheels = 0 def __init__(self, color, model, year): self.color = color self.model = model self.year = year self._cupholders = 6 my_car = Car("yellow", "Beetle", "1969") print(f"It was built in {my_car.year}") Out: It was built in 1969
這里Car類中的杯托 _cupholders就是“私有“屬性,為什么我這里加上了引號(hào),是因?yàn)镻ython只是名義上規(guī)定這種寫法,但是在實(shí)際訪問上沒啥卵用,依然可以直接用._cupholders來訪問:
my_car.year = 1966 print(f"It was built in {my_car.year}") print(f"It has {my_car._cupholders} cupholders.") Out: It was built in 1966 It has 6 cupholders.
后來Python決定使用雙下劃線__來替換單下劃線,這樣可以最大程度避免“意外訪問“,然而還是沒有卵用,再來展示一下新方案:
class Car: wheels = 0 def __init__(self, color, model, year): self.color = color self.model = model self.year = year self.__cupholders = 6
其實(shí)某種程度上,這回效果還是很明顯的,如果我們還像剛才一樣嘗試調(diào)用my_car.cupholders 會(huì)報(bào)錯(cuò):
my_car = Car("yellow", "Beetle", "1969") print(f"It was built in {my_car.year}") print(f"It has {my_car.__cupholders} cupholders.") Out: It was built in 1969 --------------------------------------------------------------------------- AttributeError Traceback (most recent call last)in 1 my_car = Car("yellow", "Beetle", "1969") 2 print(f"It was built in {my_car.year}") ----> 3 print(f"It has {my_car.__cupholders} cupholders.") AttributeError: "Car" object has no attribute "__cupholders"
這個(gè)錯(cuò)誤很有意思,為什么會(huì)說cupholders這個(gè)變量不存在呢 ? 因?yàn)楫?dāng)Python看到__ 時(shí),會(huì)自動(dòng)在cupholders前面補(bǔ)上一個(gè)下劃線_和所屬類名,也就是說,這里我們嘗試用my_car.__cupholders 來調(diào)用時(shí),Python默認(rèn)的正確寫法是
my_car._Car__cupholders,現(xiàn)在再試一下:
print(f"It has {my_car._Car__cupholders} cupholders") Out: It has 6 cupholders
看見沒,依然沒攔住。。。。
不過我個(gè)人認(rèn)為這種規(guī)定公有私有變量的方式也是好處多多,這里就仁者見仁,智者見智了~
就像剛剛提到的,Python所有的東西都是公有的,我們可以隨意的新增,修改,甚至刪除變量:
my_car = Car("yellow", "beetle", 1969) print(f"My car was built in {my_car.year}") my_car.year = 2003 print(f"It was built in {my_car.year}") del my_car.year print(f"It was built in {my_car.year}") Out: My car was built in 1969 It was built in 2003 --------------------------------------------------------------------------- AttributeError Traceback (most recent call last)in 6 7 del my_car.year ----> 8 print(f"It was built in {my_car.year}") AttributeError: "Car" object has no attribute "year"
那我們?nèi)绾尾拍芸刂茖傩缘脑L問權(quán)限呢?Python給出的答案是裝飾器 @property,這個(gè)類似于Java中的setter和getter,現(xiàn)在我們?cè)囋嚕?/p>
class Car: def __init__(self, color, model, year): self.color = color self.model = model self.year = year self._voltage = 12 @property def voltage(self): return self._voltage @voltage.setter def voltage(self, volts): print("Warning: this can cause problems!") self._voltage = volts @voltage.deleter def voltage(self): print("Warning: the radio will stop working!") del self._voltage
我們新增了voltage(電壓)這個(gè)屬性,并用property來控制外部的訪問權(quán)限,這里我們定義了三個(gè)方法,利用setter方法可以改變voltage的值,利用getter方法來訪問,利用deleter方法實(shí)現(xiàn)刪除,接下來讓我們新建實(shí)例來看看propert是如何工作的:
my_car = Car("yellow", "beetle", 1969) print(f"My car uses {my_car.voltage} volts") my_car.voltage = 6 print(f"My car now uses {my_car.voltage} volts") del my_car.voltage Out: My car uses 12 volts Warning: this can cause problems! My car now uses 6 volts Warning: the radio will stop working!
可以發(fā)現(xiàn),我們這里直接使用.voltage 而不是._voltage,這樣就告訴python去使用property裝飾的方法,我們可以通過使用@.setter and @.deleter 使屬性變?yōu)閞ead-only(只讀),從而保護(hù)voltage不會(huì)被隨意修改和刪除
總結(jié)今天主要總結(jié)了OOP編程中的類,對(duì)象,屬性,公有私有屬性,訪問權(quán)限這些基礎(chǔ)概念,下一篇文章會(huì)進(jìn)一步深入,如果本文有哪些語言使用不當(dāng),希望大家可以指出,讓我們一起進(jìn)步!
我之前的一些文章已經(jīng)放到了Github上,如果感興趣的朋友可以去看看,鏈接如下:
Python 精品練習(xí)題100道
Python 實(shí)用技巧匯總
Python Pandas教程
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/45174.html
摘要:面向?qū)ο缶幊?,?jiǎn)稱,是一種程序設(shè)計(jì)思想。面向過程與面向?qū)ο竺嫦蜻^程的程序設(shè)計(jì)把函數(shù)作為程序的基本單元。以上是在計(jì)算機(jī)世界里認(rèn)識(shí)面向?qū)ο蠛兔嫦蜻^程,接下來給大家舉個(gè)生活中的例子就拿你早上想吃雞蛋灌餅為例。 面向?qū)ο缶幊獭狾bject Oriented Programming,簡(jiǎn)稱OOP,是一種程序設(shè)計(jì)思想。OOP把對(duì)象作為程序的基本單元,一個(gè)對(duì)象包含了數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)。 面向過程 ...
摘要:時(shí)代,如果需要手動(dòng)繼承,如多態(tài)多態(tài)是指,不同的子類對(duì)象調(diào)用相同的父類方法,會(huì)產(chǎn)生多態(tài)多樣結(jié)果的編程特性。 參考:黑馬程序員教程 - Python基礎(chǔ) 面向?qū)ο?OOP三大特性,且三個(gè)特性是有順序的: 封裝 繼承 多態(tài) 封裝 指的就是把現(xiàn)實(shí)世界的事務(wù),封裝、抽象成編程里的對(duì)象,包括各種屬性和方法。這個(gè)一般都很簡(jiǎn)單,不需要多講。 唯一要注意的就是:推薦從小往大開始封裝、開發(fā)類。比如手槍...
摘要:一面向?qū)ο缶幊?。是一門面向?qū)ο蟮木幊陶Z言,通過對(duì)象實(shí)現(xiàn)對(duì)方法的調(diào)用。面向過程的程序設(shè)計(jì)把計(jì)算機(jī)程序視為一系列的命令集合,即一組函數(shù)的順序執(zhí)行。對(duì)于面向?qū)ο笳Z言,重要的概念是類和實(shí)例。 一、preface 面向?qū)ο缶幊蘋OP:object oriented programming。OOP把對(duì)象作為程序的基本單元,一個(gè)對(duì)象包含了數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)。Python是一門面向?qū)ο蟮木幊陶Z言,...
摘要:反對(duì)者在某些領(lǐng)域?qū)Υ擞枰苑裾J(rèn)。下面再引用一段來自維基百科中關(guān)于的歷史。類的更嚴(yán)格的定義是由某種特定的元數(shù)據(jù)所組成的內(nèi)聚的包。類還可以有運(yùn)行時(shí)表示形式元對(duì)象,它為操作與類相關(guān)的元數(shù)據(jù)提供了運(yùn)行時(shí)支持。 在開始部分,請(qǐng)看官非常非常耐心地閱讀下面幾個(gè)枯燥的術(shù)語解釋,本來這不符合本教程的風(fēng)格,但是,請(qǐng)看官諒解,因?yàn)榱形粚硪欢ㄒ喿x枯燥的東西的。這些枯燥的屬于解釋,均來自維基百科。 1、問題...
摘要:新的稱為子類,而被繼承的稱為基類父類或超類。繼承最大的好處是子類獲得了父類的全部功能。在繼承關(guān)系中,如果一個(gè)實(shí)例的數(shù)據(jù)類型是某個(gè)子類,那它的數(shù)據(jù)類型也可以被看做是父類。 在上一篇中我們介紹了模塊和數(shù)據(jù)結(jié)構(gòu),這一篇將介紹面向?qū)ο缶幊獭? 面向?qū)ο缶幊?面向?qū)ο缶幊獭狾bject Oriented Programming,簡(jiǎn)稱 OOP,是一種程序設(shè)計(jì)思想。OOP 把對(duì)象作為程序的基本單元...
閱讀 2949·2019-08-30 15:44
閱讀 2039·2019-08-29 13:59
閱讀 2899·2019-08-29 12:29
閱讀 1145·2019-08-26 13:57
閱讀 3264·2019-08-26 13:45
閱讀 3395·2019-08-26 10:28
閱讀 979·2019-08-26 10:18
閱讀 1753·2019-08-23 16:52