
⑤Python面向對象程式設計
- Python面向對象程式設計
- 1.資料封裝、繼承和多态是面向對象的三大特點。
- 2.面向對象程式設計
- 3.類與執行個體
- 4.資料成員的通路控制
- 5.繼承
- 6. 多态
- 7. 擷取對象資訊
- 使用isinstance()
- 使用dir()
- 8. 執行個體屬性和類屬性
- 練習
Python面向對象程式設計
1.資料封裝、繼承和多态是面向對象的三大特點。
2.面向對象程式設計
一種程式設計思想,把對象作為程式的基本單元,一個對象包含了資料和操作資料的函數。面向對象的程式設計把計算機程式視為一組對象的集合,而每個對象都可以接受其他對象發過來的消息,并處理這些消息,計算機程式的執行就是一系列消息在各個對象之間傳遞。
3.類與執行個體
class Student(object):
def __init__(self,name,age):
self.name=name
self.age=age
def print_info():
print(self.name,self.age)
執行個體
bart = Student()
Michael = Student('Michael',22)
Michael.print_info()
4.資料成員的通路控制
在Class内部,可以有屬性和方法,而外部代碼可以通過直接調用執行個體變量的方法來操作資料,這樣就隐藏了内部複雜邏輯。
如果想要讓内部屬性不被外部通路,可以把屬性的名稱前加上兩個下劃線
__
,在Python中,執行個體的變量名如果以
__
開頭,就變成了一個私有變量private,隻有内部可以通路,外部不能通路。
class student(object):
def __init__(self,name,score):
self.__name = name
self.__score = score
def print_info(self):
print(self.__name,self.__score)
def get_name():
return self.__name
def get_score():
return self.__score
def set_name(name):
self.__name = name
def set_score(score):
self.__score =
但是實際上還是可以通路的,Python并沒有任何機制防止對私有成員的通路,但是原則上私有成員不可以直接進行通路,全憑自覺。
5.繼承
class Animal(object):
def run(self):
print('Animal is running...')
class Dog(Animal):
def run(self):
print('Dog is running')
a = Animal()
d = Dog()
a.run()
b.run()
子類會繼承父類的方法,并可以對其進行重寫。
6. 多态
多态實際上為了解決動态編譯的問題,Python自動支援多态,并不需要C++中的
virtual
關鍵字。
def run_twice(animal):
animal.run()
animal.run()
>>> run_twice(Animal())
Animal is running...
Animal is running...
>>> run_twice(Dog())
Dog is running...
Dog is running...
7. 擷取對象資訊
type()
>>> type(123)
<class 'int'>
>>> type('str')
<class 'str'>
>>> type(None)
<type(None) 'NoneType'>
>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False
判斷基本資料類型可以直接寫
int
,
str
等,但如果要判斷一個對象是否是函數怎麼辦?可以使用
types
子產品中定義的常量:
>>> import types
>>> def fn():
... pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True
使用isinstance()
對于class的繼承關系來說,使用
type()
就很不友善。我們要判斷class的類型,可以使用
isinstance()
函數。
我們回顧上次的例子,如果繼承關系是:
object -> Animal -> Dog ->
那麼,
isinstance()
就可以告訴我們,一個對象是否是某種類型。先建立3種類型的對象:
>>> a = Animal()
>>> d = Dog()
>>> h = Husky()
然後,判斷:
>>> isinstance(h, Husky)
True
能用
type()
判斷的基本類型也可以用
isinstance()
判斷:
>>> isinstance('a', str)
True
>>> isinstance(123, int)
True
>>> isinstance(b'a', bytes)
True
并且還可以判斷一個變量是否是某些類型中的一種,比如下面的代碼就可以判斷是否是list或者tuple:
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True
使用dir()
如果要獲得一個對象的所有屬性和方法,可以使用
dir()
函數,它傳回一個包含字元串的list,比如,獲得一個str對象的所有屬性和方法:
>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
類似
__xxx__
的屬性和方法在Python中都是有特殊用途的,比如
__len__
方法傳回長度。在Python中,如果你調用
len()
函數試圖擷取一個對象的長度,實際上,在
len()
函數内部,它自動去調用該對象的
__len__()
方法,是以,下面的代碼是等價的:
>>> len('ABC')
3
>>> 'ABC'.__len__()
3
我們自己寫的類,如果也想用
len(myObj)
的話,就自己寫一個
__len__()
方法:
>>> class MyDog(object):
... def __len__(self):
... return 100
...
>>> dog = MyDog()
>>> len(dog)
100
僅僅把屬性和方法列出來是不夠的,配合
getattr()
、
setattr()
以及
hasattr()
,我們可以直接操作一個對象的狀态:
>>> class MyObject(object):
... def __init__(self):
... self.x = 9
... def power(self):
... return self.x * self.x
...
>>> obj = MyObject()
緊接着,可以測試該對象的屬性:
>>> hasattr(obj, 'x') # 有屬性'x'嗎?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
False
>>> setattr(obj, 'y', 19) # 設定一個屬性'y'
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
True
>>> getattr(obj, 'y') # 擷取屬性'y'
19
>>> obj.y # 擷取屬性'y'
19
如果試圖擷取不存在的屬性,會抛出AttributeError的錯誤:
>>> getattr(obj, 'z') # 擷取屬性'z'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyObject' object has no attribute 'z'
可以傳入一個default參數,如果屬性不存在,就傳回預設值:
>>> getattr(obj, 'z', 404) # 擷取屬性'z',如果不存在,傳回預設值404
404
>>> hasattr(obj, 'power') # 有屬性'power'嗎?
True
>>> getattr(obj, 'power') # 擷取屬性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn = getattr(obj, 'power') # 擷取屬性'power'并指派到變量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 調用fn()與調用obj.power()是一樣的
81
8. 執行個體屬性和類屬性
class Student(object):
def __init__(self,name):
self.name = name
class Student1(object):
name = 'Student'#類屬性,對所有對象共享
練習
class Student(object):
count = 0
def __init__(self, name):
self.name = name
Student.count+=1