python物件導向程式設計基礎
先看看物件導向-----在現如今的程式語言中大部分都已經具備了完善的物件導向思想。例如C++、java這兩大主流程式語言。這兩個是現如今使用量最大,且將物件導向發揮到極致的語言。
python面向的物件最主要的類--而python類中最主要包括 欄位、方法、屬性
先來看看如何建立一個python類
class Pager:
def __init__(self, current_page):
# 使用者當前請求的頁碼(第一頁、第二頁...)
self.current_page = current_page
# 每頁預設顯示10條資料
self.per_items = 10
def start(self):
val = (self.current_page - 1) * self.per_items
return val
def end(self):
val = self.current_page * self.per_items
return val
tips: python中一個類只能有一個建構函式存在。定義多個構造方法時,例項化類只例項化最後的構造方法,
即後面的構造方法會覆蓋前面的構造方法,並且需要更具最後一個構造方法的形式進行例項化
接下來分片看看類中的三大將
欄位分為------普通欄位 和 靜態欄位
普通欄位-----(普通欄位屬於類物件擁有)
靜態欄位-----(靜態欄位屬於當前類,靜態欄位在記憶體中只儲存一份;普通欄位在每個物件中都要儲存一份)
class province:
#靜態欄位
country = "China"
def __init__(self,name):
#普通欄位
self.name = name
#訪問普通欄位方法
obj = province("shan'xi")
print(obj.name)
#訪問靜態欄位方法
print(province.country)
方法分為------普通方法、靜態方法 和 類方法
普通方法:由物件呼叫;至少一個self引數;執行普通方法時,自動將呼叫該方法的物件賦值給self;
類方法: 由類呼叫;至少一個cls引數;執行類方法時,自動將呼叫該方法的類複製給cls;
靜態方法:由類呼叫;無預設引數
class testFun:
#建構函式
def __init__(self,name):
self.name = name
def orderFunc(self):
"""普通方法,至少一個self引數 """
print("普通方法")
@classmethod
def classFunc(cls):
"""類方法,至少一個cls引數 """
print("類方法")
@staticmethod
def staticmethod():
"""靜態方法,沒有預設引數 """
print("靜態方法")
#1.呼叫普通方法
test = testFun("xi'an") #建立物件
test.orderFunc()
#2.呼叫類方法
testFun.classFunc()
#3.呼叫靜態方法
testFun.staticmethod()
屬性------類的普通方法的變種
1:在普通方法的基礎上新增 @property 裝飾器;
2:屬性僅有一個self引數;
3:呼叫時,無需括號
屬性存在意義:訪問屬性時可以製造出和訪問欄位完全相同的假象
class testProtertyFun:
#建構函式
def __init__(self,name):
self.name = name
#定義屬性
@property
def propertyFunc(self):
"""屬性方法,至少一個self引數 """
print("屬性方法")
test = testProtertyFun("xi'an")
#呼叫屬性
test.propertyFunc
再來看幾個案例,看看屬性和方法的區別到底在哪一塊
#對某一個數值進行改變,計算其開始與結束後的值。
class Pager:
def __init__(self, current_):
# 使用者當前請求的頁碼(第一頁、第二頁...)
self.current_ = current_
# 每頁預設顯示10條資料
self.per_items = 10
@property
def start(self):
val = (self.current_ - 1) * self.per_items
return val
@property
def end(self):
val = self.current_ * self.per_items
return val
# ############### 呼叫 ###############
p = Pager(1)
p.start #就是起始值,即:m
p.end #就是結束值,即:n
屬性兩種定義方式(裝飾器模式、靜態欄位)
裝飾器方式:在類的普通方法上應用@property裝飾器
tips:Python中的類有經典類和新式類,新式類的屬性比經典類的屬性豐富。( 如果類繼object,那麼該類是新式類 )
經典類,具有一種@property裝飾器
class Goods:
@property
def price(self):
return "wupeiqi"
obj = Goods()
# 自動執行 @property 修飾的 price 方法,並獲取方法的返回值
result = obj.price
新式類,具有三種@property裝飾器
#新式類,具有三種@property裝飾器
class NewerPropertyClass:
@property
def Func1(self):
print("@property")
@property
def Func2(self):
pass
#設定屬性裝飾器時,被設定的setter deleter必須有一個被property修飾的函式
@Func2.setter
def Func2(self,value):
newvalue = value
print("@property.setter")
@Func2.deleter
def Func3(self):
print("@property.deleter")
obj = NewerPropertyClass()
obj.Func1 # 自動執行 @property 修飾的 Func1 方法,並獲取方法的返回值
obj.Func2 = 123 # 自動執行 @price.setter 修飾的 Func2 方法,並將 123 賦值給方法的引數
del obj.Func3 # 自動執行 @price.deleter 修飾的 Func3 方法
tips:綜上新式類會將屬性設定為對同一個操作分為:獲取、修改、刪除. 而Setter必須有個引數,保證可以傳入引數值。且setter、deleter的函式必須有一個被@property修飾的函式
靜態欄位模式-------當使用靜態欄位的方式建立屬性時,經典類和新式類無區別
class Foo:
def get_bar(self):
return 'wupeiqi'
#靜態欄位模式
BAR = property(get_bar)
obj = Foo()
# 自動呼叫get_bar方法,並獲取方法的返回值
reuslt = obj.BAR
print(reuslt)
property的構造方法中有個四個引數
第一個引數是方法名,呼叫 物件.屬性 時自動觸發執行方法
第二個引數是方法名,呼叫 物件.屬性 = XXX 時自動觸發執行方法
第三個引數是方法名,呼叫 del 物件.屬性 時自動觸發執行方法
第四個引數是字串,呼叫 物件.屬性.__doc__ ,此引數是該屬性的描述資訊
看這個例子:
class TestClass:
def get_bar(self):
print("get_bar")
return ("wupeiqi")
# *必須兩個引數
def set_bar(self, value):
print("set_bar:" + value)
return ('set value' + value)
def del_bar(self):
value = 0
print("del_bar:" + str(value))
return (value)
BAR = property(get_bar,set_bar,del_bar,"description...")
obj = TestClass()
obj.BAR # 自動呼叫第一個引數中定義的方法:get_bar
obj.BAR = "alex" # 自動呼叫第二個引數中定義的方法:set_bar方法,並將“alex”當作引數傳入
print(obj.BAR.__doc__)#呼叫 物件.屬性.__doc__ ,
# 此引數是該屬性的描述資訊(此處呼叫需要放在del obj.BAR這句之前)
del obj.BAR # 自動呼叫第三個引數中定義的方法:del_bar方法
類成員的修飾符 (公有成員---私有成員)
公有成員,在任何地方都能訪問
私有成員,只有在類的內部才能方法;私有成員命名時,前兩個字元是下劃線 __(特殊成員除外,例如:__init__、__call__、__dict__等)
如果想要強制訪問私有欄位,可以透過 【物件._類名__私有欄位明 】訪問(如:obj._C__foo),不建議強制訪問私有成員。
靜態欄位:
公有靜態欄位:類可以訪問;類內部可以訪問;派生類中可以訪問
私有靜態欄位:僅類內部可以訪問
訪問類的公有成員欄位
class CClass:
name = "公有靜態欄位"
def func(self):
print (CClass.name)
class DClass(CClass): #DClass繼承CClass
def show(self):
print (CClass.name)
CClass.name # 類訪問
obj = CClass()
obj.func() # 類內部可以訪問
obj_son = DClass()
obj_son.show() # 派生類中可以訪問
訪問類的公有成員欄位
class CClass:
__name = "私有靜態欄位"
def func(self):
print (CClass.name)
class DClass(CClass): #DClass繼承CClass
def show(self):
print (CClass.name)
CClass.name # 類訪問==> 錯誤
obj = CClass()
obj.func() # 類內部可以訪問 ==> 正確
obj_son = DClass()
obj_son.show() # 派生類中可以訪問 ==> 錯誤
普通欄位
公有普通欄位:物件可以訪問;類內部可以訪問;派生類中可以訪問
私有普通欄位:僅類內部可以訪問;
訪問類的公有欄位
class AClass:
def __init__(self):
self.foo="公有欄位"
def func(self):
print (self.foo) # 類內部訪問
class BClass(AClass):
def show(self):
print (self.foo) #派生類中訪問
obj = AClass()
obj.foo # 透過物件訪問
obj.func() # 類內部訪問
obj_son = BClass();
obj_son.show() # 派生類中訪問
class AClass:
def __init__(self):
self.__foo = "私有欄位"
def func(self):
print (self.foo) # 類內部訪問
class BClass(AClass):
def show(self):
print (self.foo) #派生類中訪問
obj = AClass()
obj.__foo # 透過物件訪問 ==> 錯誤
obj.func() # 類內部訪問 ==> 正確
obj_son = BClass();
obj_son.show() # 派生類中訪問 ==> 錯誤
方法、屬性的訪問於上述方式相似,即:私有成員只能在類內部使用;---非要訪問私有屬性的話,可以透過 物件._類__屬性名
還有幾個類的特殊欄位需要清楚的
1. __doc__ 表示類的描述資訊
class Foo:
""" 描述類資訊,這是用於看片的神奇 """
def func(self):
pass
print (Foo.__doc__)
#輸出:類的描述資訊
2. __module__ 和 __class__
__module__ 表示當前操作的物件在那個模組
__class__ 表示當前操作的物件的類是什麼
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class C:
def __init__(self):
self.name = 'wupeiqi'
from lib.aa import C
obj = C()
print (obj.__module__) # 輸出 lib.aa,即:輸出模組
print (obj.__class__) # 輸出 lib.aa.C,即:輸出類
3. __init__
# 構造方法,透過類建立物件時,自動觸發執行。
class Foo:
def __init__(self, name):
self.name = name
self.age = 18
obj = Foo('wupeiqi') # 自動執行類中的 __init__ 方法
4. __del__
析構方法,當物件在記憶體中被釋放時,自動觸發執行。
#注:此方法一般無須定義,因為Python是一門高階語言,程式設計師在使用時無需關心記憶體的分配和釋放,因為此工作都是交給Python直譯器來執行,
#所以,解構函式的呼叫是由直譯器在進行垃圾回收時自動觸發執行的。
class Foo:
def __del__(self):
pass5. __call__
# 物件後面加括號,觸發執行。
#注:構造方法的執行是由建立物件觸發的,即:物件 = 類名() ;而對於 __call__ 方法的執行是由物件後加括號觸發的,即:物件() 或者 類()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print ('__call__')
obj = Foo() # 執行 __init__
obj() # 執行 __call__
6. __dict__
# 類或物件中的所有成員
#上文中我們知道:類的普通欄位屬於物件;類中的靜態欄位和方法等屬於類,即
class Province:
country = 'China'
def __init__(self, name, count):
self.name = name
self.count = count
def func(self, *args, **kwargs):
print ('func')
# 獲取類的成員,即:靜態欄位、方法、
print (Province.__dict__)
# 輸出:{'country': 'China', '__module__': '__main__', 'func': , '__init__': , '__doc__': None}
obj1 = Province('HeBei',10000)
print (obj1.__dict__)
# 獲取 物件obj1 的成員
# 輸出:{'count': 10000, 'name': 'HeBei'}
obj2 = Province('HeNan', 3888)
print (obj2.__dict__)
# 獲取 物件obj1 的成員
# 輸出:{'count': 3888, 'name': 'HeNan'}
7. __str__
# 如果一個類中定義了__str__方法,那麼在列印 物件 時,預設輸出該方法的返回值。
class Foo:
def __str__(self):
return 'wupeiqi'
obj = Foo()
print (obj)
# 輸出:wupeiqi
8、__getitem__、__setitem__、__delitem__
#用於索引操作,如字典。以上分別表示獲取、設定、刪除資料
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):
def __getitem__(self, key):
print ('__getitem__',key)
def __setitem__(self, key, value):
print ('__setitem__',key,value)
def __delitem__(self, key):
print ('__delitem__',key)
obj = Foo()
result = obj['k1'] # 自動觸發執行 __getitem__
obj['k2'] = 'wupeiqi' # 自動觸發執行 __setitem__
del obj['k1'] # 自動觸發執行 __delitem__
9、__getslice__、__setslice__、__delslice__
# 該三個方法用於分片操作,如:列表
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):
def __getslice__(self, i, j):
print ('__getslice__',i,j)
def __setslice__(self, i, j, sequence):
print ('__setslice__',i,j)
def __delslice__(self, i, j):
print ('__delslice__',i,j)
obj = Foo()
obj[-1:1] # 自動觸發執行 __getslice__
obj[0:1] = [11,22,33,44] # 自動觸發執行 __setslice__
del obj[0:2] # 自動觸發執行 __delslice__
10. __iter__
#用於迭代器,之所以列表、字典、元組可以進行for迴圈,是因為型別內部定義了 __iter__
#第一步
class Foo(object):
pass
obj = Foo()
for i in obj:
print (i)
# 報錯:TypeError: 'Foo' object is not iterable
#第二步
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):
def __iter__(self):
pass
obj = Foo()
for i in obj:
print (i)
# 報錯:TypeError: iter() returned non-iterator of type 'NoneType'
#第三步 鄭州做人流多少錢
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):
def __init__(self, sq):
self.sq = sq
def __iter__(self):
return iter(self.sq)
obj = Foo([11,22,33,44])
for i in obj:
print (i)
#以上步驟可以看出,for迴圈迭代的其實是 iter([11,22,33,44]) ,所以執行流程可以變更為:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
obj = iter([11,22,33,44])
for i in obj:
print (i)
#For迴圈語法內部
#!/usr/bin/env python
# -*- coding:utf-8 -*-
obj = iter([11,22,33,44])
while True:
val = obj.next()
print (val)
#11. __new__ 和 __metaclass__
#閱讀以下程式碼:
class Foo(object):
def __init__(self):
passobj = Foo() # obj是透過Foo類例項化的物件
#上述程式碼中,obj 是透過 Foo 類例項化的物件,其實,不僅 obj 是一個物件,Foo類本身也是一個物件,因為在Python中一切事物都是物件。
#如果按照一切事物都是物件的理論:obj物件是透過執行Foo類的構造方法建立,那麼Foo類物件應該也是透過執行某個類的 構造方法 建立。
print (type(obj)) # 輸出: 表示,obj 物件由Foo類建立
print (type(Foo)) # 輸出: 表示,Foo類物件由 type 類建立
#所以,obj物件是Foo類的一個例項,Foo類物件是 type 類的一個例項,即:Foo類物件 是透過type類的構造方法建立。
#那麼,建立類就可以有兩種方式:
#a). 普通方式
class Foo(object):
def func(self):
print ('hello wupeiqi')
#b).特殊方式(type類的建構函式)
def func(self):
print ('hello wupeiqi')
Foo = type('Foo',(object,), {'func': func})
#type第一個引數:類名
#type第二個引數:當前類的基類
#type第三個引數:類的成員
# 類 是由 type 類例項化產生
#那麼問題來了,類預設是由 type 類例項化產生,type類中如何實現的建立類?類又是如何建立物件?
#答:類中有一個屬性 __metaclass__,其用來表示該類由 誰 來例項化建立,所以,我們可以為 __metaclass__ 設定一個type類的派生類,從而檢視 類 建立的過程。
class MyType(type):
def __init__(self, what, bases=None, dict=None):
super(MyType, self).__init__(what, bases, dict)
def __call__(self, *args, **kwargs):
obj = self.__new__(self, *args, **kwargs)
self.__init__(obj)
class Foo(object):
__metaclass__ = MyType
def __init__(self, name):
self.name = name
def __new__(cls, *args, **kwargs):
return object.__new__(cls, *args, **kwargs)
# 第一階段:直譯器從上到下執行程式碼建立Foo類
# 第二階段:透過Foo類建立obj物件
obj = Foo()
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2667024/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- python基礎(物件導向程式設計)Python物件程式設計
- [.net 物件導向程式設計基礎] (2) 關於物件導向程式設計物件程式設計
- Python基礎入門(6)- 物件導向程式設計Python物件程式設計
- [.net 物件導向程式設計基礎] (16) 介面物件程式設計
- [.net 物件導向程式設計基礎] (22) 事件物件程式設計事件
- [.net 物件導向程式設計基礎] (19) LINQ基礎物件程式設計
- [.net 物件導向程式設計基礎] (13) 物件導向三大特性——多型物件程式設計多型
- [.net 物件導向程式設計基礎] (12) 物件導向三大特性——繼承物件程式設計繼承
- [.net 物件導向程式設計基礎] (11) 物件導向三大特性——封裝物件程式設計封裝
- python物件導向[基礎]Python物件
- [.net 物件導向程式設計深入](36)Redis——基礎物件程式設計Redis
- [.net 物件導向程式設計基礎] (1) 開篇物件程式設計
- [.net 物件導向程式設計基礎] (18) 泛型物件程式設計泛型
- [.net 物件導向程式設計基礎] (15) 抽象類物件程式設計抽象
- [.net 物件導向程式設計基礎] (14) 重構物件程式設計
- [.net 物件導向程式設計基礎] (21) 委託物件程式設計
- Python物件導向程式設計Python物件程式設計
- Python 物件導向程式設計Python物件程式設計
- Python物件導向基礎:設定物件屬性Python物件
- [.net 物件導向程式設計基礎] (20) LINQ使用物件程式設計
- [.net 物件導向程式設計基礎] (23) 結束語物件程式設計
- C++ 遞迴與物件導向程式設計基礎C++遞迴物件程式設計
- 面向Python,物件導向(基礎)Python物件
- Python基礎之物件導向Python物件
- Python OOP 物件導向程式設計PythonOOP物件程式設計
- Python - 物件導向程式設計 - @propertyPython物件程式設計
- Python - 物件導向程式設計 - super()Python物件程式設計
- python技能--物件導向程式設計Python物件程式設計
- Python物件導向程式設計(1)Python物件程式設計
- Python之物件導向程式設計Python物件程式設計
- [.net 物件導向程式設計基礎] (8) 基礎中的基礎——修飾符物件程式設計
- 程式設計基礎·Java學習筆記·物件導向(下)程式設計Java筆記物件
- [.net 物件導向程式設計基礎] (17) 陣列與集合物件程式設計陣列
- [.net 物件導向程式設計基礎] (5) 基礎中的基礎——變數和常量物件程式設計變數
- [.net 物件導向程式設計基礎] (3) 基礎中的基礎——資料型別物件程式設計資料型別
- 物件導向程式設計物件程式設計
- 物件導向基礎物件
- 史上最全 Python 物件導向程式設計Python物件程式設計