目錄
前言
建構與初始化
__setattr__
登入後複製
登入後複製
登入後複製
登入後複製
" >
__setattr__
登入後複製
登入後複製
登入後複製
登入後複製
__delattr__
登入後複製
登入後複製
登入後複製
" >
__delattr__
登入後複製
登入後複製
登入後複製
__getattribute__
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
" >
__getattribute__
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
描述器对象
__get__(self, instance, owner)
登入後複製
" >
__get__(self, instance, owner)
登入後複製
__set__(self, instance, value)
登入後複製
" >
__set__(self, instance, value)
登入後複製
__delete__(self, instance)
登入後複製
" >
__delete__(self, instance)
登入後複製
构造自定义容器(Container)
__len__(self)
登入後複製
" >
__len__(self)
登入後複製
__getitem__(self, key)
登入後複製
" >
__getitem__(self, key)
登入後複製
__setitem__(self, key, value)
登入後複製
" >
__setitem__(self, key, value)
登入後複製
__delitem__(self, key)
登入後複製
" >
__delitem__(self, key)
登入後複製
__iter__(self)
登入後複製
" >
__iter__(self)
登入後複製
__reversed__(self)
登入後複製
" >
__reversed__(self)
登入後複製
__contains__(self, item)
登入後複製
" >
__contains__(self, item)
登入後複製
__missing__(self, key)
登入後複製
" >
__missing__(self, key)
登入後複製
上下文管理
__enter__(self)
登入後複製
" >
__enter__(self)
登入後複製
__exit__(self, exception_type, exception_value, traceback)
登入後複製
" >
__exit__(self, exception_type, exception_value, traceback)
登入後複製
对象的序列化
__getinitargs__(self)
登入後複製
" >
__getinitargs__(self)
登入後複製
__getnewargs__(self)
登入後複製
" >
__getnewargs__(self)
登入後複製
__getstate__(self)
登入後複製
" >
__getstate__(self)
登入後複製
__setstate__(self, state)
登入後複製
" >
__setstate__(self, state)
登入後複製
__reduce__(self)
登入後複製
" >
__reduce__(self)
登入後複製
__reduce_ex__(self)
登入後複製
" >
__reduce_ex__(self)
登入後複製
运算符相关的魔术方法
比较运算符
__cmp__(self, other)
登入後複製
" >
__cmp__(self, other)
登入後複製
__eq__(self, other)
登入後複製
" >
__eq__(self, other)
登入後複製
__ne__(self, other)
登入後複製
" >
__ne__(self, other)
登入後複製
__lt__(self, other)
登入後複製
" >
__lt__(self, other)
登入後複製
__gt__(self, other)
登入後複製
" >
__gt__(self, other)
登入後複製
__le__(self, other)
登入後複製
" >
__le__(self, other)
登入後複製
__ge__(self, other)
登入後複製
" >
__ge__(self, other)
登入後複製
一元运算符和函数
__pos__(self)
登入後複製
" >
__pos__(self)
登入後複製
__neg__(self)
登入後複製
" >
__neg__(self)
登入後複製
__invert__(self)
登入後複製
" >
__invert__(self)
登入後複製
__abs__(self)
登入後複製
" >
__abs__(self)
登入後複製
__round__(self, n)
登入後複製
" >
__round__(self, n)
登入後複製
__floor__(self)
登入後複製
" >
__floor__(self)
登入後複製
__ceil__(self)
登入後複製
" >
__ceil__(self)
登入後複製
__trunc__(self)
登入後複製
" >
__trunc__(self)
登入後複製
算术运算符
__add__(self, other)
登入後複製
" >
__add__(self, other)
登入後複製
__sub__(self, other)
登入後複製
" >
__sub__(self, other)
登入後複製
__mul__(self, other)
登入後複製
" >
__mul__(self, other)
登入後複製
__floorp__(self, other)
登入後複製
" >
__floorp__(self, other)
登入後複製
__p__(self, other)
登入後複製
" >
__p__(self, other)
登入後複製
__truep__
登入後複製
(self, other)" >
__truep__
登入後複製
(self, other)
__mod__(self, other)
登入後複製
" >
__mod__(self, other)
登入後複製
__pmod__(self, other)
登入後複製
" >
__pmod__(self, other)
登入後複製
__pow__(self, other)
登入後複製
" >
__pow__(self, other)
登入後複製
__lshift__(self, other)
登入後複製
" >
__lshift__(self, other)
登入後複製
__rshift__(self, other)
登入後複製
" >
__rshift__(self, other)
登入後複製
__and__(self, other)
登入後複製
" >
__and__(self, other)
登入後複製
__or__(self, other)
登入後複製
" >
__or__(self, other)
登入後複製
__xor__(self, other)
登入後複製
" >
__xor__(self, other)
登入後複製
反算术运算符
增量赋值
类型转化
__int__(self)
登入後複製
" >
__int__(self)
登入後複製
__long__(self)
登入後複製
" >
__long__(self)
登入後複製
__float__(self)
登入後複製
" >
__float__(self)
登入後複製
__complex__(self)
登入後複製
" >
__complex__(self)
登入後複製
__oct__(self)
登入後複製
" >
__oct__(self)
登入後複製
__hex__(self)
登入後複製
" >
__hex__(self)
登入後複製
__index__(self)
登入後複製
" >
__index__(self)
登入後複製
__coerce__(self, other)
登入後複製
" >
__coerce__(self, other)
登入後複製
其他魔术方法
__str__(self)
登入後複製
" >
__str__(self)
登入後複製
__repr__(self)
登入後複製
" >
__repr__(self)
登入後複製
__unicode__(self)
登入後複製
" >
__unicode__(self)
登入後複製
__format__(self, formatstr)
登入後複製
" >
__format__(self, formatstr)
登入後複製
__hash__(self)
登入後複製
" >
__hash__(self)
登入後複製
__nonzero__(self)
登入後複製
" >
__nonzero__(self)
登入後複製
__dir__(self)
登入後複製
" >
__dir__(self)
登入後複製
__sizeof__(self)
登入後複製
" >
__sizeof__(self)
登入後複製
__instancecheck__(self, instance)
登入後複製
" >
__instancecheck__(self, instance)
登入後複製
__subclasscheck__(self, subclass)
登入後複製
" >
__subclasscheck__(self, subclass)
登入後複製
__copy__(self)
登入後複製
" >
__copy__(self)
登入後複製
__deepcopy__(self, memodict={})
登入後複製
" >
__deepcopy__(self, memodict={})
登入後複製
__call__(self, [args...])
登入後複製
" >
__call__(self, [args...])
登入後複製
Python3中的差异
首頁 後端開發 Python教學 深入了解Python中的魔術方法

深入了解Python中的魔術方法

Mar 24, 2017 pm 04:07 PM
python

<h2 id="前言">前言</h2> <p>在Python中,所有以」__」雙底線包起來的方法,都統稱為」魔術方法」。例如我們接觸最多的</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>.<br>有些魔術方法,我們可能以後一輩子都不會再遇到了,這裡也就只是簡單介紹下;<br>而有些魔術方法,巧妙使用它可以建構出非常優美的程式碼,例如將複雜的邏輯封裝成簡單的API。 <br>本文編輯的思路借鑒自Rafe Kettler的這篇部落格: A Guide to Python Magic Methods,並補充了一些程式碼範例。 <br>介紹的順序大概是:常見的先介紹,越少見的越後講。 <br>本文中使用的程式碼範例,可以在我的github上下載到。 </p> <h2 id="建構與初始化">建構與初始化</h2> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>我們很熟悉了,它在物件初始化的時候呼叫,我們一般將它理解為」建構函式」.<br>實際上, 當我們呼叫</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">x = SomeClass()</pre><div class="contentsignin">登入後複製</div></div> <p>的時候呼叫,</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>並不是第一個執行的, </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>才是。所以準確來說,是</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>和</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>共同構成了」建構函式」.</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>是用來建立類別並傳回這個類別的實例, 而</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>只是將傳入的參數來初始化該實例.</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>在創建一個實例的過程中必定會被呼叫,但</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>就不一定,例如透過</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">pickle.load</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>的方式反序列化一個實例時就不會呼叫</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>。 </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法總是需要傳回該類別的一個實例,而</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>不能傳回除了None的任何值。例如下面範例:<br>class Foo(object):<br>    def __init__(self):<br>        print 'foo __init__'<br>      ):<br>        print 'foo __del__'<br>實際中,你很少會用到<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>,除非你希望能夠控制類別的創建。 <p>如果要講解<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>,往往需要牽扯到<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">metaclass</pre><div class="contentsignin">登入後複製</div></div>(元類別)的介紹。 <p>如果你有興趣深入,可以參考我的另一篇博客: 理解Python的metaclass<br>對於<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>的重載,Python文檔中也有了詳細的介紹。 <p>在物件的生命週期結束時, <br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__del__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>會被呼叫,可以將<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__del__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>理解為」構析函數」.<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__del__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>定義的是當一個物件進行垃圾回收時候的行為。 <p>有一點容易被誤解, 實際上,<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">x.__del__()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> 並不是對於<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">del x</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>的實作,但是往往執行<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">del x</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>時會呼叫<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">x.__del__()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> .<p>怎麼來理解這句話呢? 繼續用上面的Foo類別的程式碼為例:<br>foo = Foo()<br>foo.__del__()<br>print foo<br># del foo<br>print foo  # NameError, foo is not defined<br>如果呼叫了<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">foo.__del__()</pre><div class="contentsignin">登入後複製</div></div>,物件本身仍然存在. 但是呼叫了<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">del foo</pre><div class="contentsignin">登入後複製</div></div>, 就再也沒有foo這個對象了.<p>請注意,如果解釋器退出的時候物件還存在,就不能保證 <br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__del__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> 被確切的執行了。所以<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__del__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>並不能取代良好的程式設計習慣。 <p>例如,在處理socket時,及時關閉結束的連線。 <br></p>屬性存取控制<h2></h2>總是有人要吐槽Python缺少對於類別的封裝,例如希望Python能夠定義私有屬性,然後提供公共可存取的getter和 setter。 Python其實可以透過魔術方法來實現封裝。 <p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattr__(self, name)</pre><div class="contentsignin">登入後複製</div></div> <h3></h3>該方法定義了你試圖存取一個不存在的屬性時的行為。因此,重載該方法可以實現捕獲錯誤拼寫然後進行重定向, 或對一些廢棄的屬性進行警告。 <p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setattr__(self, name, value)</pre><div class="contentsignin">登入後複製</div></div> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-pre-setattr-pre-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div></h3> 是實現封裝的解決方案,它定義了你對屬性進行賦值和修改操作時的行為。 <p>不管物件的某個屬性是否存在,它都允許你為該屬性進行賦值,因此你可以為屬性的值進行自訂操作。有一點要注意,實作<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>時要避免」無限遞迴」的錯誤,下面的程式碼範例會提到。 <p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delattr__(self, name)</pre><div class="contentsignin">登入後複製</div></div> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-pre-delattr-pre-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div></h3>與<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>很像,只是它定義的是你刪除屬性時的行為。實作<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>是同時要避免」無限遞迴」的錯誤。 <p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattribute__(self, name)</pre><div class="contentsignin">登入後複製</div></div> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-div-class-code-style-position-relative-padding-px-margin-px-pre-getattribute-pre-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattribute__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div></h3>定義了你的屬性被存取時的行為,相比較,<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>只有該屬性不存在時才會起作用。 <p>因此,在支援<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattribute__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>的Python版本,呼叫<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>前必定會用 <p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattribute__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>。 <p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattribute__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>同樣要避免」無限遞迴」的錯誤。 <p>要提醒的是,最好不要嘗試去實作<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getattribute__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>,因為很少見到這種做法,而且很容易出bug。 <p>範例說明<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>的無限遞迴錯誤:<p>def __setattr__(self, name, value):<br>    self.name = value<br>    # 每一次屬性賦值時, __setattr__都會被調用,因此不斷調用自身導致無限遞歸了。 <br>因此正確的寫法應該是:<br>def __setattr__(self, name, value):<br>    self.__dict__[name] = value<br></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delattr__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>如果在其實作中出現<p></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">del self.name</pre><div class="contentsignin">登入後複製</div></div> <p> 这样的代码也会出现”无限递归”错误,这是一样的原因。<br>下面的例子很好的说明了上面介绍的4个魔术方法的调用情况:<br>class Access(object):<br>    def __getattr__(self, name):<br>        print '__getattr__'<br>        return super(Access, self).__getattr__(name)<br>    def __setattr__(self, name, value):<br>        print '__setattr__'<br>        return super(Access, self).__setattr__(name, value)<br>    def __delattr__(self, name):<br>        print '__delattr__'<br>        return super(Access, self).__delattr__(name)<br>    def __getattribute__(self, name):<br>        print '__getattribute__'<br>        return super(Access, self).__getattribute__(name)<br>access = Access()<br>access.attr1 = True  # __setattr__调用<br>access.attr1  # 属性存在,只有__getattribute__调用<br>try:<br>    access.attr2  # 属性不存在, 先调用__getattribute__, 后调用__getattr__<br>except AttributeError:<br>    pass<br>del access.attr1  # __delattr__调用</p> <h2 id="描述器对象">描述器对象</h2> <p>我们从一个例子来入手,介绍什么是描述符,并介绍</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__get__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__set__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delete__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p> 的使用。(放在这里介绍是为了跟上一小节介绍的魔术方法作对比)<br>我们知道,距离既可以用单位”米”表示,也可以用单位”英尺”表示。现在我们定义一个类来表示距离,它有两个属性: 米和英尺。<br>class Meter(object):<br>    '''Descriptor for a meter.'''<br>    def __init__(self, value=0.0):<br>        self.value = float(value)<br>    def __get__(self, instance, owner):<br>        return self.value<br>    def __set__(self, instance, value):<br>        self.value = float(value)<br>class Foot(object):<br>    '''Descriptor for a foot.'''<br>    def __get__(self, instance, owner):<br>        return instance.meter * 3.2808<br>    def __set__(self, instance, value):<br>        instance.meter = float(value) / 3.2808<br>class Distance(object):<br>    meter = Meter()<br>    foot = Foot()<br>d = Distance()<br>print d.meter, d.foot  # 0.0, 0.0<br>d.meter = 1<br>print d.meter, d.foot  # 1.0 3.2808<br>d.meter = 2<br>print d.meter, d.foot  # 2.0 6.5616<br>在上面例子中,在还没有对Distance的实例赋值前, 我们认为meter和foot应该是各自类的实例对象, 但是输出却是数值。这是因为</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__get__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>发挥了作用.<br>我们只是修改了meter,并且将其赋值成为int,但foot也修改了。这是</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__set__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>发挥了作用.<br>描述器对象(Meter、Foot)不能独立存在, 它需要被另一个所有者类(Distance)所持有。<br>描述器对象可以访问到其拥有者实例的属性,比如例子中Foot的</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">instance.meter</pre><div class="contentsignin">登入後複製</div></div> <p>。<br>在面向对象编程时,如果一个类的属性有相互依赖的关系时,使用描述器来编写代码可以很巧妙的组织逻辑。在Django的ORM中, models.Model中的InterField等字段, 就是通过描述器来实现功能的。<br>一个类要成为描述器,必须实现</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__get__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__set__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delete__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p> 中的至少一个方法。下面简单介绍下:</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-get-self-instance-owner-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__get__(self, instance, owner)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>参数instance是拥有者类的实例。参数owner是拥有者类本身。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__get__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>在其拥有者对其读值的时候调用。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-set-self-instance-value-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__set__(self, instance, value)</pre><div class="contentsignin">登入後複製</div></div></h3> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__set__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>在其拥有者对其进行修改值的时候调用。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-delete-self-instance-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delete__(self, instance)</pre><div class="contentsignin">登入後複製</div></div></h3> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delete__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>在其拥有者对其进行删除的时候调用。</p> <h2 id="构造自定义容器-Container">构造自定义容器(Container)</h2> <p>在Python中,常见的容器类型有: dict, tuple, list, string。<br>其中tuple, string是不可变容器,dict, list是可变容器。<br>可变容器和不可变容器的区别在于,不可变容器一旦赋值后,不可对其中的某个元素进行修改。<br>比如定义了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">l = [1, 2, 3]</pre><div class="contentsignin">登入後複製</div></div> <p>和</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">t = (1, 2, 3)</pre><div class="contentsignin">登入後複製</div></div> <p>后, 执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">l[0] = 0</pre><div class="contentsignin">登入後複製</div></div> <p>是可以的,但执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">t[0] = 0</pre><div class="contentsignin">登入後複製</div></div> <p>则会报错。<br>如果我们要自定义一些数据结构,使之能够跟以上的容器类型表现一样,那就需要去实现某些协议。<br>这里的协议跟其他语言中所谓的”接口”概念很像,一样的需要你去实现才行,只不过没那么正式而已。<br>如果要自定义不可变容器类型,只需要定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__len__</pre><div class="contentsignin">登入後複製</div></div> <p> 和 </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getitem__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法;<br>如果要自定义可变容器类型,还需要在不可变容器类型的基础上增加定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setitem__</pre><div class="contentsignin">登入後複製</div></div> <p> 和 </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delitem__</pre><div class="contentsignin">登入後複製</div></div> <p>。<br>如果你希望你的自定义数据结构还支持”可迭代”, 那就还需要定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__iter__</pre><div class="contentsignin">登入後複製</div></div> <p>。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-len-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__len__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>需要返回数值类型,以表示容器的长度。该方法在可变容器和不可变容器中必须实现。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-getitem-self-key-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getitem__(self, key)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>当你执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">self[key]</pre><div class="contentsignin">登入後複製</div></div> <p>的时候,调用的就是该方法。该方法在可变容器和不可变容器中也都必须实现。<br>调用的时候,如果key的类型错误,该方法应该抛出TypeError;<br>如果没法返回key对应的数值时,该方法应该抛出ValueError。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-setitem-self-key-value-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setitem__(self, key, value)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>当你执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">self[key] = value</pre><div class="contentsignin">登入後複製</div></div> <p>时,调用的是该方法。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-delitem-self-key-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__delitem__(self, key)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>当你执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">del self[key]</pre><div class="contentsignin">登入後複製</div></div> <p>的时候,调用的是该方法。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-iter-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__iter__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>该方法需要返回一个迭代器(iterator)。当你执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">for x in container:</pre><div class="contentsignin">登入後複製</div></div> <p> 或者使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">iter(container)</pre><div class="contentsignin">登入後複製</div></div> <p>时,该方法被调用。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-reversed-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__reversed__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>如果想要该数据结构被內建函数</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">reversed()</pre><div class="contentsignin">登入後複製</div></div> <p>支持,就还需要实现该方法。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-contains-self-item-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__contains__(self, item)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>如果定义了该方法,那么在执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">item in container</pre><div class="contentsignin">登入後複製</div></div> <p> 或者 </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">item not in container</pre><div class="contentsignin">登入後複製</div></div> <p>时该方法就会被调用。<br>如果没有定义,那么Python会迭代容器中的元素来一个一个比较,从而决定返回True或者False。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-missing-self-key-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__missing__(self, key)</pre><div class="contentsignin">登入後複製</div></div></h3> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">dict</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>字典类型会有该方法,它定义了key如果在容器中找不到时触发的行为。<br>比如</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">d = {'a': 1}</pre><div class="contentsignin">登入後複製</div></div> <p>, 当你执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">d[notexist]</pre><div class="contentsignin">登入後複製</div></div> <p>时,</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">d.__missing__['notexist']</pre><div class="contentsignin">登入後複製</div></div> <p>就会被调用。<br>下面举例,使用上面讲的魔术方法来实现Haskell语言中的一个数据结构。<br># -*- coding: utf-8 -*-<br>class FunctionalList:<br>    ''' 实现了内置类型list的功能,并丰富了一些其他方法: head, tail, init, last, drop, take'''<br>    def __init__(self, values=None):<br>        if values is None:<br>            self.values = []<br>        else:<br>            self.values = values<br>    def __len__(self):<br>        return len(self.values)<br>    def __getitem__(self, key):<br>        return self.values[key]<br>    def __setitem__(self, key, value):<br>        self.values[key] = value<br>    def __delitem__(self, key):<br>        del self.values[key]<br>    def __iter__(self):<br>        return iter(self.values)<br>    def __reversed__(self):<br>        return FunctionalList(reversed(self.values))<br>    def append(self, value):<br>        self.values.append(value)<br>    def head(self):<br>        # 获取第一个元素<br>        return self.values[0]<br>    def tail(self):<br>        # 获取第一个元素之后的所有元素<br>        return self.values[1:]<br>    def init(self):<br>        # 获取最后一个元素之前的所有元素<br>        return self.values[:-1]<br>    def last(self):<br>        # 获取最后一个元素<br>        return self.values[-1]<br>    def drop(self, n):<br>        # 获取所有元素,除了前N个<br>        return self.values[n:]<br>    def take(self, n):<br>        # 获取前N个元素<br>        return self.values[:n]<br>我们再举个例子,实现Perl语言的autovivification,它会在你每次引用一个值未定义的属性时为你自动创建数组或者字典。<br>class AutoVivification(dict):<br>    """Implementation of perl's autovivification feature."""<br>    def __missing__(self, key):<br>        value = self[key] = type(self)()<br>        return value<br>weather = AutoVivification()<br>weather['china']['guangdong']['shenzhen'] = 'sunny'<br>weather['china']['hubei']['wuhan'] = 'windy'<br>weather['USA']['California']['Los Angeles'] = 'sunny'<br>print weather<br>结果输出:{'china': {'hubei': {'wuhan': 'windy'}, 'guangdong': {'shenzhen': 'sunny'}}, 'USA':    {'California': {'Los Angeles': 'sunny'}}}<br>在Python中,关于自定义容器的实现还有更多实用的例子,但只有很少一部分能够集成在Python标准库中,比如Counter, OrderedDict等</p> <h2 id="上下文管理">上下文管理</h2> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">with</pre><div class="contentsignin">登入後複製</div></div> <p>声明是从Python2.5开始引进的关键词。你应该遇过这样子的代码:<br>with open('foo.txt') as bar:<br>    # do something with bar<br>在with声明的代码段中,我们可以做一些对象的开始操作和清除操作,还能对异常进行处理。<br>这需要实现两个魔术方法: </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__enter__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p> 和 </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__exit__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-enter-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__enter__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__enter__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>会返回一个值,并赋值给</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">as</pre><div class="contentsignin">登入後複製</div></div> <p>关键词之后的变量。在这里,你可以定义代码段开始的一些操作。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-exit-self-exception-type-exception-value-traceback-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__exit__(self, exception_type, exception_value, traceback)</pre><div class="contentsignin">登入後複製</div></div></h3> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__exit__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>定义了代码段结束后的一些操作,可以这里执行一些清除操作,或者做一些代码段结束后需要立即执行的命令,比如文件的关闭,socket断开等。如果代码段成功结束,那么exception_type, exception_value, traceback 三个参数传进来时都将为None。如果代码段抛出异常,那么传进来的三个参数将分别为: 异常的类型,异常的值,异常的追踪栈。<br>如果</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__exit__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>返回True, 那么with声明下的代码段的一切异常将会被屏蔽。<br>如果</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__exit__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>返回None, 那么如果有异常,异常将正常抛出,这时候with的作用将不会显现出来。<br>举例说明:<br>这该示例中,IndexError始终会被隐藏,而TypeError始终会抛出。<br>class DemoManager(object):<br>    def __enter__(self):<br>        pass<br>    def __exit__(self, ex_type, ex_value, ex_tb):<br>        if ex_type is IndexError:<br>            print ex_value.__class__<br>            return True<br>        if ex_type is TypeError:<br>            print ex_value.__class__<br>            return  # return None<br>with DemoManager() as nothing:<br>    data = [1, 2, 3]<br>    data[4]  # raise IndexError, 该异常被__exit__处理了<br>with DemoManager() as nothing:<br>    data = [1, 2, 3]<br>    data['a']  # raise TypeError, 该异常没有被__exit__处理<br>输出:<br><type 'exceptions.IndexError'><br><type 'exceptions.TypeError'><br>Traceback (most recent call last):<br>  ...</p> <h2 id="对象的序列化">对象的序列化</h2> <p>Python对象的序列化操作是pickling进行的。pickling非常的重要,以至于Python对此有单独的模块</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">pickle</pre><div class="contentsignin">登入後複製</div></div> <p>,还有一些相关的魔术方法。使用pickling, 你可以将数据存储在文件中,之后又从文件中进行恢复。<br>下面举例来描述pickle的操作。从该例子中也可以看出,如果通过pickle.load 初始化一个对象, 并不会调用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法。<br># -*- coding: utf-8 -*-<br>from datetime import datetime<br>import pickle<br>class Distance(object):<br>    def __init__(self, meter):<br>        print 'distance __init__'<br>        self.meter = meter<br>data = {<br>    'foo': [1, 2, 3],<br>    'bar': ('Hello', 'world!'),<br>    'baz': True,<br>    'dt': datetime(2016, 10, 01),<br>    'distance': Distance(1.78),<br>}<br>print 'before dump:', data<br>with open('data.pkl', 'wb') as jar:<br>    pickle.dump(data, jar)  # 将数据存储在文件中<br>del data<br>print 'data is deleted!'<br>with open('data.pkl', 'rb') as jar:<br>    data = pickle.load(jar)  # 从文件中恢复数据<br>print 'after load:', data<br>值得一提,从其他文件进行pickle.load操作时,需要注意有恶意代码的可能性。另外,Python的各个版本之间,pickle文件可能是互不兼容的。<br>pickling并不是Python的內建类型,它支持所有实现pickle协议(可理解为接口)的类。pickle协议有以下几个可选方法来自定义Python对象的行为。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-getinitargs-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getinitargs__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>如果你希望unpickle时,</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法能够调用,那么就需要定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getinitargs__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, 该方法需要返回一系列参数的元组,这些参数就是传给</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__init__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>的参数。<br>该方法只对</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">old-style class</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>有效。所谓</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">old-style class</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>,指的是不继承自任何对象的类,往往定义时这样表示: </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">class A:</pre><div class="contentsignin">登入後複製</div></div> <p>, 而非</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">class A(object):</pre><div class="contentsignin">登入後複製</div></div> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-getnewargs-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getnewargs__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>跟</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getinitargs__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>很类似,只不过返回的参数元组将传值给</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__new__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-getstate-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getstate__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>在调用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">pickle.dump</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>时,默认是对象的</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__dict__</pre><div class="contentsignin">登入後複製</div></div> <p>属性被存储,如果你要修改这种行为,可以在</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getstate__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法中返回一个state。state将在调用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">pickle.load</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>时传值给</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setstate__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-setstate-self-state-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setstate__(self, state)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>一般来说,定义了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getstate__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>,就需要相应地定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__setstate__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>来对</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getstate__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>返回的state进行处理。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-reduce-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__reduce__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>如果pickle的数据包含了自定义的扩展类(比如使用C语言实现的Python扩展类)时,就需要通过实现</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__reduce__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法来控制行为了。由于使用过于生僻,这里就不展开继续讲解了。<br>令人容易混淆的是,我们知道, </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">reduce()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>是Python的一个內建函数, 需要指出</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__reduce__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>并非定义了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">reduce()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>的行为,二者没有关系。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-reduce-ex-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__reduce_ex__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__reduce_ex__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p> 是为了兼容性而存在的, 如果定义了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__reduce_ex__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, 它将代替</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__reduce__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p> 执行。<br>下面的代码示例很有意思,我们定义了一个类Slate(中文是板岩的意思)。这个类能够记录历史上每次写入给它的值,但每次</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">pickle.dump</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>时当前值就会被清空,仅保留了历史。<br># -*- coding: utf-8 -*-<br>import pickle<br>import time<br>class Slate:<br>    '''Class to store a string and a changelog, and forget its value when pickled.'''<br>    def __init__(self, value):<br>        self.value = value<br>        self.last_change = time.time()<br>        self.history = []<br>    def change(self, new_value):<br>        # 修改value, 将上次的valeu记录在history<br>        self.history.append((self.last_change, self.value))<br>        self.value = new_value<br>        self.last_change = time.time()<br>    def print_changes(self):<br>        print 'Changelog for Slate object:'<br>        for k, v in self.history:<br>            print '%s    %s' % (k, v)<br>    def __getstate__(self):<br>        # 故意不返回self.value和self.last_change,<br>        # 以便每次unpickle时清空当前的状态,仅仅保留history<br>        return self.history<br>    def __setstate__(self, state):<br>        self.history = state<br>        self.value, self.last_change = None, None<br>slate = Slate(0)<br>time.sleep(0.5)<br>slate.change(100)<br>time.sleep(0.5)<br>slate.change(200)<br>slate.change(300)<br>slate.print_changes()  # 与下面的输出历史对比<br>with open('slate.pkl', 'wb') as jar:<br>    pickle.dump(slate, jar)<br>del slate  # delete it<br>with open('slate.pkl', 'rb') as jar:<br>    slate = pickle.load(jar)<br>print 'current value:', slate.value  # None<br>print slate.print_changes()  # 输出历史记录与上面一致</p> <h2 id="运算符相关的魔术方法">运算符相关的魔术方法</h2> <p>运算符相关的魔术方法实在太多了,也很好理解,不打算多讲。在其他语言里,也有重载运算符的操作,所以我们对这些魔术方法已经很了解了。</p> <h3 id="比较运算符">比较运算符</h3> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-cmp-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__cmp__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>如果该方法返回负数,说明</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">self < other</pre><div class="contentsignin">登入後複製</div></div><p>; 返回正数,说明</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">self > other</pre><div class="contentsignin">登入後複製</div></div> <p>; 返回0说明</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">self == other</pre><div class="contentsignin">登入後複製</div></div> <p>。<br>强烈不推荐来定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__cmp__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, 取而代之, 最好分别定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__lt__</pre><div class="contentsignin">登入後複製</div></div> <p>等方法从而实现比较功能。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__cmp__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>在Python3中被废弃了。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-eq-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__eq__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>定义了比较操作符</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">==</pre><div class="contentsignin">登入後複製</div></div> <p>的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-ne-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ne__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>定义了比较操作符</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">!=</pre><div class="contentsignin">登入後複製</div></div> <p>的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-lt-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__lt__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>定义了比较操作符</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><</pre><div class="contentsignin">登入後複製</div></div><p>的行为.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-gt-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__gt__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>定义了比较操作符</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">></pre><div class="contentsignin">登入後複製</div></div> <p>的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-le-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__le__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>定义了比较操作符</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><=</pre><div class="contentsignin">登入後複製</div></div><p>的行为.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-ge-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ge__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>定义了比较操作符</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">>=</pre><div class="contentsignin">登入後複製</div></div> <p>的行为.<br>下面我们定义一种类型Word, 它会使用单词的长度来进行大小的比较, 而不是采用str的比较方式。<br>但是为了避免 </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">Word('bar') == Word('foo')</pre><div class="contentsignin">登入後複製</div></div> <p> 这种违背直觉的情况出现,并没有定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__eq__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, 因此Word会使用它的父类(str)中的</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__eq__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>来进行比较。<br>下面的例子中也可以看出: 在编程语言中, 如果</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">a >=b and a <= b</pre><div class="contentsignin">登入後複製</div></div><p>, 并不能推导出</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">a == b</pre><div class="contentsignin">登入後複製</div></div><p>这样的结论。<br/># -*- coding: utf-8 -*-<br/>class Word(str):<br/> '''存储单词的类,定义比较单词的几种方法'''<br/> def __new__(cls, word):<br/> # 注意我们必须要用到__new__方法,因为str是不可变类型<br/> # 所以我们必须在创建的时候将它初始化<br/> if ' ' in word:<br/> print "Value contains spaces. Truncating to first space."<br/> word = word[:word.index(' ')] # 单词是第一个空格之前的所有字符<br/> return str.__new__(cls, word)<br/> def __gt__(self, other):<br/> return len(self) > len(other)<br>    def __lt__(self, other):<br>        return len(self) < len(other)<br/> def __ge__(self, other):<br/> return len(self) >= len(other)<br>    def __le__(self, other):<br>        return len(self) <= len(other)<br/>print 'foo < fool:', Word('foo') < Word('fool') # True<br/>print 'foolish > fool:', Word('foolish') > Word('fool')  # True<br>print 'bar >= foo:', Word('bar') >= Word('foo')  # True<br>print 'bar <= foo:', Word('bar') <= Word('foo') # True<br/>print 'bar == foo:', Word('bar') == Word('foo') # False, 用了str内置的比较方法来进行比较<br/>print 'bar != foo:', Word('bar') != Word('foo') # True</p><h3 id="一元运算符和函数">一元运算符和函数</h3><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-pos-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__pos__(self)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了’+'号一元运算符(比如</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">+some_object</pre><div class="contentsignin">登入後複製</div></div><p>)</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-neg-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__neg__(self)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了’-'号一元运算符(比如</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-some_object</pre><div class="contentsignin">登入後複製</div></div><p>)</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-invert-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__invert__(self)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">~</pre><div class="contentsignin">登入後複製</div></div><p>号一元运算符(比如</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">~some_object</pre><div class="contentsignin">登入後複製</div></div><p>)</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-abs-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__abs__(self)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">abs()</pre><div class="contentsignin">登入後複製</div></div><p>內建函数.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-round-self-nbsp-n-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__round__(self, n)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">round()</pre><div class="contentsignin">登入後複製</div></div><p>内建函数. 参数n表示四舍五进的精度.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-floor-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__floor__(self)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">math.round()</pre><div class="contentsignin">登入後複製</div></div><p>, 向下取整.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-ceil-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ceil__(self)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">math.ceil()</pre><div class="contentsignin">登入後複製</div></div><p>, 向上取整.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-trunc-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__trunc__(self)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">math.trunc()</pre><div class="contentsignin">登入後複製</div></div><p>, 向0取整.</p><h3 id="算术运算符">算术运算符</h3><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-add-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__add__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了加号运算.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-sub-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__sub__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了减号运算.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-mul-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__mul__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了乘法运算.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-floorp-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__floorp__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">//</pre><div class="contentsignin">登入後複製</div></div><p>运算符.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-p-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__p__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">/</pre><div class="contentsignin">登入後複製</div></div><p>运算符. 该方法在Python3中废弃. 原因是Python3中,pision默认就是true pision.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-truep-pre-div-class-contentsignin-登入後複製-div-div-self-other"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__truep__</pre><div class="contentsignin">登入後複製</div></div>(self, other)</h3><p>实现了true pision. 只有你声明了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">from __future__ import pision</pre><div class="contentsignin">登入後複製</div></div><p>该方法才会生效.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-mod-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__mod__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">%</pre><div class="contentsignin">登入後複製</div></div><p>运算符, 取余运算.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-pmod-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__pmod__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">pmod()</pre><div class="contentsignin">登入後複製</div></div><p>內建函数.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-pow-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__pow__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">**</pre><div class="contentsignin">登入後複製</div></div><p>操作. N次方操作.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-lshift-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__lshift__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了位操作</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><<</pre><div class="contentsignin">登入後複製</div></div><p>.</p><h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-rshift-self-nbsp-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rshift__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3><p>实现了位操作</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">>></pre><div class="contentsignin">登入後複製</div></div> <p>.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-and-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__and__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了位操作</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&</pre><div class="contentsignin">登入後複製</div></div> <p>.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-or-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__or__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了位操作</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">|</pre><div class="contentsignin">登入後複製</div></div> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-xor-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__xor__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了位操作</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">^</pre><div class="contentsignin">登入後複製</div></div> <h3 id="反算术运算符">反算术运算符</h3> <p>这里只需要解释一下概念即可。假设针对some_object这个对象:<br>some_object + other<br>上面的代码非常正常地实现了some_object的</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__add__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法。那么如果遇到相反的情况呢?<br>other + some_object<br>这时候,如果other没有定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__add__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法,但是some_object定义了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__radd__</pre><div class="contentsignin">登入後複製</div></div> <p>, 那么上面的代码照样可以运行。<br>这里的</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__radd__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <p>就是</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__add__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <p>的反算术运算符。<br>所以,类比的,我们就知道了更多的反算术运算符, 就不一一展开了:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rsub__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rmul__(self, other)</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rmul__(self, other)</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rfloorp__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rp__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rtruep__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rmod__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rpmod__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rpow__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rlshift__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rrshift__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rand__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ror__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__rxor__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <h3 id="增量赋值">增量赋值</h3> <p>这也是只要理解了概念就容易掌握的运算。举个例子:<br>x = 5<br>x += 1  # 这里的+=就是增量赋值,将x+1赋值给了x<br>因此对于</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">a += b</pre><div class="contentsignin">登入後複製</div></div> <p>, </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__iadd__</pre><div class="contentsignin">登入後複製</div></div> <p> 将返回</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">a + b</pre><div class="contentsignin">登入後複製</div></div> <p>, 并赋值给a。<br>所以很容易理解下面的魔术方法了:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__iadd__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__isub__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__imul__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ifloorp__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ip__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__itruep__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__imod__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ipow__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ilshift__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__irshift__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__iand__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ior__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__ixor__(self, other)</pre><div class="contentsignin">登入後複製</div></div> <h3 id="类型转化">类型转化</h3> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-int-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__int__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了类型转化为int的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-long-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__long__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了类型转化为long的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-float-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__float__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了类型转化为float的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-complex-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__complex__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了类型转化为complex(复数, 也即1+2j这样的虚数)的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-oct-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__oct__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了类型转化为八进制数的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-hex-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__hex__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了类型转化为十六进制数的行为.</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-index-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__index__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>在切片运算中将对象转化为int, 因此该方法的返回值必须是int。用一个例子来解释这个用法。<br>class Thing(object):<br>    def __index__(self):<br>        return 1<br>thing = Thing()<br>list_ = ['a', 'b', 'c']<br>print list_[thing]  # 'b'<br>print list_[thing:thing]  # []<br>上面例子中, </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">list_[thing]</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>的表现跟</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">list_[1]</pre><div class="contentsignin">登入後複製</div></div> <p>一致,正是因为Thing实现了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__index__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法。<br>可能有的人会想,</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">list_[thing]</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>为什么不是相当于</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">list_[int(thing)]</pre><div class="contentsignin">登入後複製</div></div> <p>呢? 通过实现Thing的</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__int__</pre><div class="contentsignin">登入後複製</div></div> <p>方法能否达到这个目的呢?<br>显然不能。如果真的是这样的话,那么</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">list_[1.1:2.2]</pre><div class="contentsignin">登入後複製</div></div> <p>这样的写法也应该是通过的。<br>而实际上,该写法会抛出TypeError: </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">slice indices must be integers or None or have an __index__ method</pre><div class="contentsignin">登入後複製</div></div> <p><br>下面我们再做个例子,如果对一个dict对象执行</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">dict_[thing]</pre><div class="contentsignin">登入後複製</div></div> <p>会怎么样呢?<br>dict_ = {1: 'apple', 2: 'banana', 3: 'cat'}<br>print dict_[thing]  # raise KeyError<br>这个时候就不是调用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__index__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>了。虽然</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">list</pre><div class="contentsignin">登入後複製</div></div> <p>和</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">dict</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>都实现了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__getitem__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法, 但是它们的实现方式是不一样的。<br>如果希望上面例子能够正常执行, 需要实现Thing的</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__hash__</pre><div class="contentsignin">登入後複製</div></div> <p> 和 </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__eq__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>方法.<br>class Thing(object):<br>    def __hash__(self):<br>        return 1<br>    def __eq__(self, other):<br>        return hash(self) == hash(other)<br>dict_ = {1: 'apple', 2: 'banana', 3: 'cat'}<br>print dict_[thing]  # apple</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-coerce-self-other-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__coerce__(self, other)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>实现了混合模式运算。<br>要了解这个方法,需要先了解</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">coerce()</pre><div class="contentsignin">登入後複製</div></div> <p>内建函数: 官方文档上的解释是, coerce(x, y)返回一组数字类型的参数, 它们被转化为同一种类型,以便它们可以使用相同的算术运算符进行操作。如果过程中转化失败,抛出TypeError。<br>比如对于</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">coerce(10, 10.1)</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>, 因为10和10.1在进行算术运算时,会先将10转为10.0再来运算。因此</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">coerce(10, 10.1)</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>返回值是(10.0, 10.1).</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__coerce__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>在Python3中废弃了。</p> <h2 id="其他魔术方法">其他魔术方法</h2> <p>还没讲到的魔术方法还有很多,但有些我觉得很简单,或者很少见,就不再累赘展开说明了。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-str-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__str__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">str()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>时调用。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-repr-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__repr__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">repr()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>时调用。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">str()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>和</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">repr()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>都是返回一个代表该实例的字符串,<br>主要区别在于: str()的返回值要方便人来看,而repr()的返回值要方便计算机看。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-unicode-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__unicode__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">unicode()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>时调用。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">unicode()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>与</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">str()</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>的区别在于: 前者返回值是unicode, 后者返回值是str。unicode和str都是</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">basestring</pre><div class="contentsignin">登入後複製</div></div> <p>的子类。<br>当你对一个类只定义了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__str__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>但没定义</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__unicode__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>时,</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__unicode__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>会根据</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__str__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>的返回值自动实现,即</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">return unicode(self.__str__())</pre><div class="contentsignin">登入後複製</div></div> <p>;<br>但返回来则不成立。<br>class StrDemo2:<br>    def __str__(self):<br>        return 'StrDemo2'<br>class StrDemo3:<br>    def __unicode__(self):<br>        return u'StrDemo3'<br>demo2 = StrDemo2()<br>print str(demo2)  # StrDemo2<br>print unicode(demo2)  # StrDemo2<br>demo3 = StrDemo3()<br>print str(demo3)  # <__main__.StrDemo3 instance><br>print unicode(demo3)  # StrDemo3</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-format-self-formatstr-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__format__(self, formatstr)</pre><div class="contentsignin">登入後複製</div></div></h3> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">"Hello, {0:abc}".format(a)</pre><div class="contentsignin">登入後複製</div></div> <p>等价于</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">format(a, "abc")</pre><div class="contentsignin">登入後複製</div></div> <p>, 等价于</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">a.__format__("abc")</pre><div class="contentsignin">登入後複製</div></div> <p>。<br>这在需要格式化展示对象的时候非常有用,比如格式化时间对象。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-hash-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__hash__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">hash()</pre><div class="contentsignin">登入後複製</div></div> <p>时调用, 返回值是数值类型。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-nonzero-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__nonzero__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">bool()</pre><div class="contentsignin">登入後複製</div></div> <p>时调用, 返回True或者False。<br>你可能会问, 为什么不是命名为</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__bool__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>? 我也不知道。<br>我只知道该方法在Python3中改名为</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__bool__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>了。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-dir-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__dir__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">dir()</pre><div class="contentsignin">登入後複製</div></div> <p>时调用。通常实现该方法是没必要的。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-sizeof-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__sizeof__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">sys.getsizeof()</pre><div class="contentsignin">登入後複製</div></div> <p>时调用。返回对象的大小,单位是bytes。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-instancecheck-self-instance-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__instancecheck__(self, instance)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例调用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">isinstance(instance, class)</pre><div class="contentsignin">登入後複製</div></div> <p>时调用。 返回值是布尔值。它会判断instance是否是该类的实例。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-subclasscheck-self-subclass-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__subclasscheck__(self, subclass)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">issubclass(subclass, class)</pre><div class="contentsignin">登入後複製</div></div> <p>时调用。返回值是布尔值。它会判断subclass否是该类的子类。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-copy-self-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__copy__(self)</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">copy.copy()</pre><div class="contentsignin">登入後複製</div></div> <p>时调用。返回”浅复制”的对象。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-deepcopy-self-memodict-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__deepcopy__(self, memodict={})</pre><div class="contentsignin">登入後複製</div></div></h3> <p>对实例使用</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">copy.deepcopy()</pre><div class="contentsignin">登入後複製</div></div> <p>时调用。返回”深复制”的对象。</p> <h3 id="div-class-code-style-position-relative-padding-px-margin-px-pre-call-self-args-pre-div-class-contentsignin-登入後複製-div-div"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__call__(self, [args...])</pre><div class="contentsignin">登入後複製</div></div></h3> <p>该方法允许类的实例跟函数一样表现:<br>class XClass:<br>    def __call__(self, a, b):<br>        return a + b<br>def add(a, b):<br>    return a + b<br>x = XClass()<br>print 'x(1, 2)', x(1, 2)<br>print 'callable(x)', callable(x)  # True<br>print 'add(1, 2)', add(1, 2)<br>print 'callable(add)', callable(add)  # True</p> <h2 id="Python-中的差异">Python3中的差异</h2> <p>Python3中,str与unicode的区别被废除了,因而</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__unicode__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>没有了,取而代之地出现了</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__bytes__</pre><div class="contentsignin">登入後複製</div></div> <p>.<br>Python3中,pision默认就是true pision, 因而</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__p__</pre><div class="contentsignin">登入後複製</div></div> <p>废弃.</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__coerce__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>因存在冗余而废弃.</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__cmp__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <p>因存在冗余而废弃.</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__nonzero__</pre><div class="contentsignin">登入後複製</div></div> <p>改名为</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">__bool__</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <div></div> <!--<p class='doc-content-pic doc-pic'><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/013/b418c5819b5ebecfe1f9367c41f9fb08-0.jpg" class="lazy" / alt="深入了解Python中的魔術方法" > </p>-->

以上是深入了解Python中的魔術方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

vs code 可以在 Windows 8 中運行嗎 vs code 可以在 Windows 8 中運行嗎 Apr 15, 2025 pm 07:24 PM

VS Code可以在Windows 8上運行,但體驗可能不佳。首先確保系統已更新到最新補丁,然後下載與系統架構匹配的VS Code安裝包,按照提示安裝。安裝後,注意某些擴展程序可能與Windows 8不兼容,需要尋找替代擴展或在虛擬機中使用更新的Windows系統。安裝必要的擴展,檢查是否正常工作。儘管VS Code在Windows 8上可行,但建議升級到更新的Windows系統以獲得更好的開發體驗和安全保障。

visual studio code 可以用於 python 嗎 visual studio code 可以用於 python 嗎 Apr 15, 2025 pm 08:18 PM

VS Code 可用於編寫 Python,並提供許多功能,使其成為開發 Python 應用程序的理想工具。它允許用戶:安裝 Python 擴展,以獲得代碼補全、語法高亮和調試等功能。使用調試器逐步跟踪代碼,查找和修復錯誤。集成 Git,進行版本控制。使用代碼格式化工具,保持代碼一致性。使用 Linting 工具,提前發現潛在問題。

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

vscode 擴展是否是惡意的 vscode 擴展是否是惡意的 Apr 15, 2025 pm 07:57 PM

VS Code 擴展存在惡意風險,例如隱藏惡意代碼、利用漏洞、偽裝成合法擴展。識別惡意擴展的方法包括:檢查發布者、閱讀評論、檢查代碼、謹慎安裝。安全措施還包括:安全意識、良好習慣、定期更新和殺毒軟件。

See all articles