(四)面向物件程式設計
一、類和例項
1.
class Student(object):
pass
(object),表示該類是從哪個類繼承下來的,如果沒有合適的繼承類,就使用object類,這是所有類最終都會繼承的類。
2.建立例項是通過類名+()實現
3.
由於類可以起到模板的作用,因此,可以在建立例項的時候,把一些我們認為必須繫結的屬性強制填寫進去。通過定義一個特殊的__init__方法,在建立例項的時候,就把name,score等屬性綁上去:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
注意到__init__方法的第一個引數永遠是self,表示建立的例項本身,因此,在__init__方法內部,就可以把各種屬性繫結到self,因為self就指向建立的例項本身。
有了__init__方法,在建立例項的時候,就不能傳入空的引數了,必須傳入與__init__方法匹配的引數,但self不需要傳,Python直譯器自己會把例項變數傳進去:
>>> bart = Student('Bart Simpson', 59)
>>> bart.name
'Bart Simpson'
>>> bart.score
59
注意:Java中所有屬性都在首部羅列出來,其中有static修飾的屬性相當於類屬性,沒有static修飾的相當於例項屬性。
Python中在類中直接定義的是類屬性,通過__init__在建立例項的時候繫結 或 建立例項後再繫結 的屬性是例項屬性。
(在下文 五、例項屬性和類屬性 中解釋了Python中類屬性和例項屬性應該注意的地方)
4.
和靜態語言不同,Python允許對例項變數繫結任何資料,也就是說,對於兩個例項變數,雖然它們都是同一個類的不同例項,但擁有的變數名稱都可能不同:4.
>>> bart = Student('Bart Simpson', 59)
>>> lisa = Student('Lisa Simpson', 87)
>>> bart.age = 8
>>> bart.age
8
>>> lisa.age
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'
(為啥要這樣設計?優點?不容易造成混亂嗎?)
二、訪問限制
1.在Python中,例項的變數名如果以__開頭,就變成了一個私有變數(private)
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
2.在Python中,變數名類似__xxx__的,也就是以雙下劃線開頭,並且以雙下劃線結尾的,是特殊變數,特殊變數是可以直接訪問的,不是private變數,所以,不能用__name__、__score__這樣的變數名。
3._name,這樣的例項變數外部是可以訪問的,但是,按照約定俗成的規定,當你看到這樣的變數時,意思就是,“雖然我可以被訪問,但是,請把我視為私有變數,不要隨意訪問”。
4.Python本身沒有任何機制阻止你幹壞事,一切全靠自覺。(按套路出牌)
5.最後注意下面的這種錯誤寫法:
>>> bart = Student('Bart Simpson', 98)
>>> bart.get_name()
'Bart Simpson'
>>> bart.__name = 'New Name' # 設定__name變數!
>>> bart.__name
'New Name'
表面上看,外部程式碼“成功”地設定了__name變數,但實際上這個__name變數和class內部的__name變數不是一個變數!內部的__name變數已經被Python直譯器自動改成了_Student__name,而外部程式碼給bart新增了一個__name變數。
三、繼承和多型:(原理與Java中的相同,也有不同點)
1.理解多型:
(1)要有繼承 (2)要有方法的重寫 (3)父類引用指向子類物件
2.“開閉”原則:
對擴充套件開放:允許新增父類的子類;
對修改封閉:不需要修改依賴父類中的函式。(直接在子類中重寫即可)
3.靜態語言(Java) vs 動態語言(Python)
對於靜態語言(例如Java)來說,如果需要傳入Animal型別,則傳入的物件必須是Animal型別或者它的子類,否則,將無法呼叫run()方法。
對於Python這樣的動態語言來說,則不一定需要傳入Animal型別。我們只需要保證傳入的物件有一個run()方法就可以了:
class Timer(object):
def run(self):
print('Start...')
這就是動態語言的“鴨子型別”,它並不要求嚴格的繼承體系,一個物件只要“看起來像鴨子,走起路來像鴨子”,那它就可以被看做是鴨子。
Python的“file-like object“就是一種鴨子型別。對真正的檔案物件,它有一個read()方法,返回其內容。但是,許多物件,只要有read()方法,都被視為“file-like object“。許多函式接收的引數就是“file-like object“,你不一定要傳入真正的檔案物件,完全可以傳入任何實現了read()方法的物件。
(有點靈活到嚇人的設計)
四、獲取物件資訊
1.通過方法檢視物件內部的詳細資訊。(只有在不知道物件資訊的時候,我們才會去獲取物件資訊。)
2.一個實用的例子如下:
def readImage(fp):
if hasattr(fp, 'read'):
return readData(fp)
return None
假設我們希望從檔案流fp中讀取影象,我們首先要判斷該fp物件是否存在read方法,如果存在,則該物件是一個流,如果不存在,則無法讀取。hasattr()就派上了用場。
3.請注意,在Python這類動態語言中,根據鴨子型別,有read()方法,不代表該fp物件就是一個檔案流,它也可能是網路流,也可能是記憶體中的一個位元組流,但只要read()方法返回的是有效的影象資料,就不影響讀取影象的功能。
五、例項屬性和類屬性(java中只有類屬性吧)
1.給例項繫結屬性的方法是通過例項變數,或者通過self變數:
class Student(object):
def __init__(self, name):
self.name = name
s = Student('Bob')
s.score = 90
2.但是,如果Student類本身需要繫結一個屬性呢?可以直接在class中定義屬性,這種屬性是類屬性,歸Student類所有:
class Student(object):
name = 'Student'
當我們定義了一個類屬性後,這個屬性雖然歸類所有,但類的所有例項都可以訪問到。
3.>>> class Student(object):
... name = 'Student'
...
>>> s = Student() # 建立例項s
>>> print(s.name) # 列印name屬性,因為例項並沒有name屬性,所以會繼續查詢class的name屬性
Student
>>> print(Student.name) # 列印類的name屬性
Student
>>> s.name = 'Michael' # 給例項繫結name屬性
>>> print(s.name) # 由於例項屬性優先順序比類屬性高,因此,它會遮蔽掉類的name屬性
Michael
>>> print(Student.name) # 但是類屬性並未消失,用Student.name仍然可以訪問
Student
>>> del s.name # 如果刪除例項的name屬性
>>> print(s.name) # 再次呼叫s.name,由於例項的name屬性沒有找到,類的name屬性就顯示出來了
Student
從上面的例子可以看出,在編寫程式的時候,千萬不要把例項屬性和類屬性使用相同的名字,因為相同名稱的例項屬性將遮蔽掉類屬性,但是當你刪除例項屬性後,再使用相同的名稱,訪問到的將是類屬性。
相關推薦
(四)面向物件程式設計
一、類和例項 1. class Student(object): pass (object),表示該類是從哪個類繼承下來的,如果沒有合適的繼承類,就使用object類,這是所有
熟練使用Lua(四)面向物件:基於table的面向物件實現(2)
myluaootest.lua –1. 基本原理 local Cal = {} function Cal:New(o) o = o or {} setmetatable(o, self) self.__index = self return o end functio
熟練使用Lua(四)面向物件:基於table的面向物件實現(1)
轉:https://www.cnblogs.com/yao2yaoblog/p/6433553.html c++和java語言機制中本身帶有面向物件的內容,而lua設計的思想是超程式設計,沒有面向物件的實現。 但是利用lua的元表(matetable)機制,可以實現面向物件。要講清楚怎樣
JAVA基礎(42)---面向物件程式設計
面向物件 概述 類(class)和物件(object)是面向物件方法的核心概念。 類是對一類事物描述,是抽象的、概念上的定義;物件是實際存在的該類事物的每個個體,
PHP學習筆記(四)--面向物件
1、基本內容 注意事項: 無論是使用“$this->”還是使用“物件名->”格式,後面的變數是沒有$符號的,如$this->value; 通過“類名::常量”方式類訪問類常量的,如bastBall::Type; 在PHP中使用“垃圾回收”機制,不需要手動建
C++ 重點知識梳理(四) -------- 面向物件
五、面向物件 5.1 面向物件的三大特性 三大特性:封裝,繼承,多型 封裝:封裝是實現面向物件程式設計的第一步,封裝就是將資料或函式等集合在一個個的單元中(我們稱之為類)。封裝的意義在於保護或者防止程式碼(資料)被我們無意中破壞。 繼承:繼承主要實現重用程式碼,節
重拾Python學習(五)----------面向物件程式設計
本文參考:廖雪峰的官方網站:https://www.liaoxuefeng.com 類和例項 定義類是通過class關鍵字: class Student(object): pass __init__方法的第一個引數永遠是self,表示建立的例項本身
Scala程式設計(二)面向物件程式設計
Scala程式設計(二)面向物件程式設計 類 1.類的定義 //scala類 class Person { //用val定義的成員變數,只提供了getter方法 val id = "1234" //用var定義的成員變數,提供了setter和getter方法 va
Java基礎知識(四)——面向物件(下)
Java基礎知識(四)——面向物件(下) Java8的增強包裝類: 為了解決8種基本資料型別不能當成Object型別變數使用的問題。 JDK1.5提供了自動裝箱(Autoboxing)和自動拆箱·(AotuUnboxing)功能,所謂自動裝箱,就是可以把一個基本型別變數直接賦給對應的包裝
JavaSE(二)面向物件程式設計
面向物件程式設計 面向物件的概念 資料封裝 方法 構造方法Constructor 方法過載 Overload 繼承和多型 繼承 多型Polymorphic 抽象類和介面
軟體工程(四)面向物件技術
面向物件的看完了,其實物件很早就有了解過、這次只是加深了一些、下面就給大家精簡的敘述下、什麼是面向物件…… 什麼是面向物件? 面向物件=物件+類+繼承
【20171014】python_語言設計(8)面向物件程式設計
1.計算GPA,返回最高GPA同學 # 找到GPA最高的學生 class Student: def __init__(self, name, hours, qpoints): self.name = name self.hours = floa
php學習筆記(二)面向物件程式設計
public 公有的:本類,子類,外部物件都可以呼叫 protected 受保護的:本類 子類,可以執行,外部物件不可以呼叫 private 私有的:只能本類執行,子類與外部物件都不可呼叫 面向物件程式設計的三大特點 1)封閉性 封閉性,也可以稱為資訊隱藏。就是將一個
《簡明python教程》總結(五)-- 面向物件程式設計,輸入/輸出,異常
#!/usr/bin/python# Filename: inherit.pyclass SchoolMember:'''Represents any school member.'''def __init__(self, name, age):self.name = nameself.age = a
python學習筆記(二)面向物件程式設計
面向物件程式設計 self代表類的例項 python支援多重繼承 特殊方法def init(self,): 作用:在init方法內部,就可以把各種屬性繫結到self 前後分別有兩個下劃線
python學習筆記:(十四)面向物件
1、類(class): 用來描述具有相同的屬性和方法的物件的集合。它定義了該集合中每個物件所共有的屬性和方法 2、類變數: 類變數在整個例項化的物件中是公用的。類變數定義在類中且在函式體之外。類變數通常不作為例項變數使用。 3、資料成員: 類變數或者例項變數用於處理類及其例項物件的相關的
重拾Python學習(六)----------面向物件高階程式設計
本文參考:廖雪峰的官方網站:https://www.liaoxuefeng.com 使用__slots__ 果我們想要限制例項的屬性,比如,只允許對Student例項新增name和age屬性。 class Student(object): __slots
Java程式設計師從笨鳥到菜鳥之(三)面向物件之封裝,繼承,多型(下)
五:再談繼承 繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。物件的一個新類可以從現有的類中派生,這個過程稱為類繼承。新類繼承了原始類的特性,新類稱為原始類的派生類(子類),而原始類稱為新類的基類(父類)。派生類可以從它的基類那裡繼承方法和例項變數,並且類可以修改或增加
python(十二)面向物件程式設計、類
面向物件程式設計 面向物件--Object Oriented Programming,簡稱oop,是一種程式設計思想。在說面向物件之前,先說一下什麼是程式設計正規化,程式設計正規化你按照什麼方式來去程式設計,去實現一個功能。舉個例子,你要做飯,可以用電磁爐,也可以用煤氣灶。不同的程式設計正規化本質上代表對各
程式碼Python入門(十、面向物件程式設計實戰)
編寫模組#!/usr/bin/env python # -*- coding: UTF-8 -*- # 簡單遊戲模組 class Player(object): """A player for a game.""" def __init__(self, n