我正在制作一个编程框架(基于Django),适用于编程经验有限的学生。学生应该从我的基类继承(它们本身是从Django模型,表单和视图继承而来)。
我现在正在和一些学生一起测试这个问题,问题是当他们在IDE中编写代码时(他们大多数都使用PyCharm),自动完成给了他们很多建议,因为有很多继承的方法和属性,其中90%与它们无关。
有没有办法隐藏这些继承的成员?目前我主要考虑如何在自动完成中隐藏它们(在PyCharm和其他IDE中)。如果被调用,他们可以(也可能应该)仍然有效,但不会出现在自动完成等地方。
我尝试设置__dict__
,但这并不会影响自动填充中显示的内容。我的另一个想法是使用组合而不是继承,但我必须更详细地考虑这一点。
编辑:此框架未在CS类中使用;相反,学生将使用它来构建非CS域的应用程序。因此,我的首要任务是尽可能保持简单,即使它不是纯粹的"做法。 (尽管如此,我正在考虑这些论点,因为它们确实有价值。)
答案 0 :(得分:8)
免责声明:以下方法不是很干净(但这就是您要求的)。
现在,好消息是这种方法永远不会破坏你的Python 。实际上,它只会影响IDE。
然而,请注意,PyCharm将来可能变得更聪明,并且无论如何都可以自动完成工作。不过,我认为这不是Jetbrains团队的优先考虑事项!
我们走了。
所有你需要做的就是混淆PyCharm。 PyCharm无法可靠地跟踪使用__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.
。你应该试一试,亲眼看看。
答案 1 :(得分:2)
我建议您使用合成而不是继承。然后设计类的接口并确定哪些方法可用。
答案 2 :(得分:-1)
我认为正确的解决方案是teach your students python's naming conventions(并确保您的代码遵循它们)。自动填充中的选项按字母顺序排列,'_'
字符在字母表后面的位置比'a'->'Z'
晚,因此如果您遵循命名约定,则公共API应首先位于自动完成列表中。遵循该标准是他们无论如何都需要学习的一课,所以我不会试图将它隐藏起来。
现在我可以理解为什么你可能想要隐藏Django的公共API,但考虑隐藏基类API而不是实际抽象它的其他结果:如果学生不知道方法名称是什么怎么办?已经被基类使用(因为它没有显示在自动完成中,或者你提供的文档中),决定命名一个他们自己的方法,并完全破坏一切,因为他们覆盖了一个方法而没有意识到它?
基本上,你试图隐藏学生在课堂上的实际内容,而不是向他们传授他们需要知道的信息,而不是他们不应该做的事情。这几乎总是导致简单地增加出错的可能性。它还教他们完全依赖于IDE的功能; E.X.如果它不在自动完成中,则一定不存在!
我认为您需要查看您所关注问题的根本原因,并尝试创建解决这些问题的课程,而不是找出解决这些问题的黑客,并可能教会您的学生回归编程实践。学习如何正确阅读文档是一个真正的,非常重要的部分,是一个程序员。不要试着让他们不必学习那一课。地狱,没有学到那个教训是什么导致了Stack Exchange上99%的问题(特别是在Python上出于任何原因)。