一個在交流群裡討論過兩輪的問題,答案竟然跟一個 PEP 有關
阿新 • • 發佈:2020-08-14
Python 中有沒有辦法通過類方法找到其所屬的類?
這個問題看起來不容易理解,我可以給出一個例子:
```python
class Test:
@xxx
def foo(self):
pass
```
現在有一個類和一個類方法,其中類方法上有一個裝飾器。
**我們的問題就是要在裝飾器程式碼中動態地獲得 Test 這個類(類名+類物件)。**
去年 11 月份的時候,我在微信讀者群裡提出了這個問題,當時引起了小範圍的討論。
沒想到在今年上個月的時候,群裡又有人提了同樣的問題(我在討論結束後才看到),而且最終都找到了 stackoverflow 上一個同樣的問題:
![](http://ww1.sinaimg.cn/large/68b02e3bgy1ghocppegtfj20bh0m8abo.jpg)
stackoverflow 上的問題提得很明確:[Get defining class of unbound method object in Python 3](https://stackoverflow.com/questions/3589311/get-defining-class-of-unbound-method-object-in-python-3) 。但是 unbound method 的叫法已經不常見了,詳細的討論也就不展開了,感興趣的同學可以去查閱。
這個問題的關鍵是要使用在 Python 3.3 中引入的\_\_qualname\_\_ 屬性,通過它可以獲取上層類的名稱。
鋪墊了這麼多,開始進入本文的正題了:**\_\_qualname\_\_ 屬性是什麼東西?為什麼 Python 3 要特別引入它呢?**
下文是 PEP-3155 的翻譯摘錄,清楚地說明了這個屬性的來龍去脈。
完整內容可在 Github 倉庫檢視:[https://github.com/chinesehuazhou/peps-cn/blob/master/StandardsTrack/3155--%E7%B1%BB%E5%92%8C%E6%96%B9%E6%B3%95%E7%9A%84%E7%89%B9%E5%AE%9A%E5%90%8D%E7%A7%B0.md](https://github.com/chinesehuazhou/peps-cn/blob/master/StandardsTrack/3155--%E7%B1%BB%E5%92%8C%E6%96%B9%E6%B3%95%E7%9A%84%E7%89%B9%E5%AE%9A%E5%90%8D%E7%A7%B0.md)
-------------------摘錄開始--------------------
## 原理
一直以來,對於巢狀類的自省,Python 的支援很不夠。給定一個類物件,根本不可能知道它是在某個類中定義的,還是在頂層模組中定義的;而且,如果是前者,也不可能知道它具體是在哪個類中定義的。雖然巢狀類通常被認為是不太好的用法,但這不應該成為不支援內層自省的理由。
Python 3 因為丟棄了以前的未繫結方法(unbound method),而受到了侮辱性的傷害。
在 Python 2 中,給出以下定義:
```python
class C:
def f():
pass
```
你可以從`C.f` 物件中獲得其所屬的類:
```python
>>> C.f.i