當前位置:首頁 » 編程語言 » python的描述符

python的描述符

發布時間: 2022-08-27 10:07:49

Ⅰ 請問python描述符property中的self.fget(instance)怎麼理解

self.fget等價於 __init__(self,fget=None,fset=None,fdel=None) 方法中的 fset參數
==================看這下面=================================
class C:
def __init__(self):
self._x = None
def getX(self):
return self._x
def setX(self, value):
self._x = value
def delX(self):
del self._x
x = MyProperty(getX, setX, delX)
執行上面的語句後self.fget就等於類C里的getX
self.fget(instance)等價於調用C里的getX(instance)方法
===========我是新手剛看到這如有興趣可共同學習================

Ⅱ python 函數是不是描述符

在Python中,訪問一個屬性的優先順序順序按照如下順序:
1.類屬性
2.數據描述符
3.實例屬性
4.非數據描述符
5.__getattr__()方法。這個方法的完整定義如下所示:

[python] view plain
def __getattr__(self,attr) :#attr是self的一個屬性名
pass;

先來闡述下什麼叫數據描述符。

數據描述符是指實現了__get__,__set__,__del__方法的類屬性(由於Python中,一切皆是對象,所以你不妨把所有的屬性也看成是對象)

PS:個人覺得這里最好把數據描述符等效於定義了__get__,__set__,__del__三個方法的介面。

闡述下這三個方法:

__get__的標準定義是__get__(self,obj,type=None),它非常接近於JavaBean的get

第一個函數是調用它的實例,obj是指去訪問屬性所在的方法,最後一個type是一個可選參數,通常為None(這個有待於進一步的研究)

例如給定類X和實例x,調用x.foo,等效於調用:

type(x).__dict__["foo"].__get__(x,type(x))

調用X.foo,等效於調用:

type(x).__dict__["foo"].__get__(None,type(x))

第二個函數__set__的標準定義是__set__(self,obj,val),它非常接近於JavaBean的set方法,其中最後一個參數是要賦予的值

第三個函數__del__的標準定義是__del__(self,obj),它非常接近Java中Object的Finailize()方法,指
Python在回收這個垃圾對象時所調用到的析構函數,只是這個函數永遠不會拋出異常。因為這個對象已經沒有引用指向它,拋出異常沒有任何意義。

接下來,我們來一一比較這些優先順序.

首先來看類屬性

[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29

@author: naughty
'''
class A(object):
foo=3

print A.foo
a=A()
print a.foo
a.foo=4
print a.foo
print A.foo

上面這段代碼的輸出如下:

3
3
4
3

從輸出可以看到,當我們給a.foo賦值的時候,其實與類實例的那個foo是沒有關系的。a.foo=4 這句話給a對象增加了一個屬性叫foo。其值是4。

最後兩個語句明確的表明了,我們輸出a.foo和A.foo的值,他們是不同的。

但是為什麼a=A()語句後面的print
a.foo輸出了3呢?這是因為根據搜索順序找到了類屬性。當我們執行a.foo=4的時候,我們讓a對象的foo屬性指向了4這個對象。但是並沒有改變
類屬性foo的值。所以最後我們print A.foo的時候,又輸出了3。

[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29

@author: naughty
'''
class A(object):
foo=3

a=A()
a.foo=4
print a.foo
del a.foo
print a.foo

上面的代碼,我給a.foo賦值為4,在輸出一次之後就del了。兩次輸出,第一次輸出的是a對象的屬性。第二次是類屬性。不是說類屬性的優先順序比
實例屬性的高嗎。為啥第一次輸出的是4而不是3呢?還是上面解釋的原因。因為a.foo與類屬性的foo只是重名而已。我們print
a.foo的時候,a的foo指向的是4,所以輸出了4。

------------------------------------

然後我們來看下數據描述符這一全新的語言概念。按照之前的定義,一個實現了__get__,__set__,__del__的類都統稱為數據描述符。我們來看下一個簡單的例子。

[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29

@author: naughty
'''

class simpleDescriptor(object):

def __get__(self,obj,type=None):
pass

def __set__(self,obj,val):
pass

def __del__(self,obj):
pass

class A(object):
foo=simpleDescriptor()

print str(A.__dict__)
print A.foo
a=A()
print a.foo
a.foo=13
print a.foo

上面例子的輸出結果如下:

[plain] view plain
{'__dict__': <attribute '__dict__' of 'A' objects>, '__mole__': '__main__', 'foo': <__main__.simpleDescriptor object at 0x005511B0>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
None
None
None

從輸出結果看出,print語句列印出來的都是None。這說明a.foo都沒有被賦值內容。這是因為__get__函數的函數體什麼工作都沒有做。直接是pass。此時,想要訪問foo,每次都沒有返回內容,所以輸出的內容就是None了。

[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29

@author: naughty
'''

class simpleDescriptor(object):

def __get__(self,obj,type=None):
return "hi there"

def __set__(self,obj,val):
pass

def __del__(self,obj):
pass

class A(object):
foo=simpleDescriptor()

print str(A.__dict__)
print A.foo
a=A()
print a.foo
a.foo=13
print a.foo

把__get__函數實現以下,就可以得到如下輸出結果:

[plain] view plain
{'__dict__': <attribute '__dict__' of 'A' objects>, '__mole__': '__main__', 'foo': <__main__.simpleDescriptor object at 0x00671190>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
hi there
hi there
hi there

為了加深對數據描述符的理解,看如下例子:

[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29

@author: naughty
'''

class simpleDescriptor(object):
def __init__(self):
self.result = None;
def __get__(self, obj, type=None) :
return self.result - 10;
def __set__(self, obj, val):
self.result = val + 3;
print self.result;
def __del__(self, obj):
pass
class A(object):
foo = simpleDescriptor();
a = A();
a.foo = 13;
print a.foo;

上面代碼的輸出是

16

6

第一個16為我們在對a.foo賦值的時候,人為的將13加上3後作為foo的值,第二個6是我們在返回a.foo之前人為的將它減去了10。

所以我們可以猜測,常規的Python類在定義get,set方法的時候,如果無特殊需求,直接給對應的屬性賦值或直接返回該屬性值。如果自己定義類,並且繼承object類的話,這幾個方法都不用定義。

-----------------

在這里看一個題外話。

看代碼

[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29

@author: naughty
'''

class simpleDescriptor(object):
def __init__(self):
self.result = None;
def __get__(self, obj, type=None) :
return self.result - 10;
def __set__(self, obj, val):
if isinstance(val,str):
assert False,"int needed! but get str"
self.result = val + 3;
print self.result;
def __del__(self, obj):
pass
class A(object):
foo = simpleDescriptor();
a = A();
a.foo = "13";
print a.foo;

上面代碼在__set__ 函數中檢查了參數val,如果val是str類型的,那麼要報錯。這就實現了我們上一篇文章中要實現的,在給屬性賦值的時候做類型檢查的功能。

-----------------------------------------------

下面我們來看下實例屬性和非數據描述符。

[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29

@author: naughty
'''

class B(object):
foo = 1.3
b = B()
print b.__dict__
b.bar = 13
print b.__dict__
print b.bar

上面代碼輸出結果如下:

{}
{'bar': 13}
13

那麼什麼是非數據描述符呢?

簡單的說,就是沒有實現get,set,del三個方法的所有類。

讓我們任意看一個函數的描述:

def call():

pass

執行print dir(call)會得到如下結果:

[plain] view plain
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__mole__', '__name__', '__new__', '__rece__', '__rece_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

先看下dir的幫助。

dir列出給定對象的屬性或者是從這個對象能夠達到的對象。

回到print dir(call)方法的輸出,看到,call方法,有輸出的那麼多個屬性。其中就包含了__get__函數。但是卻沒有__set__和__del__函數。所以所有的類成員函數都是非數據描述符。

看一個實例數據掩蓋非數據描述符的例子:

[python] view plain
'''''
Created on 2013-3-29

@author: naughty
'''

class simpleDescriptor(object):
def __get__(self,obj,type=None) :
return "get",self,obj,type

class D(object):
foo=simpleDescriptor()
d=D()
print d.foo
d.foo=15
print d.foo

看輸出:

('get', <__main__.simpleDescriptor object at 0x02141190>,
<__main__.D object at 0x025CAF50>, <class '__main__.D'>)
15

可見,實例數據掩蓋了非數據描述符。

如果改成數據描述符,那麼就不會被覆蓋了。看下面:

[python] view plain
'''''
Created on 2013-3-29

@author: naughty
'''

class simpleDescriptor(object):
def __get__(self,obj,type=None) :
return "get",self,obj,type
def __set__(self,obj,type=None) :
pass
def __del__(self,obj,type=None) :
pass

class D(object):
foo=simpleDescriptor()
d=D()
print d.foo
d.foo=15
print d.foo

代碼的輸出如下:

[plain] view plain
('get', <__main__.simpleDescriptor object at 0x01DD1190>, <__main__.D object at 0x0257AF50>, <class '__main__.D'>)
('get', <__main__.simpleDescriptor object at 0x01DD1190>, <__main__.D object at 0x0257AF50>, <class '__main__.D'>)

由於是數據描述符,__set __函數體是pass,所以兩次輸出都是同樣的內容。

最後看下__getatrr__方法。它的標準定義是:__getattr__(self,attr),其中attr是屬性名

Ⅲ python類的屬性有哪幾種如何訪問它們

屬性的訪問機制

一般情況下,屬性訪問的默認行為是從對象的字典中獲取,並當獲取不到時會沿著一定的查找鏈進行查找。例如a.x的查找鏈就是,從a.__dict__['x'],然後是type(a).__dict__['x'],再通過type(a)的基類開始查找。

若查找鏈都獲取不到屬性,則拋出AttributeError異常。

一、__getattr__方法

這個方法是當對象的屬性不存在是調用。如果通過正常的機制能找到對象屬性的話,不會調用__getattr__方法。

classA:
a=1
def__getattr__(self,item):
print('__getattr__call')
returnitem

t=A()
print(t.a)
print(t.b)
#output
1
__getattr__call
b

二、__getattribute__方法

這個方法會被無條件調用。不管屬性存不存在。如果類中還定義了__getattr__,則不會調用__getattr__()方法,除非在__getattribute__方法中顯示調用__getattr__()或者拋出了AttributeError。

classA:
a=1
def__getattribute__(self,item):
print('__getattribute__call')
raiseAttributeError

def__getattr__(self,item):
print('__getattr__call')
returnitem

t=A()
print(t.a)
print(t.b)

所以一般情況下,為了保留__getattr__的作用,__getattribute__()方法中一般返回父類的同名方法:

def__getattribute__(self,item):
returnobject.__getattribute__(self,item)

使用基類的方法來獲取屬性能避免在方法中出現無限遞歸的情況。

三、__get__方法

這個方法比較簡單說明,它與前面的關系不大。

如果一個類中定義了__get__(),__set__()或__delete__()中的任何方法。則這個類的對象稱為描述符。

classDescri(object):
def__get__(self,obj,type=None):
print("callget")

def__set__(self,obj,value):
print("callset")

classA(object):
x=Descri()

a=A()
a.__dict__['x']=1#不會調用__get__
a.x#調用__get__
如果查找的屬性是在描述符對象中,則這個描述符會覆蓋上文說的屬性訪問機制,體現在查找鏈的不同,而這個行文也會因為調用的不同而稍有不一樣:

  • 如果調用是對象實例(題目中的調用方式),a.x則轉換為調用:。type(a).__dict__['x'].__get__(a, type(a))
  • 如果調用的是類屬性,A.x則轉換為:A.__dict__['x'].__get__(None, A)
  • 其他情況見文末參考資料的文檔

  • 四、__getitem__方法

  • 這個調用也屬於無條件調用,這點與__getattribute__一致。區別在於__getitem__讓類實例允許[]運算,可以這樣理解:
  • __getattribute__適用於所有.運算符;
  • __getitem__適用於所有[]運算符。
  • classA(object):

  • a=1


  • def__getitem__(self,item):

  • print('__getitem__call')

  • returnitem


  • t=A()

  • print(t['a'])

  • print(t['b'])

  • 如果僅僅想要對象能夠通過[]獲取對象屬性可以簡單的:

  • def__getitem(self,item):

  • returnobject.__getattribute__(self,item)

  • 總結

    當這幾個方法同時出現可能就會擾亂你了。我在網上看到一份示例還不錯,稍微改了下:

  • classC(object):

  • a='abc'


  • def__getattribute__(self,*args,**kwargs):

  • print("__getattribute__()iscalled")

  • returnobject.__getattribute__(self,*args,**kwargs)


  • #return"haha"

  • def__getattr__(self,name):

  • print("__getattr__()iscalled")

  • returnname+"fromgetattr"


  • def__get__(self,instance,owner):

  • print("__get__()iscalled",instance,owner)

  • returnself


  • def__getitem__(self,item):

  • print('__getitem__call')

  • returnobject.__getattribute__(self,item)


  • deffoo(self,x):

  • print(x)


  • classC2(object):

  • d=C()


  • if__name__=='__main__':

  • c=C()

  • c2=C2()

  • print(c.a)

  • print(c.zzzzzzzz)

  • c2.d

  • print(c2.d.a)

  • print(c['a'])

  • 可以結合輸出慢慢理解,這里還沒涉及繼承關系呢。總之,每個以__get為前綴的方法都是獲取對象內部數據的鉤子,名稱不一樣,用途也存在較大的差異,只有在實踐中理解它們,才能真正掌握它們的用法。

Ⅳ fluent python是什麼意思

《Fluent Python》是一本介紹Python的書。這本書並不是一本完備的 Python 使用手冊,而是會強調 Python 作為編程語言獨有的特性,這些特性或者是只有 Python 才具備的,或者是在其他大眾語言里很少見的。 Python語言核心以及它的一些庫會是本書的重點。

相關推薦:《Python基礎教程》

目標讀者:

正在使用 Python,又想熟悉 Python 3 的程序員 。

主題:

第一部分:

第一部分只有單獨的一章,講解的是 Python 的數據模型(data model),以及如何為了保證行為一致性而使用特殊方法(比如 __repr__),畢竟 Python 的一致性是出了名的。其實整本書幾乎都是在講解 Python 的數據模型,第 1 章算是一個概覽。

第二部分:

第二部分包含了各種集合類型:序列(sequence)、映射(mapping)和集合(set),另外還提及了字元串(str)和位元組序列(bytes)的區分。說起來,最後這一點也是讓親者(Python 3 用戶)快,仇者(Python 2 用戶)痛的一個關鍵,因為這個區分致使 Python 2 代碼遷移到 Python 3 的難度陡增。第二部分的目標是幫助讀者回憶起 Python內置的類庫,順帶解釋這些類庫的一些不太直觀的地方。具體的例子有 Python 3 如何在我們觀察不到的地方對 dict 的鍵重新排序,或者是排序有區域(locale)依賴的字元串時的注意事項。為了達到本部分的目標,有些地方的講解會比較大而全,像序列類型和映射類型的變種就是這樣;有時則會寫得很深入,比方說我會對 dict 和 set 底層的散列表進行深層次的討論。

第三部分:

第三部分首先會解釋,如何把函數作為一等對象(first-order object)來使用,然後話題延伸到這個概念對那些被廣泛使用的設計模型的影響,最後讀者會看到如何利用閉包(closure)的概念來實現函數裝飾器(function decorator)。這一部分的話題還包括 Python 的這些基本概念:可調用(callable)、函數屬性(functionattribute)、內省(introspection)、參數註解(parameter annotation)和 Python 3 里新出現的 nonlocal 聲明。

第四部分:

到了這里,書的重點轉移到了類的構建上面。雖然在第二部分里的例子里就有類聲明(class declaration)的出現,但是第四部分會呈現更多的類。和任何面向對象語言一樣,Python 還有些自己的特性,這些特性可能並不會出現在你我學習基於類的編程的語言中。這一部分的章節解釋了引用(reference)的原理、 「可變性」的概念、實例的生命周期、如何構建自定義的集合類型和 ABC、多重繼承該怎麼理順、什麼時候應該使用操作符重載及其方法。

第五部分:

Python 中有些結構和庫不再滿足於諸如條件判斷、循環和子程序(subroutine)之類的順序控制流程,第五部分的筆墨會集中在這些構造和庫上。我們會從生成器(generator)起步,然後話題會轉移到上下文管理器(context manager)和協程(coroutine),其中會涵蓋新增的功能強大但又不容易理解的 yield from 語法。這一部分以並發性和面向事件的 I/O 來結尾,其中跟並發性相關的是 collections.futures 這個很新的包,它藉助futures 包把線程和進程的概念給封裝了起來;而跟面向事件 I/O 相關的則是 asyncio,它的背後是基於協程和 yield from 的 futures 包。

第六部分:

第六部分的開頭會講到如何動態創建帶屬性的類,用以處理諸如JSON這類半結構化的數據。然後會從大家已經熟悉的特性(property)機制入手,用描述符從底層來解釋Python對象屬性的存取。同時,函數、方法和描述符的關系也會被梳理一遍。第六部分會從頭至尾地實現一個欄位驗證器,在這個過程中我們會遇到一些微妙的問題,然後在最後一章中就自然引出像類裝飾器(class decorator)和元類(metaclass)這些高級的概念。

Ⅳ python中用fileno沒返迴文件描述符,請問是怎麼回事

這個就是啊,你應該用一個變數來接收返回值,然後用變數來操作文件。

Ⅵ python高級編程技巧實戰怎麼樣

bobby《Python3高級核心技術97講》(超清視頻)網路網盤

鏈接: https://pan..com/s/1iJ9VvVE3Km_x4-RCfI5Anw

提取碼: ti4i 復制這段內容後打開網路網盤手機App,操作更方便哦

若資源有問題歡迎追問~

Ⅶ python的標識符有哪些

python函數的變數名,函數名都是標識符標識符遵循4點規則1 。標識符由字母、下劃線和數字組成2 。不能以數字開頭3 。區分大小寫4 。不能使用關字

定律是為實踐和事實所證明,反映事物在一定條件下發展變化的客觀規律的論斷。定律是一種理論模型,它用以描述特定情況、特定尺度下的現實世界,在其它尺度下可能會失效或者不準確。

沒有任何一種理論可以描述宇宙當中的所有情況,也沒有任何一種理論可能完全正確。人生同樣有其客觀規律可循。

一、生活定律 痛苦定律:死無疑是痛苦的,然而還有比死更痛苦的東西,那就是等死。

幸福定律:如果你不再總是想著自己是否幸福時,你就獲得幸福了。

錯誤定律:人人都會有過失,但是,只有重復這些過失時,你才犯了錯誤。

沉默定律:在辯論時,沉默是一種最難駁倒的觀點。

動力定律:動力往往只是起源於兩種原因:希望,或者絕望。

受辱定律:受辱時的唯一辦法是忽視它,不能忽視它時就藐視它;如果連藐視它也不能,那麼你就只能受辱了。

愚蠢定律:愚蠢大多是在手腳或舌頭運轉得比大腦還快的時候產生的。

化妝定律:在修飾打扮上花費的時間有多少,你就需要掩飾的缺點也就有多少。

省時定律:要想學會最節省時間的辦法,首先就需要學會說"不"。

地位定律:有人站在山頂上,有人站在山腳下,雖然所處的地位不同,但在兩者的眼中所看到的對方,卻是同樣大小的。

失敗定律:失敗並不以為著浪費時間與生命,卻往往意味著你又有理由去擁有新的時間與生命了。

談話定律:最使人厭煩的談話有兩種:從來不停下來想想;或者,從來也不想停下來。

誤解定律:被某個人誤解,麻煩並不大;被許多人誤解,那麻煩就大了。

結局定律:有一個可怕的結局,也比不上沒有任何結局可怕。

二、工作定律

安全定律:最安全的單位幾十年沒有得過安全獎(最安全證明你們安全沒有做工作)

需要定律:同樣兩個相同的單位,同樣的辦公費。多少年以後,發生了變化(證明你們單位辦公不需要那麼多的錢)出來反對,這種成功的概論會歸結為零。

評比定律:領導認為誰好,誰就好。(只要領導看你不順眼,再辛辛苦苦地工作也是白費力氣。)

一票否決定律:在一個單位,比如升工資,比如提拔任用,一個人提出來,往往成功的概率最大,而另一個人站

接受教育定律:每個單位都有吊兒郎當不好好乾工作的人。但領導往往在批評這些人的時候,這些人恰恰不在場,於是,便出現了遵紀守法的人,經常接受教育的尷尬局面。

哭鬧定律;那個部門沒有幾個因為經常的哭鬧而得到了實惠,他有什麼理由不經常哭鬧下去。(此定理也適用那些經常在領導面前叫苦叫累的部門)

能者多勞定律:在同一科室里,有的人雖然在其崗,但卻不能勝任本職工作,那他的工作只能由能勝任該項工作的人去代勞。

不平衡定律:年年當先進的部門或個人,一年沒有當先進便想不通;從未當先進的部門或個人,當上先進後便想不到。

少勞多得定律:一般的單位,都分為合同工、(過去稱為正式工)協議工、臨時工等等。拿錢越少的工作量越大,而且越容易被解僱;拿錢越多的越沒有多少事情可干,而且最不容易被解僱。

Ⅷ python中w、r表示什麼意思

文件讀寫就是一種常見的IO操作。

文件讀寫操作步驟

不同的編程語言讀寫文件的操作步驟大體都是一樣的,都分為以下幾個步驟:

1)打開文件,獲取文件描述符;

2)操作文件描述符--讀/寫;

3)關閉文件。

相關推薦:《Python教程》

文件打開模式:

r+、w+和a+都可以實現對文件的讀寫,那麼他們有什麼區別呢?

r+會覆蓋當前文件指針所在位置的字元,如原來文件內容是"Hello,World",打開文件後寫入"hi"則文件內容會變成"hillo, World"。

w+與r+的不同是,w+在打開文件時就會先將文件內容清空,不知道它有什麼用。

a+與r+的不同是,a+只能寫到文件末尾(無論當前文件指針在哪裡)。

熱點內容
python虛擬環境開發 發布:2025-01-17 04:04:34 瀏覽:690
編譯運行後保存exe文件 發布:2025-01-17 04:00:18 瀏覽:565
asm源碼編譯 發布:2025-01-17 03:54:24 瀏覽:287
如何配置svi介面的ip地址 發布:2025-01-17 03:48:09 瀏覽:44
微軟怎麼解壓縮文件 發布:2025-01-17 03:43:06 瀏覽:204
有沒有手機可以用的java編譯器 發布:2025-01-17 03:38:56 瀏覽:542
手把手教你學c語言版 發布:2025-01-17 03:38:52 瀏覽:781
最優化遺傳演算法 發布:2025-01-17 03:35:24 瀏覽:547
四代飛度家用需要加裝哪些配置 發布:2025-01-17 03:34:28 瀏覽:877
安卓手機貓和老鼠怎麼換號 發布:2025-01-17 03:23:58 瀏覽:470