您好,登錄后才能下訂單哦!
概述
面向?qū)ο缶幊蹋∣bject Oriented Programming,即 OOP),是一種程序設(shè)計思想,比面向過程編程更加靈活,更易擴展。
Python 在設(shè)計的時候就是按照面向?qū)ο缶幊痰乃枷朐O(shè)計的,像我們前面學(xué)過的各種數(shù)據(jù)類型,如字符串、列表、字典等都是一個個對象,它們都具有各自的屬性和行為。
面向?qū)ο缶幊叹褪菍⒖陀^存在的事物,總結(jié)提煉出它們各自的屬性與行為,然后通過編程的方法形成一個模版(即類),我們就可以根據(jù)這個模版創(chuàng)建出一個個實際的、可使用的對象(即類的實例)。
特性
封裝
封裝是面向?qū)ο缶幊痰暮诵乃枷?,即將對象具有的,且是我們需要的屬性和行為封裝起來,編寫成一個模版(即類),而在使用的時候只需要事先根據(jù)定義好的模版創(chuàng)建出其實例即可,使用過程中無需知道其屬性和行為是如何實現(xiàn)的,只需要知道它們能夠完成哪些功能即可。
繼承
舉個例子,我們創(chuàng)建一個四邊形的類,它具有四條邊,四個角這兩個特性,計算周長、面積這兩個行為;當我們基于這個四邊形的類,再創(chuàng)建一個平行四邊形的類,則該平行四邊形也將自動具有四條邊、四個角的特性和計算周長、面積的行為。
繼承就是實現(xiàn)重復(fù)利用的重要手段,子類可以繼承父類的屬性和行為。
多態(tài)
子類繼承于父類,那么子類也就擁有了父類的特性和行為,但是因為子類相對于父類而言是一個全新的類,所以它也擁有自己獨特的特性和行為,這就是多態(tài)。例如,平行四邊形繼承于四邊形,同樣擁有四條邊和四個角同時,它也有自己的特性,如對邊相等,對角相等。
類和實例
面向?qū)ο缶幊痰乃枷刖褪怯么a描述客觀世界中的物體,但是不可能將每個物體都用代碼描述一遍,這不現(xiàn)實,所以引入了類。類就是一系列具有相同特性和行為的物體的集合,描述物體的模版。當我們需要一個該物體的具體實例時,只需要按照這個模版就能創(chuàng)建一個新的物體實例,然后對其進行操作。
如何定義類
在 Python 編程中,使用關(guān)鍵字 class 定義類,
class Triangle:
pass
Triangle(三角形)是類的名字。
創(chuàng)建類的實例
定義好一個類,并不能供我們直接使用,而是需要創(chuàng)建一個它的實例之后,才可以使用其內(nèi)部的屬性和行為。
就像國家發(fā)行鈔票,會制作的一個鈔票模版,然后根據(jù)這個模版印刷出一張張的紙幣,這些紙幣就是該鈔票模版的實例,市場上流通的也是這些紙幣,不會是這個鈔票模版。所以,當我們要使用這個類的時候,就需要將其實例化,創(chuàng)建一個它的實例,
class Triangle:
pass
if name == "main":
triangle = Triangle()
triangle 就是類 Triangle的實例,也是這個實例的名稱。
init() 方法
在 Python 中,如果在定義一個類的時候,不自定義該方法,則編譯器會自動幫我們指定一個。但是如果想在創(chuàng)建類的實例的時候,為它的屬性賦予一些參數(shù),就需要自定義一個 init() 方法。
該方法用于在創(chuàng)建類的實例時,傳入必要的屬性。它的第一個參數(shù)必須是 self ,代表實例本身,
class Triangle:
def init(self, base, height)
self.base = base
self.height = height
if name == "main":
triangle = Triangle(4, 5)
這樣就給 Triangle 這個類定義了一個 init() 方法,在創(chuàng)建其實例的時候,必須傳入除 self 以外的所有參數(shù)。
屬性
屬性指類中的變量,包括類的屬性和實例屬性,它們定義的位置不同。
類的屬性
類的屬性定義在類中(實例方法之外),所有類的實例都可以訪問類的屬性。
class Triangle:
triangle_amount = 0
def __init__(self, base, height):
self.base = base
self.height = height
Triangle.triangle_amount += 1
if name == "main":
triangle_1 = Triangle(4, 5)
triangle_2 = Triangle(12, 5)
print(Triangle.triangle_amount)
print(triangle_1.triangle_amount)
類的屬性可以通過類名直接訪問,也可以通過類的實例訪問。
類的屬性不僅僅只能在定義類的時候定義,也可以在類的定義之外動態(tài)添加,
class Triangle:
triangle_amount = 0
def __init__(self, base, height):
self.base = base
self.height = height
Triangle.triangle_amount += 1
if name == "main":
triangle_1 = Triangle(4, 5)
triangle_2 = Triangle(12, 5)
Triangle.triangle_number = "001"
print(triangle_1.triangle_number)
print(triangle_2.triangle_number)
實例屬性
實例屬性是指在類的方法中定義的屬性(變量),只能被類的實例使用。而且,改變一個實例的屬性并不會影響其他實例,
class Triangle:
def init(self, base, height):
self.base = base
self.height = height
def print_base(self):
print(self.base)
def print_height(self):
print(self.height)
if name == "main":
triangle_1 = Triangle(12, 5)
triangle_2 = Triangle(19, 7)
triangle_1.print_base()
triangle_1.print_height()
triangle_1.base = 20
triangle_1.height = 10
triangle_1.print_base()
triangle_1.print_height()
triangle_2.print_base()
triangle_2.print_height()
在 init() 方法中,base 和 height 就是實例屬性,當創(chuàng)建 triangle_1 和 triangle_2 兩個三角形的時候分別給它們的 base 和 height 屬性賦了值。當改變 triangle_1 的屬性后,并沒有影響 triangle_2 的屬性值。
方法
每個對象都有其獨有的行為,在面向?qū)ο缶幊讨邪堰@些行為稱為方法,也就是面向過程編程中的函數(shù),但是有些微差別。
方法需要在定義類的時候一起定義,這樣類的實例就可以使用這些方法。定義方法和定義函數(shù)相似,不過方法必須包含一個 self 參數(shù),且必須放在第一位,
class Triangle:
def init(self, base, height):
self.base = base
self.height = height
def compute_area(self)
area = self.base * self.height / 2
函數(shù)用于實現(xiàn)某個獨立的功能,而實例方法是實現(xiàn)類(類的實例)的一個特性行為,只有類的實例可以使用它。
訪問限制
可以在類的外部訪問創(chuàng)建類的時候定義的屬性和方法,如果我們不想某些屬性或方法在類的外部被直接訪問(使用),可以給它們加上限制。不受限制的代碼如下:
class Triangle:
description = "我是這個類最原始的描述"
def __init__(self):
pass
def print_base_height(self):
print("我是這個三角形的底和高")
if name == "main":
print(Triangle.description)
triangle = Triangle()
triangle.print_base_height()
受保護的
以單下劃線開頭的屬性和方法是受保護的(protected)
class Triangle:
_description = "我是這個類最原始的描述"
_number = 0
def __init__(self):
self._base = "我是底"
print(self._base)
pass
def _print_base_height(self):
print("我是這個三角形的底和高")
if name == "main":
print(Triangle._description)
triangle = Triangle()
triangle._print_base_height()
print(triangle._base)
print(str(Triangle._number))
Triangle._number += 99
print(str(Triangle._number))
私有的
以雙下劃線開頭的屬性和方法是私有的(private),
class Triangle:
description = "我是這個類最原始的描述"
number = 0
def __init__(self):
self.__base = "我是底"
print(self.__base)
pass
def __print_base_height(self):
print("我是這個三角形的底和高")
def modify_description(self):
print(Triangle.__description)
Triangle.__description = "我是在類定義之內(nèi)修改的描述"
print(Triangle.__description)
if name == "main":
triangle = Triangle()
triangle.modify_description()
print(triangle._Triangle__description)
triangle._Triangle__print_base_height()
print(str(triangle._Triangle__number))
triangle._Triangle__number += 99
print(str(triangle._Triangle__number))
通過上面的代碼可以看出,通過 類的實例名._類名__xxx 的方式依然可以訪問私有的屬性和方法。
所以,在 Python 編程中,訪問限制并不能真正的限制你,總是可以通過別的某種方法突破限制,全憑自覺吧。
@property
通過 @property(裝飾器)可以將一個方法轉(zhuǎn)換為一個用于計算的特殊屬性,可以通過方法名(無需在方法名后面加上小括號)直接訪問該方法,
class Triangle:
def init(self, base, height):
self.base = base
self.height = height
@property
def compute_area(self):
return self.base * self.height / 2
if name == "main":
triangle = Triangle(12, 5)
print(triangle.compute_area)
繼承
繼承是面向?qū)ο缶幊痰囊粋€重要特性,被繼承的類稱為父類(或基類),繼承父類的類稱為子類(或派生類),子類具有父類除了私有屬性和方法以外的所有屬性和方法。繼承使得子類不再需要重新定義父類中已有的屬性和方法,只要拿過來直接用就可以了。
class Triangle:
def init(self, base, height):
self.base = base
self.height = height
@property
def compute_area(self):
return self.base * self.height / 2
class IsoscelesTriangle(Triangle):
pass
if name == "main":
isosceless_triangle = IsoscelesTriangle(12, 5)
print(isosceless_triangle.compute_area)
多態(tài)
如果是僅僅只能繼承父類的一切,那和父類還有什么兩樣?所以,子類除了可以繼承父類,還可以根據(jù)自己的特點增加自己的特性,修改從父類集成的特性,也就是面向?qū)ο缶幊痰亩鄳B(tài)。
class Rectangle:
def init(self, length, width):
self.length = length
self.width = width
@property
def area(self):
return self.length * self.width
@property
def perimeter(self):
return (self.length + self.width) * 2
class Square(Rectangle):
def init(self, length, width=0):
self.length = length
self.width = width
@property
def area(self):
return self.length ** 2
@property
def perimeter(self):
return self.length * 4
if name == "main":
rectangle = Rectangle(12, 5)
print(str(rectangle.area))
print(str(rectangle.perimeter))
square = Square(12)
print(str(square.area))
print(str(square.perimeter))
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。