在Python中,我可以隐藏基类的成员吗?

时间:2014-05-04 14:43:11

标签: python pycharm

我正在制作一个编程框架(基于Django),适用于编程经验有限的学生。学生应该从我的基类继承(它们本身是从Django模型,表单和视图继承而来)。

我现在正在和一些学生一起测试这个问题,问题是当他们在IDE中编写代码时(他们大多数都使用PyCharm),自动完成给了他们很多建议,因为有很多继承的方法和属性,其中90%与它们无关。

有没有办法隐藏这些继承的成员?目前我主要考虑如何在自动完成中隐藏它们(在PyCharm和其他IDE中)。如果被调用,他们可以(也可能应该)仍然有效,但不会出现在自动完成等地方。

我尝试设置__dict__,但这并不会影响自动填充中显示的内容。我的另一个想法是使用组合而不是继承,但我必须更详细地考虑这一点。

编辑:此框架未在CS类中使用;相反,学生将使用它来构建非CS域的应用程序。因此,我的首要任务是尽可能保持简单,即使它不是纯粹的"做法。 (尽管如此,我正在考虑这些论点,因为它们确实有价值。)

3 个答案:

答案 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没有显示在自动完成中:

the hidden method does not show


注意:我相信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上出于任何原因)。