溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python面向?qū)ο缶幊讨R(shí)點(diǎn)總結(jié)

發(fā)布時(shí)間:2021-08-12 16:13:01 來源:億速云 閱讀:149 作者:chen 欄目:編程語言

這篇文章主要講解了“Python面向?qū)ο缶幊讨R(shí)點(diǎn)總結(jié)”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Python面向?qū)ο缶幊讨R(shí)點(diǎn)總結(jié)”吧!

面向?qū)ο缶幊毯秃瘮?shù)式編程(面向過程編程)都是程序設(shè)計(jì)的方法,不過稍有區(qū)別。

面向過程編程:

1. 導(dǎo)入各種外部庫

2. 設(shè)計(jì)各種全局變量

3. 寫一個(gè)函數(shù)完成某個(gè)功能

4. 寫一個(gè)函數(shù)完成某個(gè)功能

5. 寫一個(gè)函數(shù)完成某個(gè)功能

6.  寫一個(gè)函數(shù)完成某個(gè)功能

7. 寫一個(gè)函數(shù)完成某個(gè)功能

8. ......

9. 寫一個(gè)main函數(shù)作為程序入口

在多函數(shù)程序中,許多重要的數(shù)據(jù)被放置在全局?jǐn)?shù)據(jù)區(qū),這樣它們可以被所有的函數(shù)訪問。每個(gè)函數(shù)都可以具有它們自己的局部數(shù)據(jù),將某些功能代碼封裝到函數(shù)中,日后便無需重復(fù)編寫,僅調(diào)用函數(shù)即可。從代碼的組織形式來看就是根據(jù)業(yè)務(wù)邏輯從上到下壘代碼  。

面向?qū)ο缶幊蹋?/strong>

1. 導(dǎo)入各種外部庫

2. 設(shè)計(jì)各種全局變量

3. 決定你要的類

4. 給每個(gè)類提供完整的一組操作

5. 明確地使用繼承來表現(xiàn)不同類之間的共同點(diǎn)

6.  根據(jù)需要,決定是否寫一個(gè)main函數(shù)作為程序入口

面向?qū)ο缶幊讨?,將函?shù)和變量進(jìn)一步封裝成類,類才是程序的基本元素,它將數(shù)據(jù)和操作緊密地連結(jié)在一起,并保護(hù)數(shù)據(jù)不會(huì)被外界的函數(shù)意外地改變。類和和類的實(shí)例(也稱對(duì)象)是面向?qū)ο蟮暮诵母拍?,是和面向過程編程、函數(shù)式編程的根本區(qū)別。

并不是非要用面向?qū)ο缶幊?,要看你的程序怎么設(shè)計(jì)方便,但是就目前來說,基本上都是在使用面向?qū)ο缶幊獭?/p>

類的基本用法

面向?qū)ο笫峭ㄟ^定義class類來定義,這么說面向?qū)ο缶幊叹褪侵皇褂胏lass類,在class類中有封裝,繼承的功能,并且還可以構(gòu)造要傳入的參數(shù),方便控制。

案例一

import sys import time reload(sys) sys.setdefaultencoding('utf-8')  class studetn:     # 定義一個(gè)類名為studetn     def __init__(self,idx):     # 定義初始化構(gòu)造,這里使用init,還有別的屬性比如reversed,iter之類的         self.idx=idx         # 初始化變量,方便繼承     def runx(self):     # 定義運(yùn)行函數(shù),從上面繼承變量         print self.idx         # 打印出idx的值,或者做一些別的處理         time.sleep(1) a=studetn('a') a.runx() # 這是類的調(diào)用,一定要記得類的使用方法,首先傳入?yún)?shù),類賦值給一個(gè)變量a # 然后調(diào)用這個(gè)類下面定義的函數(shù)

一些專業(yè)術(shù)語概念,既然有面向?qū)ο缶幊踢@個(gè)高大上的定義了,自然要搭配一些高大上的概念。

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 類(Class): 用來描述具有相同屬性和方法的對(duì)象的集合。它定義了該集合中每個(gè)對(duì)象所共有的屬性和方法。其中的對(duì)象被稱作類的實(shí)例。

  3. 實(shí)例:也稱對(duì)象。通過類定義的初始化方法,賦予具體的值,成為一個(gè)”有血有肉的實(shí)體”。

  4. 實(shí)例化:創(chuàng)建類的實(shí)例的過程或操作。

  5. 實(shí)例變量:定義在實(shí)例中的變量,只作用于當(dāng)前實(shí)例。

  6. 類變量:類變量是所有實(shí)例公有的變量。類變量定義在類中,但在方法體之外。

  7. 數(shù)據(jù)成員:類變量、實(shí)例變量、方法、類方法、靜態(tài)方法和屬性等的統(tǒng)稱。

  8. 方法:類中定義的函數(shù)。

  9. 靜態(tài)方法:不需要實(shí)例化就可以由類執(zhí)行的方法

  10. 類方法:類方法是將類本身作為對(duì)象進(jìn)行操作的方法。

  11. 方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對(duì)父類的方法進(jìn)行改寫,這個(gè)過程也稱override。

  12. 封裝:將內(nèi)部實(shí)現(xiàn)包裹起來,對(duì)外透明,提供api接口進(jìn)行調(diào)用的機(jī)制

  13. 繼承:即一個(gè)派生類(derived class)繼承父類(base class)的變量和方法。

  14. 多態(tài):根據(jù)對(duì)象類型的不同以不同的方式進(jìn)行處理。

類與實(shí)例

# -*- coding: utf-8 -*- # @Time    : 2018/5/3 0003 17:02 # @Author  : Langzi # @Blog    : www.langzi.fun # @File    : 面向?qū)ο?.py # @Software: PyCharm import sys import time import requests reload(sys) sys.setdefaultencoding('utf-8')  class cc:     ccc = 'ccc'     # cc就是類名 如果想要繼承別的類 就class cc(threading) 意思就是從threading繼承     def __init__(self,a,b,c):         self.a=a         self.b=b         self.c=c         # 定義構(gòu)造的過程就是實(shí)例化     def runx(self):         print self.a*10         print self.b*5         print self.c*2     def runy(self):         print requests.get('http://www.langzi.fun').headers e = cc('AAA','CCC','EEE') e.runx() e.runy() # 這兩個(gè)就是調(diào)用類里面的方法 print e.c #實(shí)例變量指的是實(shí)例本身擁有的變量。每個(gè)實(shí)例的變量在內(nèi)存中都不一樣。 print e.ccc #類變量,在類里面找到定義的變量。 調(diào)用類的三種方法

調(diào)用類的三種方法

實(shí)例方法

# -*- coding: utf-8 -*- # @Time    : 2018/5/3 0003 17:16 # @Author  : Langzi # @Blog    : www.langzi.fun # @File    : 面向?qū)ο?.py # @Software: PyCharm import sys import time import requests reload(sys) sys.setdefaultencoding('utf-8')  class dd:     def __init__(self,url):         self.url=url     def runx(self):         print requests.get(self.url).status_code  a = dd('http://www.langzi.fun') a.runx() # 這種調(diào)用方法就是實(shí)例方法

靜態(tài)方法

靜態(tài)方法由類調(diào)用,無默認(rèn)參數(shù)。將實(shí)例方法參數(shù)中的self去掉,然后在方法定義上方加上@staticmethod,就成為靜態(tài)方法。它屬于類,和實(shí)例無關(guān)。建議只使用類名.靜態(tài)方法的調(diào)用方式。(雖然也可以使用實(shí)例名.靜態(tài)方法的方式調(diào)用)

# -*- coding: utf-8 -*- # @Time    : 2018/5/3 0003 17:21 # @Author  : Langzi # @Blog    : www.langzi.fun # @File    : 面向?qū)ο?.py # @Software: PyCharm import sys import requests reload(sys) sys.setdefaultencoding('utf-8') class ff:     @staticmethod     def runx():         print requests.get('http://www.langzi.fun').status_code ff.runx() #這里就直接調(diào)用了類的變量,只在類中運(yùn)行而不在實(shí)例中運(yùn)行的方法

經(jīng)常有一些跟類有關(guān)系的功能但在運(yùn)行時(shí)又不需要實(shí)例和類參與的情況下需要用到靜態(tài)方法. 比如更改環(huán)境變量或者修改其他類的屬性等能用到靜態(tài)方法.  這種情況可以直接用函數(shù)解決, 但這樣同樣會(huì)擴(kuò)散類內(nèi)部的代碼,造成維護(hù)困難。

類方法

類方法由類調(diào)用,采用@classmethod裝飾,至少傳入一個(gè)cls(代指類本身,類似self)參數(shù)。執(zhí)行類方法時(shí),自動(dòng)將調(diào)用該方法的類賦值給cls。建議只使用類名.類方法的調(diào)用方式。(雖然也可以使用實(shí)例名.類方法的方式調(diào)用)

實(shí)際案例

如果要構(gòu)造一個(gè)類,接受一個(gè)網(wǎng)站和這個(gè)網(wǎng)站的狀態(tài)碼,然后打印出來。就像這樣:

import sys import requests reload(sys) sys.setdefaultencoding('utf-8') class gg:     def __init__(self,url,stat):         self.url=url         self.stat=stat     def outer(self):         print self.url         print self.stat a = gg('langzi',200) a.outer()

這樣就是使用實(shí)例方法,雖然可以實(shí)現(xiàn),但是有的時(shí)候傳入的參數(shù)并不是(‘langzi’,200)這樣的格式,而是(‘langzi-200’)這樣的,那該怎么做?首先要把這個(gè)拆分,但是要使用實(shí)例方法實(shí)現(xiàn)起來很麻煩,這個(gè)時(shí)候就可以使用類方法。

# -*- coding: utf-8 -*- # @Time    : 2018/5/3 0003 17:27 # @Author  : Langzi # @Blog    : www.langzi.fun # @File    : 面向?qū)ο?.py # @Software: PyCharm import sys import requests reload(sys) sys.setdefaultencoding('utf-8') class gg:     url = 0     stat = 0     # 因?yàn)槭褂胏lassmethod后會(huì)傳入新的變量,所以一開始是需要自己先定義類變量     def __init__(self,url=0,stat=0):     # 這里按照正常的定義構(gòu)造函數(shù)         self.url=url         self.stat=stat     @classmethod     # 裝飾器,立馬執(zhí)行下面的函數(shù)     def split(cls,info):         # 這個(gè)函數(shù)接受兩個(gè)參數(shù),默認(rèn)的cls就是這個(gè)類的init函數(shù),info就是外面?zhèn)魅脒M(jìn)來的         url,stat=map(str,info.split('-'))         # 這里轉(zhuǎn)換成了格式化的結(jié)構(gòu)         data = cls(url,stat)         # 然后執(zhí)行這個(gè)類***個(gè)方法,這個(gè)類構(gòu)造函數(shù)需要傳入兩個(gè)參數(shù),于是就傳入了兩個(gè)參數(shù)         return data         # 這里就直接返回了函數(shù)結(jié)果     def outer(self):         print self.url         print self.stat  r = gg.split(('langzi-200')) r.outer() # 這里是調(diào)用類方法,與調(diào)用實(shí)例方法一樣

類的特性

封裝

封裝是指將數(shù)據(jù)與具體操作的實(shí)現(xiàn)代碼放在某個(gè)對(duì)象內(nèi)部,外部無法訪問。必須要先調(diào)用類的方法才能啟動(dòng)。

案例

class cc:     ccc = 'ccc'     # cc就是類名 如果想要繼承別的類 就class cc(threading) 意思就是從threading繼承     def __init__(self,a,b,c):         self.a=a         self.b=b         self.c=c print e.ccc #類變量,在類里面找到定義的變量。 print ccc # 這里會(huì)報(bào)錯(cuò),這就是封裝。類中的函數(shù)同理。

繼承

當(dāng)我們定義一個(gè)class的時(shí)候,可以從某個(gè)現(xiàn)有的class繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類(Base  class、Super class)。

比如,我們已經(jīng)編寫了一個(gè)名為Animal的class,有一個(gè)run()方法可以直接打?。?/p>

class Animal(object):     def run(self):         print 'Animal is running...'

當(dāng)我們需要編寫Dog和Cat類時(shí),就可以直接從Animal類繼承:

class Dog(Animal):     pass class Cat(Animal):     pass

繼承有什么好處?***的好處是子類獲得了父類的全部功能。由于Animial實(shí)現(xiàn)了run()方法,因此,Dog和Cat作為它的子類,什么事也沒干,就自動(dòng)擁有了run()方法:

dog = Dog() dog.run() cat = Cat() cat.run()

當(dāng)子類和父類都存在相同的run()方法時(shí),我們說,子類的run()覆蓋了父類的run(),在代碼運(yùn)行的時(shí)候,總是會(huì)調(diào)用子類的run()。這樣,我們就獲得了繼承的另一個(gè)好處:多態(tài)。

多態(tài)

要理解多態(tài)的好處,我們還需要再編寫一個(gè)函數(shù),這個(gè)函數(shù)接受一個(gè)Animal類型的變量:

def run_twice(animal):     animal.run()     animal.run()

當(dāng)我們傳入Animal的實(shí)例時(shí),run_twice()就打印出:

run_twice(Animal()) 運(yùn)行結(jié)果: Animal is running... Animal is running...

當(dāng)我們傳入Dog的實(shí)例時(shí),run_twice()就打印出:

run_twice(Dog()) 運(yùn)行結(jié)果: Dog is running... Dog is running...

當(dāng)我們傳入Cat的實(shí)例時(shí),run_twice()就打印出:

run_twice(Cat()) 運(yùn)行結(jié)果: Cat is running... Cat is running...

看上去沒啥意思,但是仔細(xì)想想,現(xiàn)在,如果我們再定義一個(gè)Tortoise類型,也從Animal派生:

class Tortoise(Animal):     def run(self):         print 'Tortoise is running slowly...'

當(dāng)我們調(diào)用run_twice()時(shí),傳入Tortoise的實(shí)例:

run_twice(Tortoise()) 運(yùn)行結(jié)果: Tortoise is running slowly... Tortoise is running slowly...

你會(huì)發(fā)現(xiàn),新增一個(gè)Animal的子類,不必對(duì)run_twice()做任何修改,實(shí)際上,任何依賴Animal作為參數(shù)的函數(shù)或者方法都可以不加修改地正常運(yùn)行,原因就在于多態(tài)。

多態(tài)的好處就是,當(dāng)我們需要傳入Dog、Cat、Tortoise……時(shí),我們只需要接收Animal類型就可以了,因?yàn)镈og、Cat、Tortoise……都是Animal類型,然后,按照Animal類型進(jìn)行操作即可。由于Animal類型有run()方法,因此,傳入的任意類型,只要是Animal類或者子類,就會(huì)自動(dòng)調(diào)用實(shí)際類型的run()方法,這就是多態(tài)的意思:

對(duì)于一個(gè)變量,我們只需要知道它是Animal類型,無需確切地知道它的子類型,就可以放心地調(diào)用run()方法,而具體調(diào)用的run()方法是作用在Animal、Dog、Cat還是Tortoise對(duì)象上,由運(yùn)行時(shí)該對(duì)象的確切類型決定,這就是多態(tài)真正的威力:調(diào)用方只管調(diào)用,不管細(xì)節(jié),而當(dāng)我們新增一種Animal的子類時(shí),只要確保run()方法編寫正確,不用管原來的代碼是如何調(diào)用的。這就是著名的“開閉”原則:

對(duì)擴(kuò)展開放:允許新增Animal子類;

對(duì)修改封閉:不需要修改依賴Animal類型的run_twice()等函數(shù)。

總結(jié):繼承可以把父類的所有功能都直接拿過來,這樣就不必重零做起,子類只需要新增自己特有的方法,也可以把父類不適合的方法覆蓋重寫;

有了繼承,才能有多態(tài)。在調(diào)用類實(shí)例方法的時(shí)候,盡量把變量視作父類類型,這樣,所有子類類型都可以正常被接收;

舊的方式定義Python類允許不從object類繼承,但這種編程方式已經(jīng)嚴(yán)重不推薦使用。任何時(shí)候,如果沒有合適的類可以繼承,就繼承自object類。

魔法方法

在上面有提到除了init之外還有iter,reverse的方法,這里就詳細(xì)說下除了init初始化還有哪些別的方法。

__init__ :      構(gòu)造函數(shù),在生成對(duì)象時(shí)調(diào)用 __del__ :       析構(gòu)函數(shù),釋放對(duì)象時(shí)使用 __repr__ :      打印,轉(zhuǎn)換 __setitem__ :   按照索引賦值 __getitem__:    按照索引獲取值 __len__:        獲得長度 __cmp__:        比較運(yùn)算 __call__:       調(diào)用 __add__:        加運(yùn)算 __sub__:        減運(yùn)算 __mul__:        乘運(yùn)算 __div__:        除運(yùn)算 __mod__:        求余運(yùn)算 __pow__:        冪

具體使用

1. doc

說明性文檔和信息。Python自建,無需自定義。

class Foo:     """ 描述類信息,可被自動(dòng)收集 """     def func(self):         pass # 打印類的說明文檔  print(Foo.__doc__)

2. init()

實(shí)例化方法,通過類創(chuàng)建實(shí)例時(shí),自動(dòng)觸發(fā)執(zhí)行。

class Foo:     def __init__(self, name):         self.name = name         self.age = 18 obj = Foo(jack') # 自動(dòng)執(zhí)行類中的 __init__ 方法

3. module__ 和 __class

module 表示當(dāng)前操作的對(duì)象在屬于哪個(gè)模塊。

class 表示當(dāng)前操作的對(duì)象屬于哪個(gè)類。

這兩者也是Python內(nèi)建,無需自定義。

class Foo:     pass obj = Foo() print(obj.__module__) print(obj.__class__)

運(yùn)行結(jié)果:

main

4. del()

析構(gòu)方法,當(dāng)對(duì)象在內(nèi)存中被釋放時(shí),自動(dòng)觸發(fā)此方法。

注:此方法一般無須自定義,因?yàn)镻ython自帶內(nèi)存分配和釋放機(jī)制,除非你需要在釋放的時(shí)候指定做一些動(dòng)作。析構(gòu)函數(shù)的調(diào)用是由解釋器在進(jìn)行垃圾回收時(shí)自動(dòng)觸發(fā)執(zhí)行的。

class Foo:     def __del__(self):         print("我被回收了!")  obj = Foo() del obj

5. call()

如果為一個(gè)類編寫了該方法,那么在該類的實(shí)例后面加括號(hào),可會(huì)調(diào)用這個(gè)方法。

注:構(gòu)造方法的執(zhí)行是由類加括號(hào)執(zhí)行的,即:對(duì)象 = 類名(),而對(duì)于call() 方法,是由對(duì)象后加括號(hào)觸發(fā)的,即:對(duì)象() 或者 類()()

class Foo:     def __init__(self):         pass     def __call__(self, *args, **kwargs):         print('__call__') obj = Foo()     # 執(zhí)行 __init__ obj()       # 執(zhí)行 __call__

可以用Python內(nèi)建的callable()函數(shù)進(jìn)行測試,判斷一個(gè)對(duì)象是否可以被執(zhí)行。

callable(Student())

運(yùn)行結(jié)果:

True

6. dict

列出類或?qū)ο笾械乃谐蓡T!非常重要和有用的一個(gè)屬性,Python自建,無需用戶自己定義。

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__) # 獲取 對(duì)象obj1 的成員  obj1 = Province('HeBei',10000) print(obj1.__dict__) # 獲取 對(duì)象obj2 的成員  obj2 = Province('HeNan', 3888) print(obj2.__dict__)

7. str()

如果一個(gè)類中定義了str()方法,那么在打印對(duì)象時(shí),默認(rèn)輸出該方法的返回值。這也是一個(gè)非常重要的方法,需要用戶自己定義。

下面的類,沒有定義str()方法,打印結(jié)果是:

class Foo:     pass obj = Foo() print(obj) 定義了__str__()方法后,打印結(jié)果是:'jack'。 class Foo:     def __str__(self):         return 'jack' obj = Foo() print(obj)

8、getitem__()、_setitem_()、__delitem()

取值、賦值、刪除這“三劍客”的套路,在Python中,我們已經(jīng)見過很多次了,比如前面的@property裝飾器。

Python中,標(biāo)識(shí)符后面加圓括號(hào),通常代表執(zhí)行或調(diào)用方法的意思。而在標(biāo)識(shí)符后面加中括號(hào)[],通常代表取值的意思。Python設(shè)計(jì)了getitem()、setitem()、delitem()這三個(gè)特殊成員,用于執(zhí)行與中括號(hào)有關(guān)的動(dòng)作。它們分別表示取值、賦值、刪除數(shù)據(jù)。

也就是如下的操作:

a = 標(biāo)識(shí)符[]?。?nbsp;執(zhí)行__getitem__方法 標(biāo)識(shí)符[] = a  : 執(zhí)行__setitem__方法 del 標(biāo)識(shí)符[]?。?nbsp;執(zhí)行__delitem__方法

如果有一個(gè)類同時(shí)定義了這三個(gè)魔法方法,那么這個(gè)類的實(shí)例的行為看起來就像一個(gè)字典一樣,如下例所示:

class Foo:     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']      # 自動(dòng)觸發(fā)執(zhí)行 __getitem__ obj['k2'] = 'jack'      # 自動(dòng)觸發(fā)執(zhí)行 __setitem__ del obj['k1']             # 自動(dòng)觸發(fā)執(zhí)行 __delitem__

9. iter()

這是迭代器方法!列表、字典、元組之所以可以進(jìn)行for循環(huán),是因?yàn)槠鋬?nèi)部定義了  iter()這個(gè)方法。如果用戶想讓自定義的類的對(duì)象可以被迭代,那么就需要在類中定義這個(gè)方法,并且讓該方法的返回值是一個(gè)可迭代的對(duì)象。當(dāng)在代碼中利用for循環(huán)遍歷對(duì)象時(shí),就會(huì)調(diào)用類的這個(gè)iter()方法。

普通的類:

class Foo:     pass obj = Foo() for i in obj:     print(i) # 報(bào)錯(cuò):TypeError: 'Foo' object is not iterable<br># 原因是Foo對(duì)象不可迭代 添加一個(gè)__iter__(),但什么都不返回: class Foo:     def __iter__(self):         pass obj = Foo() for i in obj:     print(i) # 報(bào)錯(cuò):TypeError: iter() returned non-iterator of type 'NoneType' #原因是 __iter__方法沒有返回一個(gè)可迭代的對(duì)象

返回一個(gè)個(gè)迭代對(duì)象:

class Foo:     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)

***的方法是使用生成器:

class Foo:     def __init__(self):         pass     def __iter__(self):         yield 1         yield 2         yield 3 obj = Foo() for i in obj:     print(i)

10、len()

在Python中,如果你調(diào)用內(nèi)置的len()函數(shù)試圖獲取一個(gè)對(duì)象的長度,在后臺(tái),其實(shí)是去調(diào)用該對(duì)象的len()方法,所以,下面的代碼是等價(jià)的:

len('ABC') 3 'ABC'.__len__() 3

Python的list、dict、str等內(nèi)置數(shù)據(jù)類型都實(shí)現(xiàn)了該方法,但是你自定義的類要實(shí)現(xiàn)len方法需要好好設(shè)計(jì)。

11. repr()

這個(gè)方法的作用和str()很像,兩者的區(qū)別是str()返回用戶看到的字符串,而repr()返回程序開發(fā)者看到的字符串,也就是說,repr()是為調(diào)試服務(wù)的。通常兩者代碼一樣。

class Foo:     def __init__(self, name):         self.name = name     def __str__(self):         return "this is %s" % self.name     __repr__ = __str__

12. add__: 加運(yùn)算 _sub_: 減運(yùn)算 _mul_: 乘運(yùn)算 _div_: 除運(yùn)算 _mod_: 求余運(yùn)算 __pow: 冪運(yùn)算

這些都是算術(shù)運(yùn)算方法,需要你自己為類設(shè)計(jì)具體運(yùn)算代碼。有些Python內(nèi)置數(shù)據(jù)類型,比如int就帶有這些方法。Python支持運(yùn)算符的重載,也就是重寫。

class Vector:    def __init__(self, a, b):       self.a = a       self.b = b    def __str__(self):       return 'Vector (%d, %d)' % (self.a, self.b)    def __add__(self,other):       return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10) v2 = Vector(5,-2) print (v1 + v2)

13. author作者信息

__author__ = "Jack" def show():     print(__author__) show()

14. slots

Python作為一種動(dòng)態(tài)語言,可以在類定義完成和實(shí)例化后,給類或者對(duì)象繼續(xù)添加隨意個(gè)數(shù)或者任意類型的變量或方法,這是動(dòng)態(tài)語言的特性。例如:

def print_doc(self):     print("haha")  class Foo:     pass  obj1 = Foo() obj2 = Foo() # 動(dòng)態(tài)添加實(shí)例變量 obj1.name = "jack" obj2.age = 18 # 動(dòng)態(tài)的給類添加實(shí)例方法 Foo.show = print_doc obj1.show() obj2.show()

但是!如果我想限制實(shí)例可以添加的變量怎么辦?可以使slots限制實(shí)例的變量,比如,只允許Foo的實(shí)例添加name和age屬性。

def print_doc(self):     print("haha") class Foo:     __slots__ = ("name", "age")     pass obj1 = Foo() obj2 = Foo() # 動(dòng)態(tài)添加實(shí)例變量 obj1.name = "jack" obj2.age = 18 obj1.sex = "male"       # 這一句會(huì)彈出錯(cuò)誤 # 但是無法限制給類添加方法 Foo.show = print_doc obj1.show() obj2.show() 由于'sex'不在__slots__的列表中,所以不能綁定sex屬性,試圖綁定sex將得到AttributeError的錯(cuò)誤。 Traceback (most recent call last):   File "F:/Python/pycharm/201705/1.py", line 14, in <module>     obj1.sex = "male" AttributeError: 'Foo' object has no attribute 'sex'

需要提醒的是,slots定義的屬性僅對(duì)當(dāng)前類的實(shí)例起作用,對(duì)繼承了它的子類是不起作用的。想想也是這個(gè)道理,如果你繼承一個(gè)父類,卻莫名其妙發(fā)現(xiàn)有些變量無法定義,那不是大問題么?如果非要子類也被限制,除非在子類中也定義slots,這樣,子類實(shí)例允許定義的屬性就是自身的slots加上父類的slots。

成員保護(hù)與訪問機(jī)制

有些對(duì)象你不想外部訪問,即使是通過調(diào)用類對(duì)象也無法訪問,那就請(qǐng)認(rèn)真學(xué)完本章節(jié)。

私有成員

class obj:     def __init__(self,name):         self.name=name     def pri(self):         print self.name     __age = 18     # 加上雙下劃線的就是私有變量,只能在類的內(nèi)部訪問,外部無法訪問 a = obj('zhao') a.pri()

運(yùn)行結(jié)果:

zhao

如果要在類中調(diào)用這個(gè)私有成員,可以這么用

class obj:     def __init__(self,name):         self.name=name     def prin(self):         print self.name     __age = 18     # 加上雙下劃線的就是私有變量,只能在類的內(nèi)部訪問,外部無法訪問     @classmethod     # 如果要在類中調(diào)用,首先調(diào)用類方法     def pri(cls):         print cls.__age         # 然后在使用 a = obj('zhao') a.prin() obj.pri() # 通過這樣直接調(diào)用類中的私有變量

運(yùn)行結(jié)果:

zhao18

使用get-set-del方法操作私有成員

class obj:     def __init__(self,name):         self.name=name     def prin(self):         print self.name     __age = 18     # 加上雙下劃線的就是私有變量,只能在類的內(nèi)部訪問,外部無法訪問     @classmethod     # 如果要在類中調(diào)用,首先調(diào)用類方法     def pri(cls):         print cls.__age         # 然后在使用     @classmethod     def set_age(cls,value):         cls.__age = value         return cls.__age         # 這個(gè)用法就是改變__age的值     @classmethod     def get_age(cls):         return cls.__age         # 這個(gè)用法就是直接返回__age的值     @classmethod     def del_age(cls):         del cls.__age         # 這個(gè)用法就是直接刪除__age的值  print obj.get_age() # 這里是直接調(diào)用出__age的值  返回值18 print obj.set_age(20) # 這里是直接改變__age的值  返回值20 obj.del_age() # 這里是直接刪除__age的值

思考:  既然是私有變量,不讓外部訪問,為何有要在后面調(diào)用又改變呢?因?yàn)榭梢詫?duì)私有變量進(jìn)行額外的檢測,處理,加工等等。比如判斷value的值,使用isinstance然后做if-else判斷。

使用私有變量可以對(duì)內(nèi)部變量進(jìn)行保護(hù),外部無法改變,但是可以對(duì)它進(jìn)行檢測處理。

這里引申一下私有成員的保護(hù)機(jī)制,使用__age對(duì)私有變量其實(shí)就是&mdash;>obj._obj__age的樣子進(jìn)行保護(hù),說白了你直接使用obj._obj__age就可以直接調(diào)用內(nèi)部私有變量age了。

Propety裝飾器

把類的方法偽裝成屬性調(diào)用的方式,就是把類里面的一個(gè)函數(shù),變成一個(gè)屬性一樣的東西~

一開始調(diào)用類的方法要使用圓括號(hào),現(xiàn)在變成了屬性進(jìn)行讀取設(shè)置存儲(chǔ)。

舉個(gè)例子來說明:

常用的調(diào)用方法

class obj:     def __init__(self,name,age):         self.__name=name         self.__age=age         # 講這些設(shè)置成私有變量     def get_age(self):         return self.__age     def set_age(self,value):         if isinstance(value,int):             self.__age=value         else:             raise ValueError('非整數(shù)類型')     def del_age(self):         print 'delete over' a = obj('langzi',18) print a.get_age() a.set_age(20) print a.get_age()

使用裝飾器

class obj:     def __init__(self,name,age):         self.__name=name         self.__age=age         # 把這些設(shè)置成私有變量     @property     def age(self):         return self.__age     @age.setter     def age(self,value):         if isinstance(value,int):             self.__age=value         else:             raise ValueError('非整數(shù)類型')     @age.deleter     def age(self):         print 'delete over' a = obj('langzi',18) # 使用這些裝飾器,可以使用類與對(duì)象的方法直接調(diào)用 print a.age # 這里就是直接調(diào)用返回age的值 a.age=20 # 這里就是直接使用setter把值轉(zhuǎn)換 print a.age del a.age # 刪除age

當(dāng)然這種調(diào)用方法有些麻煩,每次都是一個(gè)一個(gè)去實(shí)例類與對(duì)象,有個(gè)更加簡單直觀的方法。

更加減半的使用property()函數(shù)

除了使用裝飾器的方式將一個(gè)方法偽裝成屬性外,Python內(nèi)置的builtins模塊中的property()函數(shù),為我們提供了第二種設(shè)置類屬性的手段。

class People:      def __init__(self, name, age):         self.__name = name         self.__age = age      def get_age(self):         return self.__age      def set_age(self, age):         if isinstance(age, int):             self.__age = age         else:             raise ValueError      def del_age(self):         print("刪除年齡數(shù)據(jù)!")      # 核心在這句     age = property(get_age, set_age, del_age, "年齡")       obj = People("jack", 18) print(obj.age) obj.age = 19 print("obj.age:  ", obj.age) del obj.ag

通過語句age = property(get_age, set_age, del_age,  “年齡”)將一個(gè)方法偽裝成為屬性。其效果和裝飾器的方法是一樣的。

property()函數(shù)的參數(shù):

***個(gè)參數(shù)是方法名,調(diào)用 實(shí)例.屬性 時(shí)自動(dòng)執(zhí)行的方法 第二個(gè)參數(shù)是方法名,調(diào)用 實(shí)例.屬性 = XXX時(shí)自動(dòng)執(zhí)行的方法 第三個(gè)參數(shù)是方法名,調(diào)用 del 實(shí)例.屬性 時(shí)自動(dòng)執(zhí)行的方法 第四個(gè)參數(shù)是字符串,調(diào)用 實(shí)例.屬性.__doc__時(shí)的描述信息。

感謝各位的閱讀,以上就是“Python面向?qū)ο缶幊讨R(shí)點(diǎn)總結(jié)”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Python面向?qū)ο缶幊讨R(shí)點(diǎn)總結(jié)這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI