15 內置方法(下)

来源:https://www.cnblogs.com/oceanicstar/archive/2018/04/16/8853275.html
-Advertisement-
Play Games

面向對象學習目錄 1 面向對象介紹 2 類、實例、屬性、方法詳解 3 面向過程與面向對象進一步比較 4 類與對象 5 屬性查找與綁定方法 6 小結 7 繼承與派生 8 組合 9 抽象類 10 多態 11 封裝 12 綁定方法與非綁定方法 13 內置方法(上) 14 內置方法(中)之描述符 15 內置 ...


面向對象學習目錄

1 面向對象介紹

2 類、實例、屬性、方法詳解

3 面向過程與面向對象進一步比較

4 類與對象

5 屬性查找與綁定方法

6 小結

7 繼承與派生

8 組合

9 抽象類

10 多態

11 封裝

12 綁定方法與非綁定方法

13 內置方法(上)

14 內置方法(中)之描述符

15 內置方法(下)


七、再看property

        一個靜態屬性property本質就是實現了get,set,delete三種方法 用法一
 1 class Foo:
 2     @property
 3     def AAA(self):
 4         print('get的時候運行我啊')
 5  
 6     @AAA.setter
 7         def AAA(self,value):
 8             print('set的時候運行我啊')
 9  
10     @AAA.deleter
11         def AAA(self):
12             print('delete的時候運行我啊')
13  
14 #只有在屬性AAA定義property後才能定義AAA.setter,AAA.deleter
15 f1=Foo()
16 f1.AAA
17 f1.AAA='aaa'
18 del f1.AAA

用法二

 1 class Foo:
 2     def get_AAA(self):
 3         print('get的時候運行我啊')
 4  
 5     def set_AAA(self,value):
 6         print('set的時候運行我啊')
 7  
 8     def delete_AAA(self):
 9         print('delete的時候運行我啊')
10  
11 AAA=property(get_AAA,set_AAA,delete_AAA) #內置property三個參數與get,set,delete一一對應
12  
13 f1=Foo()
14 f1.AAA
15 f1.AAA='aaa'
16 del f1.AAA

怎麼用?

案例一
 1 class Goods:
 2     def __init__(self):
 3         # 原價
 4         self.original_price = 100
 5         # 折扣
 6         self.discount = 0.8
 7  
 8     @property
 9     def price(self):
10         # 實際價格 = 原價 * 折扣
11         new_price = self.original_price * self.discount
12         return new_price
13  
14     @price.setter
15     def price(self, value):
16         self.original_price = value
17  
18     @price.deleter
19     def price(self):
20         del self.original_price
21  
22  
23 obj = Goods()
24 obj.price # 獲取商品價格
25 obj.price = 200 # 修改商品原價
26 print(obj.price)
27 del obj.price # 刪除商品原價

案例二

 1 #實現類型檢測功能
 2  
 3 #第一關:
 4 class People:
 5     def __init__(self,name):
 6         self.name=name
 7  
 8     @property
 9     def name(self):
10         return self.name
11  
12 # p1=People('alex')
13 #property自動實現了set和get方法屬於數據描述符,比實例屬性優先順序高,所以你這面寫會觸發property內置的set,拋出異常
14  
15  
16 #第二關:修訂版
17  
18 class People:
19     def __init__(self,name):
20         self.name=name #實例化就觸發property
21  
22     @property
23     def name(self):
24         # return self.name #無限遞歸
25         print('get------>')
26         return self.DouNiWan
27  
28     @name.setter
29     def name(self,value):
30         print('set------>')
31         self.DouNiWan=value
32  
33     @name.deleter
34     def name(self):
35         print('delete------>')
36         del self.DouNiWan
37  
38 p1=People('alex') #self.name實際是存放到self.DouNiWan里
39 print(p1.name)
40 print(p1.name)
41 print(p1.name)
42 print(p1.__dict__)
43  
44 p1.name='egon'
45 print(p1.__dict__)
46  
47 del p1.name
48 print(p1.__dict__)
49  
50  
51 #第三關:加上類型檢查
52 class People:
53     def __init__(self,name):
54         self.name=name #實例化就觸發property
55  
56     @property
57     def name(self):
58         # return self.name #無限遞歸
59         print('get------>')
60         return self.DouNiWan
61  
62     @name.setter
63     def name(self,value):
64         print('set------>')
65         if not isinstance(value,str):
66             raise TypeError('必須是字元串類型')
67             self.DouNiWan=value
68  
69     @name.deleter
70     def name(self):
71         print('delete------>')
72         del self.DouNiWan
73  
74 p1=People('alex') #self.name實際是存放到self.DouNiWan里
75 p1.name=1

 

八、__setitem__,__getitem__,__delitem__

 1 class Foo:
 2     def __init__(self,name):
 3         self.name=name
 4  
 5     def __getitem__(self, item):
 6         print(self.__dict__[item])
 7  
 8     def __setitem__(self, key, value):
 9         self.__dict__[key]=value
10     def __delitem__(self, key):
11         print('del obj[key]時,我執行')
12         self.__dict__.pop(key)
13     def __delattr__(self, item):
14         print('del obj.key時,我執行')
15         self.__dict__.pop(item)
16  
17 f1=Foo('sb')
18 f1['age']=18
19 f1['age1']=19
20 del f1.age1
21 del f1['age']
22 f1['name']='alex'
23 print(f1.__dict__)

 

九、__str__,__repr__,__format__

        改變對象的字元串顯示__str__,__repr__         自定製格式化字元串__format__
 1 format_dict={
 2     'nat':'{obj.name}-{obj.addr}-{obj.type}',#學校名-學校地址-學校類型
 3     'tna':'{obj.type}:{obj.name}:{obj.addr}',#學校類型:學校名:學校地址
 4     'tan':'{obj.type}/{obj.addr}/{obj.name}',#學校類型/學校地址/學校名
 5     }
 6  
 7 class School:
 8     def __init__(self,name,addr,type):
 9         self.name=name
10         self.addr=addr
11         self.type=type
12  
13     def __repr__(self):
14         return 'School(%s,%s)' %(self.name,self.addr)
15     def __str__(self):
16         return '(%s,%s)' %(self.name,self.addr)
17  
18     def __format__(self, format_spec):
19         # if format_spec
20         if not format_spec or format_spec not in format_dict:
21             format_spec='nat'
22             fmt=format_dict[format_spec]
23             return fmt.format(obj=self)
24  
25 s1=School('oldboy1','北京','私立')
26 print('from repr: ',repr(s1))
27 print('from str: ',str(s1))
28 print(s1)
29  
30 '''
31 str函數或者print函數--->obj.__str__()
32 repr或者互動式解釋器--->obj.__repr__()
33 如果__str__沒有被定義,那麼就會使用__repr__來代替輸出
34 註意:這倆方法的返回值必須是字元串,否則拋出異常
35 '''
36 print(format(s1,'nat'))
37 print(format(s1,'tna'))
38 print(format(s1,'tan'))
39 print(format(s1,'asfdasdffd'))

自定義format練習

 1 date_dic={
 2     'ymd':'{0.year}:{0.month}:{0.day}',
 3     'dmy':'{0.day}/{0.month}/{0.year}',
 4     'mdy':'{0.month}-{0.day}-{0.year}',
 5     }
 6  
 7 class Date:
 8     def __init__(self,year,month,day):
 9         self.year=year
10         self.month=month
11         self.day=day
12  
13     def __format__(self, format_spec):
14         if not format_spec or format_spec not in date_dic:
15             format_spec='ymd'
16             fmt=date_dic[format_spec]
17             return fmt.format(self)
18  
19 d1=Date(2016,12,29)
20 print(format(d1))
21 print('{:mdy}'.format(d1))

issubclass和isinstance

 1 class A:
 2     pass
 3  
 4 class B(A):
 5     pass
 6  
 7 print(issubclass(B,A)) #B是A的子類,返回True
 8  
 9 a1=A()
10 print(isinstance(a1,A)) #a1是A的實例

 

十、slots

slots使用
 1 '''
 2 1.__slots__是什麼:是一個類變數,變數值可以是列表,元祖,或者可迭代對象,也可以是一個字元串(意味著所有實例只有一個數據屬性)
 3 2.引子:使用點來訪問屬性本質就是在訪問類或者對象的__dict__屬性字典(類的字典是共用的,而每個實例的是獨立的)
 4 3.為何使用__slots__:字典會占用大量記憶體,如果你有一個屬性很少的類,但是有很多實例,為了節省記憶體可以使用__slots__取代實例的__dict__
 5 當你定義__slots__後,__slots__就會為實例使用一種更加緊湊的內部表示。實例通過一個很小的固定大小的數組來構建,而不是為每個實例定義一個
 6 字典,這跟元組或列表很類似。在__slots__中列出的屬性名在內部被映射到這個數組的指定小標上。使用__slots__一個不好的地方就是我們不能再給
 7 實例添加新的屬性了,只能使用在__slots__中定義的那些屬性名。
 8 4.註意事項:__slots__的很多特性都依賴於普通的基於字典的實現。另外,定義了__slots__後的類不再 支持一些普通類特性了,比如多繼承。大多數情況下,你應該
 9 只在那些經常被使用到 的用作數據結構的類上定義__slots__比如在程式中需要創建某個類的幾百萬個實例對象 。
10 關於__slots__的一個常見誤區是它可以作為一個封裝工具來防止用戶給實例增加新的屬性。儘管使用__slots__可以達到這樣的目的,但是這個並不是它的初衷。 更多的是用來作為一個記憶體優化工具。
11  
12 '''
13 class Foo:
14     __slots__='x'
15  
16  
17 f1=Foo()
18 f1.x=1
19 f1.y=2 #報錯
20 print(f1.__slots__) #f1不再有__dict__
21  
22 class Bar:
23     __slots__=['x','y']
24  
25 n=Bar()
26 n.x,n.y=1,2
27 n.z=3 #報錯

刨根問底

 1 class Foo:
 2     __slots__=['name','age']
 3  
 4 f1=Foo()
 5 f1.name='alex'
 6 f1.age=18
 7 print(f1.__slots__)
 8  
 9 f2=Foo()
10 f2.name='egon'
11 f2.age=19
12 print(f2.__slots__)
13  
14 print(Foo.__dict__) #f1與f2都沒有屬性字典__dict__了,統一歸__slots__管,節省記憶體

 

十一、__next__和__iter__實現迭代器協議

簡單示範
 1 class Foo:
 2     def __init__(self,x):
 3         self.x=x
 4  
 5     def __iter__(self):
 6         return self
 7  
 8     def __next__(self):
 9         n=self.x
10         self.x+=1
11         return self.x
12  
13 f=Foo(3)
14 for i in f:
15     print(i)
 1 class Foo:
 2     def __init__(self,start,stop):
 3         self.num=start
 4         self.stop=stop
 5     def __iter__(self):
 6         return self
 7     def __next__(self):
 8         if self.num >= self.stop:
 9             raise StopIteration
10         n=self.num
11         self.num+=1
12         return n
13  
14 f=Foo(1,5)
15  
16 from collections import Iterable,Iterator
17 print(isinstance(f,Iterator))
18  
19 for i in Foo(1,5):
20     print(i)

練習:簡單模擬range,加上步長

 1 class Range:
 2     def __init__(self,n,stop,step):
 3         self.n=n
 4         self.stop=stop
 5         self.step=step
 6  
 7     def __next__(self):
 8         if self.n >= self.stop:
 9             raise StopIteration
10         x=self.n
11         self.n+=self.step
12         return x
13  
14     def __iter__(self):
15         return self
16  
17 for i in Range(1,7,3): #
18     print(i)

斐波那契數列

 1 class Fib:
 2     def __init__(self):
 3         self._a=0
 4         self._b=1
 5  
 6     def __iter__(self):
 7         return self
 8  
 9     def __next__(self):
10         self._a,self._b=self._b,self._a + self._b
11         return self._a
12  
13 f1=Fib()
14  
15 print(f1.__next__())
16 print(next(f1))
17 print(next(f1))
18  
19 for i in f1:
20     if i > 100:
21         break
22     print('%s ' %i,end='')

 

十二、__doc__

它類的描述信息
1 class Foo:
2     '我是描述信息'
3     pass
4  
5 print(Foo.__doc__)

該屬性無法被繼承

1 class Foo:
2     '我是描述信息'
3     pass
4  
5 class Bar(Foo):
6     pass
7  
8 print(Bar.__doc__) #該屬性無法繼承給子類

 

十三、__module__和__class__

        __module__ 表示當前操作的對象在那個模塊         __class__ 表示當前操作的對象的類是什麼   lib/aa.py
1 class C:
2     def __init__(self):
3         self.name = ‘SB'

index.py

1 from lib.aa import C
2  
3 obj = C()
4 print obj.__module__ # 輸出 lib.aa,即:輸出模塊
5 print obj.__class__ # 輸出 lib.aa.C,即:輸出類

 

十四、__del__

        析構方法,當對象在記憶體中被釋放時,自動觸發執行。         註:如果產生的對象僅僅只是python程式級別的(用戶級),那麼無需定義__del__,如果產生的對象的同時還會向操作系統發起系統調用,即一個對象有用戶級與內核級兩種資源,比如(打開一個文件,創建一個資料庫鏈接),則必須在清除對象的同時回收系統資源,這就用到了__del__。   簡單示範
 1 class Foo:
 2     def __del__(self):
 3     print('執行我啦')
 4  
 5 f1=Foo()
 6 del f1
 7 print('------->')
 8  
 9 #輸出結果
10 執行我啦
11 ------->

挖坑埋了你

 1 class Foo:
 2     def __del__(self):
 3         print('執行我啦')
 4  
 5 f1=Foo() # del f1
 6 print('------->')
 7  
 8 #輸出結果
 9 ------->
10 執行我啦

 

典型的應用場景:         創建資料庫類,用該類實例化出資料庫鏈接對象,對象本身是存放於用戶空間記憶體中,而鏈接則是由操作系統管理的,存放於內核空間記憶體中         當程式結束時,python只會回收自己的記憶體空間,即用戶態記憶體,而操作系統的資源則沒有被回收,這就需要我們定製__del__,在對象被刪除前向操作系統發起關閉資料庫鏈接的系統調用,回收資源   這與文件處理是一個道理:
1 f=open('a.txt') #做了兩件事,在用戶空間拿到一個f變數,在操作系統內核空間打開一個文件
2 del f #只回收用戶空間的f,操作系統的文件還處於打開狀態
3  
4 #所以我們應該在del f之前保證f.close()執行,即便是沒有del,程式執行完畢也會自動del清理資源,於是文件操作的正確用法應該是
5 f=open('a.txt')
6 讀寫...
7 f.close()
8 很多情況下大家都容易忽略f.close,這就用到了with上下文管理

 

十五、__enter__和__exit__

        我們知道在操作文件對象的時候可以這麼寫
1 with open('a.txt') as f:
2   '代碼塊'

        上述叫做上下文管理協議,即with語句,為了讓一個對象相容with語句,必須在這個對象的類中聲明__enter__和__exit__方法

上下文管理協議
 1 class Open:
 2     def __init__(self,name):
 3         self.name=name
 4     def __enter__(self):
 5         print('出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變數')
 6         # return self
 7     def __exit__(self, exc_type, exc_val, exc_tb):
 8         print('with中代碼塊執行完畢時執行我啊')
 9  
10  
11 with Open('a.txt') as f:
12   print('=====>執行代碼塊')
13   # print(f,f.name)

        __exit__()中的三個參數分別代表異常類型,異常值和追溯信息,with語句中代碼塊出現異常,則with後的代碼都無法執行

 1 class Open:
 2     def __init__(self,name):
 3         self.name=name
 4  
 5     def __enter__(self):
 6         print('出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變數')
 7  
 8     def __exit__(self, exc_type, exc_val, exc_tb):
 9         print('with中代碼塊執行完畢時執行我啊')
10         print(exc_type)
11         print(exc_val)
12         print(exc_tb)
13  
14  
15 with Open('a.txt') as f:
16     print('=====>執行代碼塊')
17     raise AttributeError('***著火啦,救火啊***')
18     print(	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • css選擇器 有通配符選擇器書寫格式:*+{聲名塊} 並集選擇器/組合選擇器 書寫格式;元素或類或id+“”+元素或類或id+“,”+元素或類或id{聲明塊} 列:h1,h2,h3{color:red;} 層次選擇器 : 子集選擇器: 格式:父級元素名稱+">"+子級元素名稱+{聲明塊} 例:div ...
  • 一、概述 vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,適合用於構建單頁面應用。 vue的單頁面應用是基於路由和組件的,路由用於設定訪問路徑,並將路徑和組件映射起來。 而傳統的多頁面應用,是用一些超鏈接來實現頁面切換和跳轉的。在vue-router單頁面應用中,則是 ...
  • 使用靜態關鍵字實現單例模式 單例模式:只能獲得某個類的唯一一個實例 單例模式,不管什麼時間點得到的對象都是同一個對象 看下麵代碼: 將構造方法私有,以便實現外部無法使用new進行實例化的效果,達到任何時候其實都是同一個對象的效果 測試代碼如下: 結果如下: 該結果表明:single、single2、 ...
  • 最小生成樹 下圖標明瞭六個城市(A~F)之間的公路(每條公路旁標註了其長度公裡數)。為將部分公路改造成高速公路,使各個城市之間均通過高速公路通達,至少要改造共計()公裡的公路,這種總公裡數最少的改造方案共有()個。 解析: (1)普里姆演算法 任取一點,例如A,將其納入已完成部分。點A與其他各點中的最... ...
  • Web應用中常用的HTTP方法有四種: 1.PUT方法用來添加的資源 2.GET方法用來獲取已有的資源 3.POST方法用來對資源進行狀態轉換 4.DELETE方法用來刪除已有的資源 Spring MVC最新的版本中提供了一種更加簡潔的配置HTTP方法的方式,增加了四個標註: @PutMapping ...
  • 1、page作用域也是最小的作用域,它只能在當前頁面中使用。 2、request作用域主要是發送請求,但只能在兩個頁面之間發送一次請求。 3、session作用域是一個會話,也就是一個瀏覽器,意思是說只能在當前會話中傳值,如果換個瀏覽器就不行了。 4、application作用域,這個就牛逼了,它是 ...
  • 手把手教你寫網路爬蟲(2) 作者:拓海 摘要:從零開始寫爬蟲,初學者的速成指南! 封面: 介紹 大家好!回顧上一期,我們在介紹了爬蟲的基本概念之後,就利用各種工具橫衝直撞的完成了一個小爬蟲,目的就是猛、糙、快,方便初學者上手,建立信心。對於有一定基礎的讀者,請不要著急,以後我們會學習主流的開源框架, ...
  • MyBatis 簡介 MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis,是一個基於Java的持久層框架。 持久層: 可以將業務數據 存儲到磁碟,具備長期存儲 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...