簡體   English   中英

在Python中,我可以隱藏基類的成員嗎?

[英]In Python, can I hide a base class's members?

我正在制作一個編程框架(基於Django),適用於編程經驗有限的學生。 學生應該從我的基類繼承(它們本身是從Django模型,表單和視圖繼承而來)。

我現在正在和一些學生一起測試這個問題,問題是當他們在IDE中編寫代碼時(大多數都是使用PyCharm),自動完成給了他們很多建議,因為有很多繼承的方法和屬性,90其中%與他們無關。

有沒有辦法隱藏這些繼承的成員? 目前我主要考慮如何在自動完成中隱藏它們(在PyCharm和其他IDE中)。 它們可以(並且可能應該)在被調用時仍然可以工作,但是不會出現在自動完成的地方。

我嘗試設置__dict__ ,但這並沒有影響自動完成中顯示的內容。 我的另一個想法是使用組合而不是繼承,但我必須更詳細地考慮這一點。

編輯 :此框架未在CS類中使用; 相反,學生將使用它來構建非CS域的應用程序。 因此,我的首要任務是盡可能保持簡單,即使它不是一種“純粹”的方法。 (盡管如此,我正在考慮這些論點,因為它們確實有價值。)

免責聲明:以下方法不是很干凈 (但這就是你要求的)。

現在,好消息是這個方法永遠不會破壞你的Python 實際上,它只會影響IDE。

但請注意,PyCharm將來可能會變得更聰明,並且無論如何都可以自動完成工作。 不過,我認為這不會成為Jetbrains團隊的首要任務!


開始了。

你所要做的就是混淆PyCharm。 PyCharm將無法可靠地跟蹤使用__import__執行的__import__ ,因此我們將使用它來導入您的django模塊(如果PyCharm沒有導入您正在導入的模塊,則無法知道您正在使用哪個類以及哪個類在自動完成窗口中顯示的方法!)。

在以下示例中,我們假設:

  • _base.py是包含要擴展的類的django文件(以及要隱藏的方法)
  • base.py是包含您要為學生提供的課程的文件(您要顯示的方法)
  • test.py是學生將要編寫的文件

_base.py

這里沒什么特別的

class DjangoBaseClass(object):
    def method_that_is_hidden(self):
        print "The hidden method is there!"

base.py

請注意導入

base = __import__("_base")  # This is equivalent to `import base`. Python understands it, but PyCharm doesn't.

class YourBaseClass(base.DjangoBaseClass):  # PyCharm doesn't know what class this is! No autocomplete.
    def method_that_shows(self):
        print "The method that shows is there!"

重要說明:在多級導入的情況下,語法略有不同。 例如,要繼承自django.views.generic.base.View ,請執行以下操作:

base = __import('django.views.generic.base', fromlist=['View',])

class MyView(base.View):
    # Your stuff

請注意,如果PyCharm將來變得更聰明,你將不得不添加更多的間接(例如,而不是__import__('base') ,你可以使用__import__(''.join(['b', 'a', 's', 'e'])) 。但這會變得混亂。

test.py

這里沒什么特別的

from base import YourBaseClass

class StudentClass(YourBaseClass):
    pass

if __name__ == "__main__":
    c = StudentClass()
    c.method_that_is_hidden()
    c.method_that_shows()

運行test.py腳本時,這些方法都有效:

$ python test.py
The hidden method is there!
The method that shows is there!

但是當您使用PyCharm時, method_that_is_hidden不會顯示在自動完成中:

隱藏的方法沒有顯示


注意:我相信PyCharm現在具有在運行測試時跟隨調用樹的功能,因此如果您的學生使用PyCharm運行測試,PyCharm可能會接受這些方法的存在。 我想他們不會在課堂定義中表現出來,但是如果你的學生寫c. ,他們可能會表明c. 你應該試一試,親眼看看。

我建議你使用組合而不是繼承。 然后設計類的接口並確定哪些方法可用。

我認為正確的解決方案是教你的學生python的命名約定 (並確保你的代碼遵循它們)。 自動填充中的選項按字母順序排列,字母表后面的'_'字符比'a'->'Z'字母更高,因此如果遵循命名約定,則公共API應首先位於自動完成列表中。 遵循該標准是他們無論如何都需要學習的一課,所以我不會試圖將它隱藏起來。

現在我可以理解為什么你可能想要隱藏Django的公共API,但是考慮一下隱藏基類API而不是實際抽象它的其他結果:如果學生不知道方法名已被使用了怎么辦?一個基類(因為它沒有顯示在自動完成中,或者你提供的文檔中),決定命名一個他們自己的方法,並最終完全破壞一切,因為他們覆蓋了一個方法而沒有意識到它?

基本上,你試圖隱藏學生實際上在課堂上的內容,而不是向他們傳授他們需要知道的信息,而不是他們不應該做的事情。 這幾乎總是導致簡單地增加出錯的可能性。 它還教他們完全依賴於IDE的功能; EX如果它不在自動完成中,它一定不存在!

我認為您需要查看您所關注的問題的根本原因,並嘗試創建解決這些問題的課程,而不是找出解決這些問題的黑客,並可能教會您的學生重新編程。 學習如何正確閱讀文檔是一個真正的,非常重要的部分,是一個程序員。 不要試着讓他們不必學習那一課。 地獄,沒有學到那個教訓是什么導致了Stack Exchange上99%的問題(尤其是因為任何原因在Python上)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM