Từ khóa “code introspection” này mình vô tình tìm thấy trong một bài viết trên Medium. Sau một hồi tìm hiểu, mình mới biết “code introspection” chính là việc khai thác thông tin về class, method, module … ngay tại thời điểm runtime. Python cung cấp cho chúng ta một số built-in methods để hỗ trợ cho việc này, nhờ đó chúng ta có thể hiểu chương trình hơn, nắm rõ các objects mà mình đang làm việc hơn (nó là gì, nó có thể làm được những gì, …) qua đó có thể xử lý logic một cách đúng đắn hoặc debugging một cách hiệu quả hơn. Có lẽ đó cũng chính là lý do xuất hiện từ “introspection” (sự tự suy xét nội tâm ?).
Trong quá trình làm việc, mình cũng đã thử sử dụng một số phương thức trên và thấy rất hữu dụng. Chính vì thế, mình muốn tổng hợp lại một lần nữa để khiến bản thân nhớ lâu hơn, và hi vọng có thể chia sẻ cho bạn nào muốn tìm hiểu về Python, thêm một vài kiến thức mới thú vị. Nếu mọi người có gì góp ý thì bảo với mình nhé!
Sau đây mình sẽ giới thiệu một số hàm intropection phổ biến:
type()
Để minh họa cho phương thức này, mình xin phép lấy lại ví dụ trong một bài Medium (link ở cuối bài):
Làm thế nào để lưu trữ giá trị 1?
Chúng ta có thể liệt kê những cách sau đây:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">import</span> numpy <span class="token keyword">as</span> np <span class="token keyword">import</span> pandas <span class="token keyword">as</span> pd a <span class="token operator">=</span> <span class="token number">1</span> b <span class="token operator">=</span> <span class="token number">1.0</span> c <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> d <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token punctuation">)</span> e <span class="token operator">=</span> np<span class="token punctuation">.</span>int64<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> f <span class="token operator">=</span> pd<span class="token punctuation">.</span>DataFrame<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> g <span class="token operator">=</span> <span class="token string">'1'</span> h <span class="token operator">=</span> <span class="token string">'one'</span> |
Có nhiều cách hơn bạn nghĩ đúng không? Bây giờ chúng ta sẽ kiểm tra type của các variables trên:
1 2 3 4 | <span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token builtin">type</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token keyword">for</span> x <span class="token keyword">in</span> <span class="token punctuation">[</span>a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> c<span class="token punctuation">,</span> d<span class="token punctuation">,</span> e<span class="token punctuation">,</span> f<span class="token punctuation">,</span> g<span class="token punctuation">,</span> h<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token punctuation">[</span><span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'int'</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'float'</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'list'</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'tuple'</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'numpy.int64'</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'pandas.core.frame.DataFrame'</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'str'</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token punctuation">,</span> <span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'str'</span><span class="token operator">></span><span class="token punctuation">]</span> |
Gần như mỗi biến đều là một data type khác nhau (trừ hai biến ở cuối). Cơ mà data type có quan trọng không?
Có. Vì nó sẽ xác định các operations có thể sử dụng, và đảm bảo kết quả ra đúng như kỳ vọng.
Tiếp tục ví dụ trên, khi thực hiện phép cộng (toán tử +) trên các data types khác nhau, chúng ta sẽ nhận được các output hoàn toàn khác nhau:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">def</span> <span class="token function">add</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> n<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">return</span> m <span class="token operator">+</span> n <span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">print</span><span class="token punctuation">(</span>add<span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token number">2.0</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">print</span><span class="token punctuation">(</span>add<span class="token punctuation">(</span>g<span class="token punctuation">,</span> h<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> one1 <span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">print</span><span class="token punctuation">(</span>add<span class="token punctuation">(</span>a<span class="token punctuation">,</span> g<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> TypeError<span class="token punctuation">:</span> unsupported operand <span class="token builtin">type</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token keyword">for</span> <span class="token operator">+</span><span class="token punctuation">:</span> <span class="token string">'int'</span> <span class="token keyword">and</span> <span class="token string">'str'</span> <span class="token comment"># ==> Opps!</span> |
Cùng là làm việc trên những biến “lưu giữ giá trị 1”, nhưng ở phép toán đầu tiên thì ta đang cộng số học, phép toán thứ hai thì cộng chuỗi, còn phép toán cuối cùng thì lại gặp lỗi!
Cá nhân mình thường sử dụng phương thức type()
trong quá trình debugging. Đối với mình, data types thực sự là ác mộng, vì mỗi thư viện, mỗi team làm việc, hay mỗi cá nhân đôi khi sẽ có những convention và cách tiếp cận vấn đề khác nhau. Trong một project về xử lý ảnh ở team của mình, ma trận ảnh có thể gặp dưới dạng np.uint8
hoặc np.float32
; tọa độ điểm có thể gặp dưới dạng Tuple
của hai số nguyên, List
chứa hai số nguyên, hoặc np.ndarray
chứa hai số nguyên; v.v … Nếu không cẩn thận, chúng ta có thể gặp những lỗi ngoài ý muốn như ví dụ ở trên.
Như vậy, việc kiểm tra data types và thống nhất một quy chuẩn chung khi làm việc rất quan trọng. Mình thường thực hiện bằng cách sử dụng type hint khi khai báo hàm và sử dụng assert
kết hợp với isinstance()
để validate inputs đầu vào trước khi thực hiện xử lí logic tiếp theo. Hàm ở trên có thể viết lại như sau:
1 2 3 4 5 6 7 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Union <span class="token keyword">def</span> <span class="token function">add_num</span><span class="token punctuation">(</span>m<span class="token punctuation">:</span> Union<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">float</span><span class="token punctuation">]</span><span class="token punctuation">,</span> n<span class="token punctuation">:</span> Union<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">float</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">assert</span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">float</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"m is not a type of int or float."</span> <span class="token keyword">assert</span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span>n<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">float</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"n is not a type of int or float."</span> <span class="token keyword">return</span> m <span class="token operator">+</span> n |
isinstance()
Như đã thấy ở ví dụ trên, phương thức isintance()
có tác dụng kiểm tra xem một object có phải là một thể hiện (instance) của class hay không. Nếu đúng, isinstance()
sẽ trả về True
, ngược lại trả về False
.
Chúng ta có thể tham khảo thêm một ví dụ dưới đây:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token keyword">class</span> <span class="token class-name">Bird</span><span class="token punctuation">:</span> <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">:</span> self<span class="token punctuation">.</span>name <span class="token operator">=</span> name <span class="token keyword">def</span> <span class="token function">fly</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string-interpolation"><span class="token string">f" I'm </span><span class="token interpolation"><span class="token punctuation">{</span>self<span class="token punctuation">.</span>name<span class="token punctuation">}</span></span><span class="token string">. I'm flying!"</span></span><span class="token punctuation">)</span> <span class="token keyword">class</span> <span class="token class-name">Dog</span><span class="token punctuation">:</span> <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">:</span> self<span class="token punctuation">.</span>name <span class="token operator">=</span> name <span class="token keyword">def</span> <span class="token function">bark</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string-interpolation"><span class="token string">f" I'm </span><span class="token interpolation"><span class="token punctuation">{</span>self<span class="token punctuation">.</span>name<span class="token punctuation">}</span></span><span class="token string">. I'm barking! Gau Gau!"</span></span><span class="token punctuation">)</span> animal <span class="token operator">=</span> Dog<span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"Pluto"</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span>animal<span class="token punctuation">,</span> Bird<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"This is a bird."</span><span class="token punctuation">)</span> animal<span class="token punctuation">.</span>fly<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">elif</span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span>animal<span class="token punctuation">,</span> Dog<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"This is a lovely dog."</span><span class="token punctuation">)</span> animal<span class="token punctuation">.</span>bark<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"I don't know who I am"</span><span class="token punctuation">)</span> <span class="token operator">>></span><span class="token operator">></span> This <span class="token keyword">is</span> a lovely dog<span class="token punctuation">.</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> I<span class="token string">'m Pluto. I'</span>m barking! Gau Gau! |
Nhờ vào việc xác định class của từng object mà ta đã có các actions phù hợp cho từng class cụ thể. Trong ví dụ trên, animal
là một thể hiện của Dog
nên nó sẽ thực hiện phương thức bark()
thay vì fly()
. Điều này giúp giảm thiểu rủi ro trong quá trình thực thi chương trình.
hasattr()
Phương thức này nhằm xác định xem object có tồn tại attribute nào đó hay không.
Tiếp tục ví dụ ở trên, ta thử khiến chú chó Pluto bay như chim xem sao:
1 2 3 4 5 6 | animal<span class="token punctuation">.</span>fly<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">>></span><span class="token operator">></span> Traceback <span class="token punctuation">(</span>most recent call last<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> File <span class="token string">"<input>"</span><span class="token punctuation">,</span> line <span class="token number">1</span><span class="token punctuation">,</span> <span class="token keyword">in</span> <span class="token operator"><</span>module<span class="token operator">></span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> AttributeError<span class="token punctuation">:</span> <span class="token string">'Dog'</span> <span class="token builtin">object</span> has no attribute <span class="token string">'fly'</span> |
Như vậy, Pluto không hề có attribute fly
. Tuy nhiên đâu có điều gì là “chắc chắn mọi con chó đều không biết bay”? Giả sử chúng ta khai báo một chú chó ngoài hành tinh chẳng hạn:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">class</span> <span class="token class-name">AlienDog</span><span class="token punctuation">(</span>Dog<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token triple-quoted-string string">""" This class is inherited from Dog class. """</span> <span class="token keyword">def</span> <span class="token function">fly</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string-interpolation"><span class="token string">f"I'm </span><span class="token interpolation"><span class="token punctuation">{</span>self<span class="token punctuation">.</span>name<span class="token punctuation">}</span></span><span class="token string">. I'm a special dog. I'm flying!"</span></span><span class="token punctuation">)</span> alien_animal <span class="token operator">=</span> AlienDog<span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"Woola"</span><span class="token punctuation">)</span> |
Để tránh gặp lỗi AttributeError
như ở trên, chúng ta có thể giải quyết bằng cách:
1 2 3 4 5 6 7 8 | <span class="token keyword">if</span> <span class="token builtin">hasattr</span><span class="token punctuation">(</span>animal<span class="token punctuation">,</span> <span class="token string">"fly"</span><span class="token punctuation">)</span><span class="token punctuation">:</span> animal<span class="token punctuation">.</span>fly<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token builtin">hasattr</span><span class="token punctuation">(</span>alien_animal<span class="token punctuation">,</span> <span class="token string">"fly"</span><span class="token punctuation">)</span><span class="token punctuation">:</span> alien_animal<span class="token punctuation">.</span>fly<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">>></span><span class="token operator">></span> I<span class="token string">'m Woola. I'</span>m a special dog<span class="token punctuation">.</span> I'm flying! |
Vì animal
không có attribute fly()
nên điều kiện trở nên sai, phương thức animal.fly()
sẽ không được thực hiện. Tuy nhiên, ở alien_animal
lại tồn tại phương thức này nên điều kiện trở nên đúng, và chú chó này đã bay thật.
(Tiếc thay, Woola thực sự trong phim John Carter không biết bay.)
dir()
Phương thức này liệt kê tất cả các thuộc tính và phương thức của bất cứ object nào.
Có một sự thật là, tất cả mọi thứ trong Python hầu hết đều là object. Chúng ta có thể dễ dàng kiểm chứng với isinstance()
:
1 2 3 4 5 6 7 8 | <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token builtin">object</span><span class="token punctuation">)</span> <span class="token boolean">True</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span><span class="token builtin">list</span><span class="token punctuation">,</span> <span class="token builtin">object</span><span class="token punctuation">)</span> <span class="token boolean">True</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span><span class="token boolean">None</span><span class="token punctuation">,</span> <span class="token builtin">object</span><span class="token punctuation">)</span> <span class="token boolean">True</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> |
(Chỉ riêng về object trong Python thôi mà mình đã thấy rất nhiều điều thú vị. Mình sẽ tổng hợp và chia sẻ cho mọi người trong những phần tiếp theo.)
Object sẽ có những thuộc tính và phương thức nhất định. dir()
chính là hàm quyền lực liệt kê ra tất cả những phương thức và thuộc tính của object đó, ngay cả các thuộc tính mặc định.
1 2 3 4 5 6 | <span class="token builtin">dir</span><span class="token punctuation">(</span>animal<span class="token punctuation">)</span> <span class="token comment"># animal is an instance of the Dog class as the previous example.</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token punctuation">[</span><span class="token string">'__class__'</span><span class="token punctuation">,</span> <span class="token string">'__delattr__'</span><span class="token punctuation">,</span> <span class="token string">'__dict__'</span><span class="token punctuation">,</span> <span class="token string">'__dir__'</span><span class="token punctuation">,</span> <span class="token string">'__doc__'</span><span class="token punctuation">,</span> <span class="token string">'__eq__'</span><span class="token punctuation">,</span> <span class="token string">'__format__'</span><span class="token punctuation">,</span> <span class="token string">'__ge__'</span><span class="token punctuation">,</span> <span class="token string">'__getattribute__'</span><span class="token punctuation">,</span> <span class="token string">'__gt__'</span><span class="token punctuation">,</span> <span class="token string">'__hash__'</span><span class="token punctuation">,</span> <span class="token string">'__init__'</span><span class="token punctuation">,</span> <span class="token string">'__init_subclass__'</span><span class="token punctuation">,</span> <span class="token string">'__le__'</span><span class="token punctuation">,</span> <span class="token string">'__lt__'</span><span class="token punctuation">,</span> <span class="token string">'__module__'</span><span class="token punctuation">,</span> <span class="token string">'__ne__'</span><span class="token punctuation">,</span> <span class="token string">'__new__'</span><span class="token punctuation">,</span> <span class="token string">'__reduce__'</span><span class="token punctuation">,</span> <span class="token string">'__reduce_ex__'</span><span class="token punctuation">,</span> <span class="token string">'__repr__'</span><span class="token punctuation">,</span> <span class="token string">'__setattr__'</span><span class="token punctuation">,</span> <span class="token string">'__sizeof__'</span><span class="token punctuation">,</span> <span class="token string">'__str__'</span><span class="token punctuation">,</span> <span class="token string">'__subclasshook__'</span><span class="token punctuation">,</span> <span class="token string">'__weakref__'</span><span class="token punctuation">,</span> <span class="token string">'bark'</span><span class="token punctuation">,</span> <span class="token string">'name'</span><span class="token punctuation">]</span> |
Output này giúp chúng ta có cái nhìn tổng quát về object animal
khi nãy hơn, xác định được animal
có những thuộc tính gì và có thể thực thi được những phương thức gì. Ngoài phương thức bark
và thuộc tính name
ở cuối mảng, các phương thức mặc định còn lại được gọi là magic methods (mình sẽ bàn về vấn đề này ở bài khác).
id()
Phương thức này trả về định danh (duy nhất) của object ở vòng đời chương trình hiện tại, trong C có thể hiểu như là địa chỉ bộ nhớ mà biến đó tham chiếu tới. Giá trị này sẽ thay đổi ở mỗi lần chạy chương trình.
1 2 3 4 5 6 7 8 | <span class="token operator">>></span><span class="token operator">></span> a <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">>></span><span class="token operator">></span> b <span class="token operator">=</span> a <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">id</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token number">140210586664328</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">id</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> <span class="token number">140210586664328</span> |
Như kết quả ở trên, a
và b
đang cùng tham chiếu tới một vùng nhớ chung. Bây giờ ta thử khiến b
trở thành một shallow copy của a
xem sao:
1 2 3 4 5 6 7 | <span class="token operator">>></span><span class="token operator">></span> b <span class="token operator">=</span> a<span class="token punctuation">.</span>copy<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment"># Create a shallow copy</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">id</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token number">140210586664328</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">id</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> <span class="token number">140210586663880</span> |
Lúc này, hai biến a
và b
đã không còn chung một id, hay có thể hiểu là không còn trỏ tới cùng một vùng nhớ nữa. Chúng ta có thể dùng từ khóa is
để kiểm tra:
1 2 3 4 5 6 | <span class="token operator">>></span><span class="token operator">></span> a <span class="token keyword">is</span> b <span class="token boolean">False</span> <span class="token operator">>></span><span class="token operator">></span> a <span class="token operator">==</span> b <span class="token boolean">True</span> |
Lưu ý rằng khi sử dụng ==
vẫn trả về True
vì đang lúc này đang so sánh về giá trị, không phải về id.
help()
Khi debug, chúng ta có thể dùng phương thức này để hiển thị documentation về một function, class, module hay biến nào đó.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <span class="token builtin">help</span><span class="token punctuation">(</span>AlienDog<span class="token punctuation">)</span> Help on <span class="token keyword">class</span> <span class="token class-name">AlienDog</span> <span class="token keyword">in</span> module __main__<span class="token punctuation">:</span> <span class="token keyword">class</span> <span class="token class-name">AlienDog</span><span class="token punctuation">(</span>Dog<span class="token punctuation">)</span> <span class="token operator">|</span> This <span class="token keyword">class</span> <span class="token class-name">is</span> inherited <span class="token keyword">from</span> Dog <span class="token keyword">class</span><span class="token punctuation">.</span> <span class="token operator">|</span> <span class="token operator">|</span> Method resolution order<span class="token punctuation">:</span> <span class="token operator">|</span> AlienDog <span class="token operator">|</span> Dog <span class="token operator">|</span> builtins<span class="token punctuation">.</span><span class="token builtin">object</span> <span class="token operator">|</span> <span class="token operator">|</span> Methods defined here<span class="token punctuation">:</span> <span class="token operator">|</span> <span class="token operator">|</span> fly<span class="token punctuation">(</span>self<span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token operator">|</span> <span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span> <span class="token operator">|</span> Methods inherited <span class="token keyword">from</span> Dog<span class="token punctuation">:</span> <span class="token operator">|</span> <span class="token operator">|</span> __init__<span class="token punctuation">(</span>self<span class="token punctuation">,</span> name<span class="token punctuation">)</span> <span class="token operator">|</span> Initialize self<span class="token punctuation">.</span> See <span class="token builtin">help</span><span class="token punctuation">(</span><span class="token builtin">type</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">for</span> accurate signature<span class="token punctuation">.</span> <span class="token operator">|</span> <span class="token operator">|</span> bark<span class="token punctuation">(</span>self<span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token operator">|</span> <span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span> <span class="token operator">|</span> Data descriptors inherited <span class="token keyword">from</span> Dog<span class="token punctuation">:</span> <span class="token operator">|</span> <span class="token operator">|</span> __dict__ <span class="token operator">|</span> dictionary <span class="token keyword">for</span> instance variables <span class="token punctuation">(</span><span class="token keyword">if</span> defined<span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token operator">|</span> __weakref__ <span class="token operator">|</span> <span class="token builtin">list</span> of weak references to the <span class="token builtin">object</span> <span class="token punctuation">(</span><span class="token keyword">if</span> defined<span class="token punctuation">)</span> |
Các phương thức khác
Ngoài ra còn có một số phương thức khác như: repr()
, getattr()
, sys()
hoặc issubclass()
để kiểm tra xem một class có là thừa kế của một class khác không, callable()
dùng để kiểm tra xem đó có phải là một hàm không.
1 2 3 4 5 | <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">issubclass</span><span class="token punctuation">(</span>AlienDog<span class="token punctuation">,</span> Dog<span class="token punctuation">)</span> <span class="token boolean">True</span> <span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">callable</span><span class="token punctuation">(</span>AlienDog<span class="token punctuation">.</span>fly<span class="token punctuation">)</span> <span class="token boolean">True</span> |
Nếu như bạn quá lười để thực hiện từng phương thức trên cho một object nhất định?
May mắn thay, chúng ta có thể viết một function tổng hợp để dùng trong một lần gọi:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">def</span> <span class="token function">introspect</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">for</span> func <span class="token keyword">in</span> <span class="token punctuation">[</span><span class="token builtin">type</span><span class="token punctuation">,</span> <span class="token builtin">id</span><span class="token punctuation">,</span> <span class="token builtin">dir</span><span class="token punctuation">,</span> <span class="token builtin">vars</span><span class="token punctuation">,</span> <span class="token builtin">callable</span><span class="token punctuation">]</span><span class="token punctuation">:</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"%s(%s):tt%s"</span> <span class="token operator">%</span> <span class="token punctuation">(</span>func<span class="token punctuation">.</span>__name__<span class="token punctuation">,</span> introspect<span class="token punctuation">.</span>__code__<span class="token punctuation">.</span>co_varnames<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> func<span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">>></span><span class="token operator">></span> introspect<span class="token punctuation">(</span>Bird<span class="token punctuation">)</span> <span class="token builtin">type</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token operator"><</span><span class="token keyword">class</span> <span class="token string">'type'</span><span class="token operator">></span> <span class="token builtin">id</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token number">42333256</span> <span class="token builtin">dir</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'__class__'</span><span class="token punctuation">,</span> <span class="token string">'__delattr__'</span><span class="token punctuation">,</span> <span class="token string">'__dict__'</span><span class="token punctuation">,</span> <span class="token string">'__dir__'</span><span class="token punctuation">,</span> <span class="token string">'__doc__'</span><span class="token punctuation">,</span> <span class="token string">'__eq__'</span><span class="token punctuation">,</span> <span class="token string">'__format__'</span><span class="token punctuation">,</span> <span class="token string">'__ge__'</span><span class="token punctuation">,</span> <span class="token string">'__getattribute__'</span><span class="token punctuation">,</span> <span class="token string">'__gt__'</span><span class="token punctuation">,</span> <span class="token string">'__hash__'</span><span class="token punctuation">,</span> <span class="token string">'__init__'</span><span class="token punctuation">,</span> <span class="token string">'__init_subclass__'</span><span class="token punctuation">,</span> <span class="token string">'__le__'</span><span class="token punctuation">,</span> <span class="token string">'__lt__'</span><span class="token punctuation">,</span> <span class="token string">'__module__'</span><span class="token punctuation">,</span> <span class="token string">'__ne__'</span><span class="token punctuation">,</span> <span class="token string">'__new__'</span><span class="token punctuation">,</span> <span class="token string">'__reduce__'</span><span class="token punctuation">,</span> <span class="token string">'__reduce_ex__'</span><span class="token punctuation">,</span> <span class="token string">'__repr__'</span><span class="token punctuation">,</span> <span class="token string">'__setattr__'</span><span class="token punctuation">,</span> <span class="token string">'__sizeof__'</span><span class="token punctuation">,</span> <span class="token string">'__str__'</span><span class="token punctuation">,</span> <span class="token string">'__subclasshook__'</span><span class="token punctuation">,</span> <span class="token string">'__weakref__'</span><span class="token punctuation">,</span> <span class="token string">'fly'</span><span class="token punctuation">]</span> <span class="token builtin">vars</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">'__module__'</span><span class="token punctuation">:</span> <span class="token string">'__main__'</span><span class="token punctuation">,</span> <span class="token string">'__init__'</span><span class="token punctuation">:</span> <span class="token operator"><</span>function Bird<span class="token punctuation">.</span>__init__ at <span class="token number">0x7f855108d2f0</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token string">'fly'</span><span class="token punctuation">:</span> <span class="token operator"><</span>function Bird<span class="token punctuation">.</span>fly at <span class="token number">0x7f855108d378</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token string">'__dict__'</span><span class="token punctuation">:</span> <span class="token operator"><</span>attribute <span class="token string">'__dict__'</span> of <span class="token string">'Bird'</span> objects<span class="token operator">></span><span class="token punctuation">,</span> <span class="token string">'__weakref__'</span><span class="token punctuation">:</span> <span class="token operator"><</span>attribute <span class="token string">'__weakref__'</span> of <span class="token string">'Bird'</span> objects<span class="token operator">></span><span class="token punctuation">,</span> <span class="token string">'__doc__'</span><span class="token punctuation">:</span> <span class="token boolean">None</span><span class="token punctuation">}</span> <span class="token builtin">callable</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token boolean">True</span> |
Quá tiện khi chỉ cần gọi một dòng là hiện ra được bao nhiêu là điều huyền bí về object nhỉ?
Tổng kết
Qua phần tổng hợp vừa rồi, mình đã giới thiệu được khái niệm “code introspection” và cách sử dụng cơ bản các built-in functions của Python. Hi vọng các bạn thấy nó hữu ích. Ngoài những phương thức ở trên, chúng ta còn có thể dùng package inspect
với những tùy biến “xịn xò” hơn, giúp các bạn trở nên quyền lực hơn khi thực hiện code introspection. Các bạn có thể dành thời gian tìm hiểu thêm.
Cuối cùng, mình tin rằng bài viết có lẽ vẫn còn nhiều thiếu sót. Chính ví thế, mình rất mong nhận được sự góp ý của mọi người để bài viết được hoàn thiện hơn. Mình xin cảm ơn và hẹn gặp lại mọi người ở bài viết tới! ^^
Enjoy coding!
Link gốc
https://nguyendhn.wordpress.com/2020/09/10/code-introspection-trong-python/
Tài liệu tham khảo
https://towardsdatascience.com/4-easy-to-use-introspection-functions-in-python-49bd5ee3a2
https://medium.com/better-programming/python-reflection-and-introspection-97b348be54d8.