日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

命名空间不能直接包含字段或方法之类的成员是什么意思_Python 学习笔记之类与实例...

發(fā)布時間:2023/12/1 python 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 命名空间不能直接包含字段或方法之类的成员是什么意思_Python 学习笔记之类与实例... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Python 學(xué)習(xí)筆記之類與實(shí)例

一、定義

1.1、定義

類 (class) 封裝一組相關(guān)數(shù)據(jù),使之成為一個整體,并使用一種方法持續(xù)展示和維護(hù)。

這有點(diǎn)像把零件組裝成整車提供給用戶,無須了解汽車的內(nèi)部結(jié)構(gòu)和工作原理,只要知道方向盤,剎車和油門這些外部接口就可以正常行駛。

類存在兩種關(guān)系

  • 繼承(inheritance,is-a)自某個族類
    繼承可以用來表達(dá)本車屬于某廠的哪個車族系列,除了繼承原車系的技術(shù)和優(yōu)勢,還可基于某些環(huán)境進(jìn)行改進(jìn)。
  • 組合(composition,has-a)了哪些部件
    組合可用來表述該車使用了哪些零部件,比如最新的發(fā)動機(jī)。
  • 類與模塊的不同之處

  • 類可生成多個實(shí)例。
  • 類可被繼承和擴(kuò)展。
  • 類實(shí)例的生命周期可控。
  • 類支持運(yùn)算符,可按需重載。
  • 這些特性模塊沒有或者不需要,同時,模塊粒度大,模塊可用來提供游戲場景級別的解決方案,而類則是該場景下的特定家族和演員。

    1.2、創(chuàng)建

    定義類,以此為個體為例。關(guān)鍵字 class 同樣是運(yùn)行期指令,用于完成類型對象的創(chuàng)建。

    class User:pass可在函數(shù)內(nèi)定義,以限制其作用范圍。

    類型與實(shí)例

    如果類在模塊中定義,那么其生命周期與模塊等同,如果被放在函數(shù)內(nèi),那么每次都是新建。即便名字和內(nèi)容相同,也屬于不同類型。

    def test():class X:passreturn X()?>>> a,b = test(),test()>>> a.__class__ is b.__class__Out[1]: False函數(shù)內(nèi)定義的類型對象,在所有實(shí)例死亡后,會被垃圾回收。

    類型對象除了用來創(chuàng)建實(shí)例,也為所有實(shí)例定義了基本操作接口,其負(fù)責(zé)管理整個家族的可共享數(shù)據(jù)和行為目標(biāo)。

    實(shí)例只保存私有特征,其以內(nèi)部引用從所屬類型或其它所屬祖先類查找所需的方法,用來驅(qū)動展現(xiàn)個體面貌。

    名字空間

    類型有自己的名字空間,存儲當(dāng)前類型定義的字段和方法。這其中并不包括所繼承的祖先成員,其同樣以引用關(guān)聯(lián)祖先類型,無須復(fù)制到本地。

    class A:a = 100 #類字段def __init__(self, x): #實(shí)例初始化方法self.x = x #實(shí)例字段def_get_x(self): #實(shí)例方法return self.xclass B(A): #繼承自Ab = "hello"def __init__(self, x, y):super().__init__(self,x) #調(diào)用父類的初始化方法self.y = ydef get_y(self):return self.y

    實(shí)例 instance o 會保存所有繼承層次的實(shí)例字段,因?yàn)檫@些都屬于其私有數(shù)據(jù)。

    >>> o = B(1,2)>>> print(A.__dict__){'a': 100,'__init__': <function A.__init__ at 0x109d04f28>, '_get_x': <function A._get_x at 0x109d046a8>, ...}>>> print(B.__dict__){'b': 'hello', '__init__': <function B.__init__ at 0x109d272f0>, 'get_y': <function B.get_y at 0x109d27378>, ...}

    當(dāng)通過實(shí)例或類訪問某個成員時,會從當(dāng)前對象開始(instance o 開始查找),依次由近到遠(yuǎn)向祖先類查找

    (即 o --> class B --> class A 進(jìn)行成員查找)。

    如此做的好處就是祖先類的新增功能可以直接 【廣播】給所有后代。

    在繼承層次的不同名字空間中允許有同名成員,并按順序優(yōu)先命中。

    二、字段

    依照所處空間不同,我們將字段分為類型字段和實(shí)例字段。

    官方將成員統(tǒng)稱為 Attribute,我們可按例將數(shù)據(jù)當(dāng)做字段。

    2.1、類型字段

    【類型字段】在 class 語句塊內(nèi)直接定義,而實(shí)例字段必須通過實(shí)例引用(self)賦值定義。

    僅從執(zhí)行方式來看,無論實(shí)例方法存在于哪級類型,其隱式參數(shù) self 總指向當(dāng)前調(diào)用實(shí)例。

    class A:def test(self): #self 總是指向引用的當(dāng)前實(shí)例,這與繼承層次無關(guān)print(self)self.x = 100class B(A):pass?if __name__=="__main__":o = B()print(hex(id(o)))print(o.test())0x109d2f358 <__main__.B object at 0x109d2f358> 實(shí)例參數(shù) self 只是約定成俗的名字,這類似于其它語言中的 this,換成 this 同樣有效。

    2.2、字段賦值

    可使用賦值語句為類型或?qū)嵗砑拥男伦侄巍?/p> class A: pass?if __name__=="__main__":A.x = 100 #新增類型字段print(A.x)print(vars(A))?'''100{x': 100, ...}'''

    可一旦實(shí)例重新賦值,就將會在其名字空間建立同名字段,并會遮蔽原字段。

    a = A()a.b = 200print(a.b)print(vars(a))'''200{'b': 200}'''

    2.3、私有字段

    將私有字段暴露給用戶是很危險(xiǎn)的。因?yàn)闊o論是修改還是刪除都無法截獲,由此可能引發(fā)意外錯誤。因?yàn)檎Z言沒有嚴(yán)格意義上的訪問權(quán)限設(shè)置,所以只好將它們隱藏起來。

    如果成員名字以雙下劃線開頭,但沒有以雙下劃線結(jié)尾,那么編譯器會自動對其重命名。

    class X:__table = "user" #類型變量def __init__(self,name):self.name = name #實(shí)例變量def get_name(self):return self.name同時雙下劃線開頭課結(jié)尾的,通常是系統(tǒng)方法,比如 __ init __ ,__ hash __ ,__ main __等。

    所謂重命名,就是編譯器附加了類型名稱前綴。雖然這種做法不能真正阻止用戶訪問,但基于名字的約定也算一種提示。這種方式讓繼承類也無法訪問。

    重命名機(jī)制總是針對當(dāng)前類型,繼承類型無法訪問重命名后的基類成員。

    可將雙下劃線前綴改為單下劃線,這樣雖然不能自動重命名,不過提示作用依舊。

    class A:__name = "user" #雙下劃線成員class B(A):def test(self):print(self.__name)?>>> B().test()'''AttributeError: 'B' object has no attribute '_B__name''''?class A:_name = "user" #單下劃線成員class B(A):def test(self):print(self._name)>>> B().test()'''user'''

    三、屬性

    對私有字段會進(jìn)行重命名保護(hù),那公開字段如何處理呢?

    問題是核心在于訪問攔截,必須由內(nèi)部邏輯決定如何返回結(jié)果。而屬性(property)機(jī)制就是將讀、寫和刪除操作映射到指定的方法調(diào)用上,從而實(shí)現(xiàn)操作控制。

    class C:def __init__(self, name):self.__name = name@propertydef name(self): #讀return self.__name?@name.setterdef name(self, value): #寫self.__name = value @name.deleterdef name(self): #刪除raise AttributeError("can't delete attribute")?c = C("user")print(c.name)# user c.name = "abc"print(c.name)# abcdel c.nameprint(c.name)#can't delete attribute這種 @ 語法被稱作裝飾器(decorator)。
    多個方法名必須相同,默認(rèn)從讀方法尅是定義屬性,隨后以屬性名定義寫和刪除。
    如果實(shí)現(xiàn)只讀,或禁止刪除,則只需去掉對應(yīng)的方法即可。

    四、方法

    方法是一種特殊函數(shù),其與特定對象綁定,用來獲取或修改對象狀態(tài)。

    實(shí)際上,無論是對象構(gòu)造,初始化,析構(gòu)還是運(yùn)算符,都以方法實(shí)現(xiàn)。根據(jù)綁定目標(biāo)和調(diào)用方法的不同,方法可分為實(shí)例方法,類型方法,以及靜態(tài)方法。

    名字以上下劃線開始和結(jié)束的方法,通常有特殊用途,其由解釋器和內(nèi)部機(jī)制調(diào)用。

    實(shí)例方法

    實(shí)例方法與實(shí)例對象綁定,在其參數(shù)列表中,將綁定對象作為第一參數(shù),以便在方法中讀取或修改數(shù)據(jù)狀態(tài)。在以實(shí)例引用調(diào)用方法時,無須顯式傳入第一實(shí)參,而由解釋器自動完成。

    官方建議參數(shù)名用 self,同樣以 cls 作為類型方法的第一參數(shù)名。 class W:def __init__(self, name):self.__name = namedef get(self): #以實(shí)例引用調(diào)用,自動傳入 self 參數(shù)return self.__namedef set(self, value):self.__name = value>>> w = W("python")>>> w.get() #忽略第一參數(shù)'''python'''

    類型方法

    類型方法用來維護(hù)類型狀態(tài),面向族群提供服務(wù)接口。除綁定的第一參數(shù)名稱不同外,還需添加專門的裝飾器,以便解釋器將其實(shí)例方法區(qū)分開來。

    class D:__data = "D.data"@classmethod #定義為類型方法def get(cls): #解釋器自動將類型對象 D 作為 cls 參數(shù)傳入return cls.__data@classmethoddef set(cls, value):cls.__data = value>>> D.get() #同樣忽略 cls 參數(shù)'''D.data'''

    靜態(tài)方法

    靜態(tài)方法,則更像是普通函數(shù)。其既不接收實(shí)例引用,也不參與類型處理,所以就沒有自動傳入第一參數(shù)。使用靜態(tài)方法,更多原因是將類型作為一個作用域,或者當(dāng)前類型添加便捷接口。

    class DES:def __init__(self, key):self.__key = keydef encrypt_bytes(self, value):return str(self.__key) + str(value)@staticmethoddef encrypt(key, s):return DES(key).encrypt_bytes(s.encode("utf-8"))>>> DES.encrypt("key", "value")'''keyb'value''''

    特殊方法

    下面又解釋器自動調(diào)用,與對象生命周期相關(guān)的方法。

  • __ new __:構(gòu)造方法,創(chuàng)建對象實(shí)例
  • __ init __:初始化方法,設(shè)置實(shí)例的相關(guān)屬性
  • __ del __:析構(gòu)方法,實(shí)例被回收時調(diào)用
  • 創(chuàng)建實(shí)例時,會先調(diào)用析構(gòu)方法和初始化方法。

    class E:def __new__(cls, *args): #與__init__接收相同的調(diào)用函數(shù)print("__new__", args)return super().__new__(cls)def __init__(self, *args): ##self 由 __new__創(chuàng)建并返回print("__init__", args)>>> E(1,2)'''__new__ (1, 2)__init__ (1, 2)'''

    如果 __ new __ 返回實(shí)例與 cls 類型不符,將導(dǎo)致 __ init __ 無法執(zhí)行。

    五、總結(jié)

    學(xué)習(xí)到此,我總算把類的創(chuàng)建,屬性和方法等弄清楚了,我最想強(qiáng)調(diào)一點(diǎn),希望讀者把 實(shí)例 self 參數(shù)弄明白,后續(xù)編碼過程中使用較多。

    還要清楚實(shí)例方法和靜態(tài)方法的區(qū)別。

    總結(jié)

    以上是生活随笔為你收集整理的命名空间不能直接包含字段或方法之类的成员是什么意思_Python 学习笔记之类与实例...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。