Python 獲取對象的屬性和方法—dir 函數


工作中,我們使用一些之前沒用到過的模塊,使用時需要了解一下這個模塊中的一些類的方法或屬性,怎么做呢?目前我比較常用的兩款IDE“Pycharm”和“VSCode”,都可以通過先導包,然后通過“Ctrl+鼠標左鍵”,進入源碼后觀看並膜拜一下大神們的代碼,當然也可以進入我們在項目中自己所定義的,然后進行快速修改,真的是很方便呢。但是有的時候,我們使用的環境沒有這類的IDE,那該怎么學習我們要用的這些類方法和屬性呢?方法當然很多,無論是小白,還是大神,百度谷歌大法都是比較快速和方便的。但是對於一些剛開源的或者是我們自己定義的呢,這里我們就聊聊Python 中的內建函數——dir 函數

 

首先可以先通過簡單的源碼解讀,可以得知:

1.他的返回值是一個元素為字符串的列表

 

2.當傳入一個模塊對象時,返回的是模塊里面所有的屬性(變量名和方法)

我在function_use 這個文件夾或者包中創建了一個模塊(demo01.py),內容隨便定義幾個變量和函數及類,如:

 1 a = 10
 2 b = 'test'
 3 
 4 def c(x):
 5     print(x)
 6 
 7 class D(object):
 8     def __init__(self):
 9         self.name = 'name'
10         self.age = 18
11 
12     def get_name(self):
13         return self.name
14 
15 class E(D):
16     pass

然后再創建一個模塊(demo02.py),並在"demo02.py"中引用"demo01.py“,然后打印dir(demo01),如:

1 from function_use import demo01
2 
3 print(dir(demo01))
4 
5 
6 ['D', 'E', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'c']

 

3.當傳入的對象是一個類時,返回這個類及其所有父類(包括父類的父類)的屬性和方法

就上面的例子,無論是在當前模塊“demo01.py”下面調用:

1 ...
2 if __name__ == '__main__':
3     print(dir(D))
4 
5 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_name']

還是在“demo02.py” 中引用的調用

1 from function_use import demo01
2 
3 # print(dir(demo01))
4 print(dir(demo01.D))
5 
6 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_name']

可以看出,結果是一樣的。


4.當傳入的對象是其他的時候(照我的理解,這個其他對象,就是一個實例對象),則返回這個實例對象的屬性和方法,實例對象類的屬性和方法,以及這個類的所有基類的屬性和方法

相對於第三種情況(傳入的對象是一個類時)其實只是多了這個實例對象的屬性,感覺繞的話,就看下面的例子:
老樣子,在”demo01.py“ 里面

1 ...
2 if __name__ == '__main__':
3     e = E()
4     print(dir(e))
5 
6 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'get_name', 'name']

或者在”demo02.py“ 里面

1 from function_use import demo01
2 
3 # print(dir(demo01))
4 e = demo01.E()
5 print(dir(e))
6 
7 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'get_name', 'name']

可以看到,只是多了E 的實例對象的兩個屬性“age” 和“name”

 


===================問題分割線===================

這里就有一個待解決的問題,就上面的例子,我嘗試了在demo01.py 模塊的D 這個類里面加了一個類方法及類屬性

 1 a = 10
 2 b = 'test'
 3 
 4 
 5 def c(x):
 6     print(x)
 7 
 8 
 9 class D(object):
10     dd = 123
11 
12     def __init__(self):
13         self.name = 'name'
14         self.age = 18
15 
16     def get_name(self):
17         return self.name
18 
19     @classmethod
20     def print_x(cls):
21         print("x")
22 
23 
24 class E(D):
25     pass
26 
27 
28 if __name__ == '__main__':
29     # e = E()
30     # print(dir(e))
31     print(dir(E))
32     E.print_x()
33     # print(E.get_name())
34 
35 
36 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'dd', 'get_name', 'print_x']
37 
38 x # E.print_x()
View Code

這都沒問題,但是我去調用dir 函數返回的“get_name” 函數時,卻提示我必須要傳入一個必傳的參數“self”這樣就需要
print(E.get_name(E()))了,但是這樣的話,為什么這個方法可以出現在dir(E)的返回值里面呢?
有點暈
===================問題分割線===================

 

 

說完這個函數的返回值,我們再聊聊其中具體的內容,這里用自定義的例子不好說明,就搬來廖老師的例子吧

首先對一個字符串對象,比如“ABC” 使用dir()函數,查看他的所有屬性和方法

1 print(dir("ABC"))
2 
3 ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

可以看出來,字符串對象的屬性和方法還是很多的,類似__xx__的屬性和方法在Python 中都是有特殊用途的,比如__len__方法返回長度。在Python 中,如果你調用len() 函數試圖獲得一個對象的長度,實際上,在len() 函數內部,它自動去調用該對象的__len__() 方法,所以得到兩個結論:

1.下面的代碼是等價的

1 print(len("ABC")) # 3
2 print("ABC".__len__()) # 3

 

2.對一個對象使用dir 函數,返回的列表里面,如果沒有__len__ 方法,我們去對這個對象使用len 函數,就會報TypeError 的錯

比如對整數類型使用len 函數,或者是上面我們"demo01.py" 里面的"e" 使用len 函數,如果我們想用len(e) 的話,就要自己寫一個__len__() 方法:

 1 class D(object):
 2     dd = 123
 3 
 4     def __init__(self):
 5         self.name = 'name'
 6         self.age = 18
 7 
 8     def __len__(self):
 9         return 100
10 
11     def get_name(self):
12         return self.name
13 
14     @classmethod
15     def print_x(cls):
16         print("x")
17 
18 
19     class E(D):
20         pass
21 
22 if __name__ == '__main__':
23     e = E()
24     print(len(e))         # 100

 

除了這些“__xx__” 特殊格式的方法,剩下的都是普通屬性或方法,比如lower() 返回小寫的字符串

1 print("ABC".lower()) # 'abc'

 未完


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM