python的描述符
Ⅰ 請問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)
其他情況見文末參考資料的文檔
- 這個調用也屬於無條件調用,這點與__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為前綴的方法都是獲取對象內部數據的鉤子,名稱不一樣,用途也存在較大的差異,只有在實踐中理解它們,才能真正掌握它們的用法。
四、__getitem__方法
如果僅僅想要對象能夠通過[]獲取對象屬性可以簡單的:
總結
當這幾個方法同時出現可能就會擾亂你了。我在網上看到一份示例還不錯,稍微改了下:
Ⅳ 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
若資源有問題歡迎追問~
Ⅶ 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+只能寫到文件末尾(無論當前文件指針在哪裡)。