本系列主要學(xué)習Python的基本使用和語法知識,后續(xù)可能會圍繞著AI學(xué)習展開数尿。
Python3 (1) Python語言的簡介
Python3 (2) Python語法基礎(chǔ)
Python3 (3) Python函數(shù)
Python3 (4) Python高級特性
Python3(5) Python 函數(shù)式編程
Python3(6) Python 模塊
Python3(7) Python 面向?qū)ο缶幊?/a>
面向?qū)ο缶幊淌且环N編程思想仑性,主要與面向過程編程比較學(xué)習,在經(jīng)歷了 C++砌创、C#虏缸、Java 的面向?qū)ο蟮膶W(xué)習,相信學(xué)習 Python 的面向?qū)ο髸屪约簩?OOP 有更深的理解嫩实。
面向?qū)ο笈c面向過程的比較
面向?qū)ο缶幊獭狾bject Oriented Programming,簡稱OOP窥岩,是一種程序設(shè)計思想甲献。OOP把對象作為程序的基本單元,一個對象包含了數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)颂翼。
面向過程編程——面向過程的程序設(shè)計把計算機程序視為一系列的命令集合晃洒,即一組函數(shù)的順序執(zhí)行慨灭。為了簡化程序設(shè)計,面向過程把函數(shù)繼續(xù)切分為子函數(shù)球及,即把大塊函數(shù)通過切割成小塊函數(shù)來降低系統(tǒng)的復(fù)雜度氧骤。
#面向?qū)ο?class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
def print_age(self):
print('%s: %s' % (self.name, self.age))
bart = Student('張三', 15)
lisa = Student('李四', 16)
bart.print_age()
lisa.print_age()
#面向過程
def print_age(std):
print('%s: %s' % (std['name'], std['age']))
std1 = { 'name': '張三', 'age': 17 }
std2 = { 'name': '李四', 'age': 18 }
print_age(std1)
print_age(std2)
輸出結(jié)果:
張三: 15
李四: 16
張三: 17
李四: 18
在Python中,所有數(shù)據(jù)類型都可以視為對象吃引,當然也可以自定義對象筹陵。Student
的實例就是一個個對象。
類與實例
類與實例與java相同镊尺,就是普通的 Class 和 Class的實例化 ,類可以看成一個模板朦佩,可以實例出不用的對象。
下面我們分析一下上面面向?qū)ο蟮?示例:
-
class Student(object)
Student 類的定義庐氮,繼承自object -
def __init__(self, name, age)
含義跟java構(gòu)造函數(shù)相同语稠,創(chuàng)建了實例時可以綁定一些數(shù)據(jù)。 - 創(chuàng)建實例 在類名后+
()
即可弄砍,沒有new
關(guān)鍵字跟kotlin
使用一致仙畦。 - 在類中定義的函數(shù)有個共同的特點就是第一個參數(shù)是
self
。 - Python允許對實例變量綁定任何數(shù)據(jù)音婶,與靜態(tài)語言不同慨畸。
數(shù)據(jù)封裝
數(shù)據(jù)的封裝,其實就是定義一些函數(shù)桃熄,來實現(xiàn)特定的功能先口,類的實例調(diào)用對應(yīng)的方法就可以實現(xiàn)對應(yīng)的功能,不需要關(guān)注函數(shù)的具體實現(xiàn)和數(shù)據(jù)的具體傳遞瞳收。
訪問限制
在前面我們已經(jīng)學(xué)習過碉京,除特殊的變量,以
_xxx
和__xxx
命名的變量是私有的螟深,我們可以通過設(shè)置get谐宙、set來訪問私有變量。這就體現(xiàn)了代碼的封裝性界弧,可以使我們的程序更加的安全凡蜻,規(guī)范,健壯垢箕。但是不是設(shè)置成私有的就一定不能被外界直接訪問只是不符合編碼規(guī)則划栓,例如:__name
python解釋器會編譯成_Student__name
不同的版本也可能有不同的編譯方式,所以盡量不要這樣使用条获。
繼承
OOP程序設(shè)計中忠荞,當我們定義一個class的時候,可以從某個現(xiàn)有的class繼承,新的class稱為子類(Subclass)委煤,而被繼承的class稱為基類堂油、父類或超類(Base class、Super class)碧绞。繼承的作用就是子類可以繼承到父類的所有功能府框。也可以重寫對應(yīng)的功能。
多態(tài)
多態(tài)的概念其實是在繼承讥邻,重寫的應(yīng)用迫靖,我們可以通過繼承派生出不同的子類,重寫子類的具體實現(xiàn)计维,在調(diào)用時用他們的共同基類做參數(shù)袜香,這樣基類派生出的各種子類都可以傳遞進去,系統(tǒng)會根據(jù)傳入的具體類型實現(xiàn)具體的功能鲫惶。
開閉原則
多態(tài)的設(shè)計采用的就是開閉原則:調(diào)用方只管調(diào)用蜈首,不管細節(jié),不需要任何更改欠母。
1. 對擴展開放:允許新增子類欢策;
2. 對修改封閉:不需要修改用基類作為參數(shù)的方法
鴨子類型
這是Python強大之處,決定了繼承不像靜態(tài)語言那樣是必須的赏淌。
鴨子類型:不要求嚴格的繼承體系踩寇,一個對象只要“看起來像鴨子,走起路來像鴨子”六水,那它就可以被看做是鴨子俺孙,具體講就是傳入的對象,有需要的方法就可以傳入并使用掷贾,不需要嚴格的來自它的繼承睛榄。
下面通過一個示例來演示繼承、多態(tài)想帅、鴨子類型:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#基類
class Car(object):
def run(self):
return "car running...."
#子類
class SmallCar(Car):
def run(self):
return 'small car running...'
#子類
class BigCar(Car):
def run(self):
return 'bag car running...'
#子類的子類
class PoliceCar(SmallCar):
def run(self):
return 'police car running...'
def stop(self):
return 'police car stopped...'
#鴨子類型
class SchoolCar(object):
def run(self):
return 'school car running...'
#方法的調(diào)用
def look(car):
print('I look a ',car.run())
#多態(tài)的使用場景
look(Car())
look(SmallCar())
look(BigCar())
look(PoliceCar())
#鴨子類型的調(diào)用
look(SchoolCar())
輸出結(jié)果:
I look a car running....
I look a small car running...
I look a bag car running...
I look a police car running...
I look a school car running...
獲取對象信息
python中內(nèi)置了各種函數(shù)场靴,方便我們獲取對象的信息。如
type()
港准、isinstance()
旨剥、dir()
、getattr()
浅缸、setattr()
以及hasattr()
下面是對獲取對象信息 內(nèi)置函數(shù)的使用示例:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#基類
import types
class Car(object):
weight = 2000
def run(self):
return "car running...."
#子類
class SmallCar(Car):
def run(self):
return 'small car running...'
#子類
class BigCar(Car):
def run(self):
return 'bag car running...'
#子類的子類
class PoliceCar(SmallCar):
def run(self):
return 'police car running...'
def stop(self):
return 'police car stopped...'
#鴨子類型
class SchoolCar(object):
def run(self):
return 'school car running...'
#方法的調(diào)用
def look(car):
print('I look a ',car.run())
#type()的使用
s = SmallCar()
s1 = SmallCar()
p = PoliceCar()
c = Car()
print(type(s),type(s1))
print(type(s)==SmallCar)
print(type(s)==type(c))
print("---------------------------")
#type的高級使用
print(type(look)==types.FunctionType)
print(type(abs)==types.BuiltinFunctionType)
print(type(lambda x: x)==types.LambdaType)
print(type((x for x in range(10)))==types.GeneratorType)
print("---------------------------")
#isinstance()的使用
print(isinstance(s,SmallCar))
print(isinstance(s,Car))
print(isinstance(s,PoliceCar))
print(isinstance(s,(SmallCar,PoliceCar)))#括號中是或的關(guān)系
print("---------------------------")
#dir() 的使用
print(dir(p))
print("---------------------------")
#getattr()轨帜、setattr()、hasattr() 的使用
#屬性
print(hasattr(p,'weight'))
print(getattr(p,'weight'))
setattr(p,'weight',3000)
print(getattr(p,'weight'))
print(getattr(p,'height',404))
#方法
print(hasattr(p,'run'))
print(getattr(p,'run'))
setattr(p,'run',123456)
print(getattr(p,'run'))
#attr正確用法,去阻止鴨式類型之外的對象
def look(car):
if hasattr(car, 'run'):
print('I look a ', car.run())
return None
class Ambulance(object):
def shop(self):
return 'ambulance car stopped...'
print(look(Ambulance()))
輸出結(jié)果:
<class '__main__.SmallCar'> <class '__main__.SmallCar'>
True
False
---------------------------
True
True
True
True
---------------------------
True
True
False
True
---------------------------
['__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__', 'run', 'stop', 'weight']
---------------------------
True
2000
3000
404
True
<bound method PoliceCar.run of <__main__.PoliceCar object at 0x0000020D453CC0F0>>
123456
None
實例屬性和類屬性
這里主要強調(diào)一下實例屬性與類屬性的區(qū)別衩椒,由于Python是動態(tài)語言阵谚,根據(jù)類創(chuàng)建的實例可以任意綁定屬性蚕礼。包括類的屬性
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Car(object):
name = 'car'
def __init__(self, name,weight):
self.name = name
self.weight = weight
c = Car('small car',2000);
print(Car.name)
print(c.name)
print(c.weight)
del c.name,c.weight
print(c.name)
print(getattr(c,'weight',3000))
輸出結(jié)果:
car
small car
2000
car
3000
從上面可以看出如果刪除了實例的屬性烟具,實例的屬性會自動訪問類的屬性梢什。所以一定要注意實例的屬性名與類的屬性名不要重復(fù)。