『無為則無心』Python面向對象 — 60、魔法屬性
- 2022 年 3 月 1 日
- 筆記
- 高級測試技能 - Python基礎
Python 類中,凡是以雙下劃線 “__” 開頭和結尾命名的成員(屬性和方法),這些特殊成員存在著一些特殊含義,都被稱為類的特殊成員(特殊屬性和特殊方法)。
我們把特殊屬性也可以稱之為魔法屬性,或者內置類屬性。
1、魔法屬性__name__
__name__
是用來標識模組名字的一個系統變數。
這裡分兩種情況:
- 第一種情況指的是當前運行的模組,那麼當前模組
__name__
的值就為__main__
。 - 第二種情況指的是該模組是使用
import
導入的模組,那麼這個被導入模組的__name__
變數的值為該模組的文件名(去掉.py
)。
示例:
Demo1.py
文件:
# 在當前文件中直接調用__name__屬性
def my_func():
print("我的模組名是", __name__)
# __name__屬性在模組中可直接調用
# 在當期模組中調用
# 結果:我的模組名是 __main__
if __name__ == "__main__":
my_func()
Demo2.py
文件:
# 導入Demo1模組,使用模組中的my_func()方法
from Demo1 import *
# 執行my_func()方法
# 結果:我的模組名是 Demo1
my_func()
2、魔法屬性__bases__
Python 為所有類都提供了一個__bases__
屬性,通過該屬性可以查看該類的所有直接父類,該屬性返回所有直接父類組成的元組。(直接父類)
class A(object):
pass
class B(A):
pass
class C(B):
pass
class D(C,B,A):
pass
# 類名直接調用__bases__屬性
print(C.__bases__)
print(D.__bases__)
"""
輸出結果:
(<class '__main__.B'>,)
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>)
"""
注意:在類的實例對象中沒有
__bases__
屬性。
3、魔法屬性__mro__
Python的每一個有父類的類,都有一個與方法解析順序相關的特殊屬性__mro__
屬性, 它是一個tuple
(元組), 裝著方法解析時的對象查找順序,越靠前的優先順序越高。
執行下面的程式碼:
class A(object):
pass
class B(A):
pass
class C(B):
pass
# 類名直接調用__bases__屬性
print(C.__bases__)
print(C.__mro__)
"""
輸出結果:
(<class '__main__.B'>,)
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
"""
說明:
__mro__
屬性和__bases__
屬性的區別。
__bases__
屬性是查看當前類的直接父類,返回一個元組。
__mro__
屬性是指在有繼承關係中,包括單繼承,多重繼承,多層繼承中。使用super
調用父類的方法和屬性的時候,優先查找的順序。
4、魔法屬性__doc__
作用:表示類的描述文檔資訊。
class Person:
"""
這裡是類的描述類資訊。
"""
def func(self):
"""
這裡是類中方法的描述類資訊。
"""
pass
# 因為是屬性,不用加()
print(Person.__doc__)
輸出結果:
5、魔法屬性__module__
和__class__
__module__
屬性:表示當前操作的對象屬於哪個模組。
__class__
屬相:表示當前操作的對象的是由哪個類創建的。
# 定義一個類
class Person(object):
pass
obj = Person()
print(obj.__module__)
print(obj.__class__)
"""
輸出結果:
__main__ : 表示前擋模組
<class '__main__.Person'> : 表示該對象屬於當前模組中的Python類
"""
6、魔法屬性__dict__
列出類中或者對象中的所有成員,以字典的形式返回。這個屬性不用我們再類中覆寫,類和對象默認自帶。
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def tellMe(self):
print(f'我叫{self.name},今年{self.age}')
# 獲取類的所有成員
print(Person.__dict__)
# # 獲取對象的所有成員
obj1 = Person('美猴王', "18")
obj2 = Person('齊天大聖', "30")
print(obj1.__dict__)
print(obj2.__dict__)
"""
輸出結果 :
類的所有成員:
{'__module__': '__main__',
'__init__': <function Person.__init__ at 0x0000000002425828>,
'tellMe': <function Person.tellMe at 0x0000000002425A68>,
'__dict__': <attribute '__dict__' of 'Person' objects>,
'__weakref__': <attribute '__weakref__' of 'Person' objects>,
'__doc__': None}
注意:__weakref__,和垃圾回收機制,還有弱引用的知識點有關。
對象的所有成員:
{'name': '美猴王', 'age': '18'}
{'name': '齊天大聖', 'age': '30'}
"""
注意:從上面的結果可以看出,對象調用
__dict__
屬性,沒有看到對象中的方法。
- 類的實例屬性屬於對象,類的實例方法不屬於對象。也就是說
__dict__
屬性不列印處對象的中方法。- 類中的類屬性和方法等都屬於類。
7、魔法屬性__slots__
Python是動態語言,對於普通的類,可以為類的實例對象賦值任何屬性,這些屬性會存儲在__dict__
中。
而類中定義了__slots__
屬性,它僅允許動態綁定__slots__
裡邊定義的屬性。
示例:
# 創建一個Student類
class Student():
# 定義__slots__
__slots__ = ('name', 'age')
# 創建一個學生對象
stu = Student()
# 動態添加__slots__屬性中定義的屬性,可以添加
stu.name = '孫悟空'
stu.age = 18
# 而__slots__屬性中沒有定義的屬性,是添加不了的。
# 結果:AttributeError: 'Student' object has no attribute 'addr'
stu.addr = "北京"