python類內init外聲明的屬性與init內聲明的對象屬性的訪問和操作區別(面試題)
1.在ipython中輸入以下代碼,其輸出會是什么?
In [1]: class ClassOut: ...: out_mem = 'out_mem' ...: print out_mem ...: def __init__(self): ...: inner_mem = 'inner_mem' ...: self.inner_mem = 'self.inner_mem' ...: self._inner_mem = 'self._inner_mem' ...: self.out_mem = 'self.out_mem' ...: In [2]: out = ClassOut() In [3]: out.out_mem In [4]: out._inner_mem In [5]: out.inner_mem In [6]: class ClassOut: ...: out_mem = 'out_mem' ...: print out_mem ...: def __init__(self): ...: inner_mem = 'inner_mem' ...: self.inner_mem = 'self.inner_mem' ...: self._inner_mem = 'self._inner_mem' ...: self.out_mem1 = 'self.out_mem1' ...: out_mem In [7]: out = ClassOut() In [8]: out.out_mem In [9]: ClassOut.out_mem In [10]: ClassOut.out_mem1 In [11]: out._inner_mem In [12]: out.out_mem = 'out_mem modified by object' In [13]: ClassOut.out_mem In [14]: out.out_mem In [15]: out.new_mem = 'clas' In [16]: out.new_mem In [17]: o = ClassOut() In [18]: o.out_mem In [19]: ClassOut.out_mem In [20]: ClassOut.out_mem = 'out_mem modified by Class' In [21]: o.out_mem
考察:
1. python解釋器處理解釋class
2. 類的初始化定義方法
3. 類的__init__方法 與 class object成員定義, class instance成員的定義
4. 類定義成員時的命名約定
5. class object 與 class instance的區別
6. class object 與 class instance在處理缺失成員訪問時查詢域優先級的區別
7. class 定義 __private_mem 不被外部發現的元嬰? (被重命名為_[class_name]__private_mem)!!!詳見如下代碼!
In [48]: class ClassOut:
...: out_mem = 'out_mem'
...: print out_mem
...: def __init__(self):
...: inner_mem = 'inner_mem'
...: self.inner_mem = 'self.inner_mem'
...: self._inner_mem = 'self._inner_mem'
...: self.out_mem1 = 'self.out_mem1'
...: self.__private_mem = 'self.__private_mem'
...:
out_mem
In [49]: no = ClassOut()
In [50]: no.__private_mem
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-50-36dd351a1b65> in <module>()
----> 1no.__private_mem
AttributeError: ClassOut instance has no attribute '__private_mem'
In [51]: no._ClassOut__private_mem
Out[51]: 'self.__private_mem'
8.1. 不能直接給對象設置屬性?
>>> obj = object()
>>> obj.name = "whatever"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'name'
但是為什么這樣就可以呢:
>>> class Object(object):pass
...
>>> Obj = Object()
>>> Obj.name = "whatever"
>>> Obj.name
'whatever'
>>>
答: 現在你給第二個代碼塊中的Object加上屬性 __slots__ 試試:
>>> class Object(object):
... __slots__ = {}
...
>>> Obj = Object()
>>> Obj.name = "whatever"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Object' object has no attribute 'name'
會發現拋出了同樣的異常。 object 、 list 、 dict 等內置函數都如此。
擁有 __slots__ 屬性的類在實例化對象時不會自動分配 __dict__ ,而obj.attr 即 obj.__dict__['attr'], 所以會引起 AttributeError
對於擁有 __slots__ 屬性的類的實例 Obj 來說,只能對 Obj 設置__slots__ 中有的屬性:
>>> class Object(object):
... __slots__ = {"a","b"}
...
>>> Obj = Object()
>>> Obj.a = 1
>>> Obj.a
1
>>> Obj.c = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Object' object has no attribute 'c'
詳細見 Python-slots-doc