python元類、反射及雙線方法

元類、反射及雙線方法

元類

print(type('abc'))
print(type(True))
print(type(100))
print(type([1, 2, 3]))
print(type({'name': '太白金星'}))
print(type((1,2,3)))
print(type(object))class A:passprint(isinstance(object,type))
print(isinstance(A, type))

type元類是獲取該對象從屬于的類,而type類比較特殊,Python原則是:一切皆對象,其實類也可以理解為'對象',而type元類又稱作構建類,python中大多數內置的類(包括object)以及自己定義的類,都是由type元類創造的。

而type類與object類之間的關系比較獨特:object是type類的實例,而type類是object類的子類,這種關系比較神奇無法使用python的代碼表述,因為定義其中一個之前另一個必須存在。所以這個只作為了解。

反射

反射是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。

python面向對象中的反射:通過字符串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)

反射中常用的四個函數:

class Student:f = '類的靜態變量'def __init__(self,name,age):self.name=nameself.age=agedef say_hi(self):print('hi,%s'%self.name)
obj=Student('alex',16)# hasatter 檢測是否含有某屬性,方法
print(hasattr(obj,'name'))
print(hasattr(obj,'say_hi'))
結果:
True
True# 獲取屬性,方法  # 獲取不到直接報錯
n=getattr(obj,'name')
print(n)
func=getattr(obj,'say_hi')
func()
結果:
'alex'
'hi,alex'# 設置屬性
setattr(obj,'sb',True)
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))
結果:
{'name': 'alex', 'age': 16, 'sb': True, 'show_name': <function <lambda> at 0x00000180E591BB70>}
alexsb# 刪除屬性
delattr(obj,'age')
# delattr(obj,'show_name')
# delattr(obj,'show_name111')#不存在,則報錯print(obj.__dict__)
結果:
{'name': 'alex'}

對類的反射:

class Foo(object):staticField = "old boy"def __init__(self):self.name = 'wupeiqi'def func(self):return 'func'@staticmethoddef bar():return 'bar'print(getattr(Foo, 'staticField'))
print(getattr(Foo, 'func'))
print(getattr(Foo, 'bar'))
# 結果:
old boy
<function Foo.func at 0x00000212D21FBC80>  # 獲取func對象方法地址
<function Foo.bar at 0x00000212D21FBD08>  # 獲取bar靜態方法地址

對當前模塊的反射:

import sysdef s1():print('s1')def s2():print('s2') this_module = sys.modules[__name__]print(hasattr(this_module, 's1'))
print(getattr(this_module, 's2'))
# 結果:
True
<function s2 at 0x000002000247BBF8>

對其他模塊的反射:

import time
print(hasattr(time,'ctime'))
print(getattr(time,'ctime'))
print(getattr(time,'ctime')())
# 結果:
True
<built-in function ctime>
'Fri Aug  9 08:12:54 2019'

反射的應用

# 沒學反射之前的解決方式:
class User:def login(self):print('歡迎來到登錄頁面')def register(self):print('歡迎來到注冊頁面')def save(self):print('歡迎來到存儲頁面')while 1:choose = input('>>>').strip()if choose == 'login':obj = User()obj.login()elif choose == 'register':obj = User()obj.register()elif choose == 'save':obj = User()obj.save()
# 學了反射之后解決方式
class User:def login(self):print('歡迎來到登錄頁面')def register(self):print('歡迎來到注冊頁面')def save(self):print('歡迎來到存儲頁面')user = User()
while 1:choose = input('>>>').strip()if hasattr(user,choose):func = getattr(user,choose)func()else:print('輸入錯誤。。。。')

函數和方法的區別

通過打印函數(方法)名確定

def func():passprint(func)  # <function func at 0x00000260A2E690D0>class A:def func(self):passprint(A.func)  # <function A.func at 0x0000026E65AE9C80>
obj = A()
print(obj.func)  # <bound method A.func of <__main__.A object at 0x00000230BAD4C9E8>>

通過types模塊驗證

from types import FunctionType
from types import MethodTypedef func():passclass A:def func(self):passobj = A()
print(isinstance(func,FunctionType))  # True
print(isinstance(A.func,FunctionType))  # True
print(isinstance(obj.func,FunctionType))  # False
print(isinstance(obj.func,MethodType))  # True

靜態方法是函數

from types import FunctionType
from types import MethodTypeclass A:def func(self):pass@classmethoddef func1(self):pass@staticmethoddef func2(self):pass
obj = A()# 靜態方法其實是函數
print(isinstance(A.func2,FunctionType))  # True
print(isinstance(obj.func2,FunctionType))  # True

函數和方法的幾點區別:

(1)函數的是顯性傳參的,方法是隱性傳參的。

(2)函數則跟對象無關。

(3)方法可以操作類內部的數據。

(4)方法跟對象是關聯的。

雙線方法

定義:雙下方法是特殊方法,他是解釋器提供的 由雙下劃線加方法名加雙下劃線 __方法名__的具有特殊意義的方法,雙下方法主要是python源碼程序員使用的,在開發中盡量不要使用雙下方法,熟知雙下劃線方法有助于我們研究源碼

**1、__len__**

class B:def __len__(self):print(666)b = B()
len(b) # len 一個對象就會觸發 __len__方法。class A:def __init__(self):self.a = 1self.b = 2def __len__(self):return len(self.__dict__)
a = A()
print(len(a))

**2、__hash__**

class A:def __init__(self):self.a = 1self.b = 2def __hash__(self):return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))

**3、__str__**

如果一個類中定義了__str__方法,那么在打印 對象 時,默認輸出該方法的返回值。

class A:def __init__(self):passdef __str__(self):return '太白'
a = A()
print(a)
print('%s' % a)

**4、__repr__**

如果一個類中定義了__repr__方法,那么在repr(對象) 時,默認輸出該方法的返回值。

class A:def __init__(self):passdef __repr__(self):return '太白'
a = A()
print(repr(a))
print('%r'%a)

**5、__call__**

對象后面加括號,觸發執行。

注:構造方法__new__的執行是由創建對象觸發的,即:對象 = 類名() ;而對于 call 方法的執行是由對象后加括號觸發的,即:對象() 或者 類()()

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

**6、__eq__**

class A:def __init__(self):self.a = 1self.b = 2def __eq__(self,obj):if  self.a == obj.a and self.b == obj.b:return True
a = A()
b = A()
print(a == b)

**7、__del__**

析構方法,當對象在內存中被釋放時,自動觸發執行。

注:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。

class A:def __init__(self):self.x = 1print('in init function')def __new__(cls, *args, **kwargs):print('in new function')return object.__new__(A, *args, **kwargs)a = A()
print(a.x)

**8、__new__**

class A:def __init__(self):self.x = 1print('in init function')def __new__(cls, *args, **kwargs):print('in new function')return object.__new__(A, *args, **kwargs)a = A()
print(a.x)

單例模式:

class A:__instance = Nonedef __new__(cls, *args, **kwargs):if cls.__instance is None:obj = object.__new__(cls)cls.__instance = objreturn cls.__instance
單例模式是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱為單例類的特殊類。通過單例模式可以保證系統中一個類只有一個實例而且該實例易于外界訪問,從而方便對實例個數的控制并節約系統資源。如果希望在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。
【采用單例模式動機、原因】
對于系統中的某些類來說,只有一個實例很重要,例如,一個系統中可以存在多個打印任務,但是只能有一個正在工作的任務;一個系統只能有一個窗口管理器或文件系統;一個系統只能有一個計時工具或ID(序號)生成器。如在Windows中就只能打開一個任務管理器。如果不使用機制對窗口對象進行唯一化,將彈出多個窗口,如果這些窗口顯示的內容完全一致,則是重復對象,浪費內存資源;如果這些窗口顯示的內容不一致,則意味著在某一瞬間系統有多個狀態,與實際不符,也會給用戶帶來誤解,不知道哪一個才是真實的狀態。因此有時確保系統中某個對象的唯一性即一個類只能有一個實例非常重要。
如何保證一個類只有一個實例并且這個實例易于被訪問呢?定義一個全局變量可以確保對象隨時都可以被訪問,但不能防止我們實例化多個對象。一個更好的解決辦法是讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例被創建,并且它可以提供一個訪問該實例的方法。這就是單例模式的模式動機。
【單例模式優缺點】
【優點】
一、實例控制
單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例。
二、靈活性
因為類控制了實例化過程,所以類可以靈活更改實例化過程。
【缺點】
一、開銷
雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。
二、可能的開發混淆
使用單例對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用new關鍵字實例化對象。因為可能無法訪問庫源代碼,因此應用程序開發人員可能會意外發現自己無法直接實例化此類。
三、對象生存期
不能解決刪除單個對象的問題。在提供內存管理的語言中(例如基于.NET Framework的語言),只有單例類能夠導致實例被取消分配,因為它包含對該實例的私有引用。在某些語言中(如 C++),其他類可以刪除對象實例,但這樣會導致單例類中出現懸浮引用

**9、 __item__系列**

class Foo:def __init__(self,name):self.name=namedef __getitem__(self, item):print(self.__dict__[item])def __setitem__(self, key, value):self.__dict__[key]=valuedef __delitem__(self, key):print('del obj[key]時,我執行')self.__dict__.pop(key)def __delattr__(self, item):print('del obj.key時,我執行')self.__dict__.pop(item)f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)

10 上下文管理器相關

__enter__ __exit__

# 如果想要對一個類的對象進行with  as 的操作 不行。
class A:def __init__(self, text):self.text = textwith A('大爺') as f1:print(f1.text)
class A:def __init__(self, text):self.text = textdef __enter__(self):  # 開啟上下文管理器對象時觸發此方法self.text = self.text + '您來啦'return self  # 將實例化的對象返回f1def __exit__(self, exc_type, exc_val, exc_tb):  # 執行完上下文管理器對象f1時觸發此方法self.text = self.text + '這就走啦'with A('大爺') as f1:print(f1.text)
print(f1.text)

自定義文件管理器

class Diycontextor:def __init__(self,name,mode):self.name = nameself.mode = modedef __enter__(self):print("Hi enter here!!")self.filehander = open(self.name,self.mode)return self.filehanderdef __exit__(self,*para):print("Hi exit here")self.filehander.close()with Diycontextor('py_ana.py','r') as f:for i in f:print(i)

相關面試題:

class StarkConfig:def __init__(self,num):self.num = numdef run(self):self()def __call__(self, *args, **kwargs):print(self.num)class RoleConfig(StarkConfig):def __call__(self, *args, **kwargs):print(345)def __getitem__(self, item):return self.num[item]v1 = RoleConfig('alex')
v2 = StarkConfig('太白金星')
# print(v1[1])
# print(v2[2])
v1.run()-------
class UserInfo:passclass Department:passclass StarkConfig:def __init__(self, num):self.num = numdef changelist(self, request):print(self.num, request)def run(self):self.changelist(999)class RoleConfig(StarkConfig):def changelist(self, request):print(666, self.num)class AdminSite:def __init__(self):self._registry = {}def register(self, k, v):self._registry[k] = vsite = AdminSite()
site.register(UserInfo, StarkConfig)
# 1 
# obj = site._registry[UserInfo]()# 2
obj = site._registry[UserInfo](100)
obj.run()-------
class UserInfo:passclass Department:passclass StarkConfig:def __init__(self,num):self.num = numdef changelist(self,request):print(self.num,request)def run(self):self.changelist(999)class RoleConfig(StarkConfig):def changelist(self,request):print(666,self.num)class AdminSite:def __init__(self):self._registry = {}def register(self,k,v):self._registry[k] = v(k)site = AdminSite()
site.register(UserInfo,StarkConfig)
site.register(Department,RoleConfig)for k,row in site._registry.items():row.run()-------
class A:list_display = []def get_list(self):self.list_display.insert(0,33)return self.list_displays1 = A()
print(s1.get_list())-------
class A:list_display = [1, 2, 3]def __init__(self):self.list_display = []def get_list(self):self.list_display.insert(0, 33)return self.list_displays1 = A()
print(s1.get_list())------
class A:list_display = []def get_list(self):self.list_display.insert(0,33)return self.list_displayclass B(A):list_display = [11,22]s1 = A()
s2 = B()
print(s1.get_list())
print(s2.get_list())

轉載于:https://www.cnblogs.com/lifangzheng/p/11354891.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247145.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247145.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247145.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iOS中的多線程一般使用場景

在IOS開發中為提高程序的運行效率會將比較耗時的操作放在子線程中執行&#xff0c;iOS系統進程默認啟動一個主線程&#xff0c;用來響應用戶的手勢操作以及UI刷新&#xff0c;因此主線程又叫做UI線程。 前面的Blog說明了NSThread以及GCD處理并發線程以及線程安全&#xff08;線…

iOS中如何優化Cell中圖片的下載性能

在iOS開發中使用最為常見的是UITableView&#xff0c;其中UITabelViewCell中下載圖片&#xff0c;會影響用戶下拉刷新UI,導致卡頓&#xff0c;用戶體驗不好&#xff0c;在這篇blog中&#xff0c;我將以一個例子來說明如何優化UITableView下載圖片 1.使用懶加載方式&#xff0c…

【Yoshua Bengio 親自解答】機器學習 81 個問題及答案(最全收錄)

本文轉自&#xff1a;http://mp.weixin.qq.com/s?__bizMzI3MTA0MTk1MA&mid401958262&idx1&sn707f228cf5779a31f0933af903516ba6&scene1&srcid0121zzdeFPtgoRoEviZ3LZDG#rd 譯者&#xff1a;張巨巖 王婉婷 李宏菲 戴秋池 這是 Quora 的最新節目&#xf…

Java生鮮電商平臺-SpringCloud微服務架構中網絡請求性能優化與源碼解析

Java生鮮電商平臺-SpringCloud微服務架構中網絡請求性能優化與源碼解析 說明&#xff1a;Java生鮮電商平臺中&#xff0c;由于服務進行了拆分&#xff0c;很多的業務服務導致了請求的網絡延遲與性能消耗&#xff0c;對應的這些問題&#xff0c;我們應該如何進行網絡請求的優化與…

XCode7 創建framework

1.新建一個靜態庫工程. file→ new→ project, 彈出框中選擇iOS→ framework & library中的cocoa touch static library.點擊Next,輸入product name: TestFramework, 點擊Next→ 點擊Create. 2.刪除向導所生成工程中的Target. 點擊工程名→ 點擊TARGETS → 右鍵Delete. …

基礎js逆向練習-登錄密碼破解(js逆向)

練習平臺&#xff1a;逆向賬號密碼 https://login1.scrape.center/ 直接打開平臺&#xff0c;輸入密碼賬號&#xff0c;抓包找到加密的參數攜帶的位置&#xff0c;這邊我們找到的是一個叫token的加密參數&#xff0c;這個參數的攜帶是一個密文 我們首先考慮一下搜索這個加密的…

python之socket

socket套接字 什么叫socket socket是處于應用層與傳輸層之間的抽象層,他是一組操作起來非常簡單的接口(接受數據)此接口接受數據之后,交由操作系統.socket在python中就是一個模塊. socket兩個分類 基于文件類型的套接字家族 套接字家族的名字&#xff1a;AF_UNIX unix一切皆文件…

iOS----JSON解析

在iOS開發中與服務器進行數據交互操作&#xff0c;操作過程中使用最為常見的格式為JSON與XML,其中JSON較為清量,因此本篇blog就講解一下如何在iOS中進行JSON解析。 1.建立HTTP請求 &#xff08;1&#xff09;創建URL NSString *URLStr [NSString stringWithFormat:”http:/…

VS中每次改代碼后運行程序不更新,只有重新編譯才生效。

解決方法&#xff1a;將項目移除解決方案&#xff0c;再重新添加進來&#xff0c;即添加->現有項目->選擇.vcxproj文件&#xff0c;即可解決。 轉載于:https://www.cnblogs.com/Gregg/p/11358711.html

socket補充:通信循環、鏈接循環、遠程操作及黏包現象

socket補充&#xff1a;通信循環、鏈接循環、遠程操作及黏包現象 socket通信循環 server端&#xff1a; import socketphone socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind((127.0.0.1,8080))phone.listen(5)conn, client_addr phone.accept() print(conn, cl…

PCA的原理及MATLAB實現

相關文章 PCA的原理及MATLAB實現 UFLDL教程&#xff1a;Exercise:PCA in 2D & PCA and Whitening python-A comparison of various Robust PCA implementations &#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&a…

Java生鮮電商平臺-SpringCloud微服務架構中核心要點和實現原理

Java生鮮電商平臺-SpringCloud微服務架構中核心要點和實現原理 說明&#xff1a;Java生鮮電商平臺中&#xff0c;我們將進一步理解微服務架構的核心要點和實現原理&#xff0c;為讀者的實踐提供微服務的設計模式&#xff0c;以期讓微服務在讀者正在工作的項目中起到積極的作用。…

iOS中下載小文件

在iOS中通過網絡下載小文件比如小型圖片等資源&#xff0c;一般在子線程中將數據完全下載完畢&#xff0c;然后在調用block將下載的數據整個部分返回&#xff0c;或者采用同步返回下載數據。 一般采用以下兩種方式&#xff1a; &#xff08;1&#xff09;使用GCD將下載操作放…

iOS下載大文件原理解析一

iOS中下載大型文件&#xff0c;需要考慮到占用內存的大小與下載速度&#xff08;使用多線程&#xff09;&#xff0c;因此本文首先介紹一個原理性下載文件的DEMO。 在下載大型文件中&#xff0c;需要知道下載的進度因此需要使用代理模式&#xff0c;不斷的回調下載進度。 - (…

recv原理、高階版黏包解決方案、基于UDP的socket通信

recv原理、高階版黏包解決方案、基于UDP的socket通信 recv原理 源碼解釋&#xff1a; Receive up to buffersize bytes from the socket. 接收來自socket緩沖區的字節數據&#xff0c; For the optional flags argument, see the Unix manual. 對于這些設置的參數&#xff0c;可…

iOS中下載大型文件的原理解析二

在iOS中下載大型文件&#xff0c;需要使用NSURLConnection 的代理方法&#xff1a; (void)touchesBegan:(NSSet)touches withEvent:(UIEvent *)event { NSURL *url [NSURL URLWithString:”http://d.3987.com/fengj_141112/007.jpg“]; NSURLRequest *request [NSURLReque…

ASP.NET Core Web 應用程序開發期間部署到IIS自定義主機域名并附加到進程調試

想必大家之前在進行ASP.NET Web 應用程序開發期間都有用到過將我們的網站部署到IIS自定義主機域名并附加到進程進行調試。 那我們的ASP.NET Core Web 應用程序又是如何部署到我們的IIS上面進行調試的呢&#xff0c;接下來我們來簡單介紹下&#xff1a; 一、安裝IIS所需的Host擴…

iOS下載大型文件原理解析三

在下載大型文件過程中是可以取消下載的 - (IBAction)download:(UIButton *)sender { // 狀態取反 sender.selected !sender.isSelected; // 斷點續傳 // 斷點下載if (sender.selected) { // 繼續&#xff08;開始&#xff09;下載// 1.URLNSURL *url [NSURL URLWithStrin…

HTML文件上傳與下載

文件下載 傳統的文件下載有兩種方法&#xff1a; 使用<a/>標簽&#xff0c;href屬性直接連接到服務器的文件路徑window.location.href"url"這兩種方法效果一樣。但有個很大的問題&#xff0c;如果下載出現異常&#xff08;連接路徑失效、文件不存在、網絡問題等…