从选项补全中隐藏已弃用的方法

3
我希望在IPython中控制自定义对象的制表符补全时显示哪些方法,特别是我想隐藏已经过时的函数。我仍然希望这些方法是可调用的,但如果用户检查该对象,我不希望他们看到并开始使用它们。这是可能的吗?

你想要自定义ipython以获得该行为,还是想要在每个标准ipython安装上提供表现出这种方式的模块? - flight
4个回答

4

以下是部分答案。我将发布示例代码,然后解释为什么它只是部分答案。
代码:

class hidden(object): # or whatever its parent class is
    def __init__(self):
        self.value = 4
    def show(self):
        return self.value
    def change(self,n):
        self.value = n
    def __getattr__(self, attrname):
        # put the dep'd method/attribute names here
        deprecateds = ['dep_show','dep_change']
        if attrname in deprecateds:
            print("These aren't the methods you're looking for.")
            def dep_change(n):
                self.value = n
            def dep_show():
                return self.value
            return eval(attrname)
        else:
            raise AttributeError, attrname

现在有一个警告:它们不是方法(请注意第一个变量缺少self)。如果您需要用户(或代码)能够在任何已弃用的方法上调用im_class、im_func或im_self,则此方法将无法起作用。此外,我相当确定会出现性能问题,因为您正在__getattr__中定义每个已弃用的函数。这不会影响您的其他属性查找(如果我将它们放在__getattribute__中,那就是另一回事了),但它会减慢对这些已弃用方法的访问速度。这可以通过将每个函数定义放入其自己的if块中而不是进行列表成员检查来(在很大程度上,但并非完全)消除,但是,根据您的函数大小,这可能很难维护。
更新:
1)如果您想使已弃用的函数成为方法(您确实想这样做),只需使用
import types
return types.MethodType(eval(attrname), self)

替代

return eval(attrname)

在上面的代码片段中,将self作为函数defs的第一个参数添加进去。这将把它们转换为instancemethods(因此您可以尽情使用im_class、im_func和im_self)。
2)如果__getattr__钩子没有让你激动,还有另一个选择(我知道的)(虽然它有自己的注意事项,我们将介绍这些):将弃用的函数定义放在__init__中,并使用自定义__dir__隐藏它们。以下是使用此方法完成上述代码的方式:
class hidden(object):
    def __init__(self):
        self.value = 4
        from types import MethodType
        def dep_show(self):
            return self.value
        self.__setattr__('dep_show', MethodType(dep_show, self))
        def dep_change(self, n):
            self.value = n
        self.__setattr__('dep_change', MethodType(dep_change, self))
    def show(self):
        return self.value
    def change(self, n):
        self.value = n
    def __dir__(self):
        heritage = dir(super(self.__class__, self)) # inherited attributes
        hide = ['dep_show', 'dep_change']
        show = [k for k in self.__class__.__dict__.keys() + self.__dict__.keys() if not k in heritage + private]
        return sorted(heritage + show)

这里的优点是每次查找时不需要重新定义函数,这样可以提高速度。缺点是因为你不需要每次查找时重新定义函数,所以它们必须“持续存在”。因此,虽然自定义的 __dir__ 方法可以隐藏 dir(hiddenObj) 和 IPython 的选项补全中弃用的内容,但它们仍会存在于实例的 __dict__ 属性中,用户仍然可以发现它们。

1

看起来有一个特殊的魔术方法用于内省,它被dir()调用:__dir__()。这难道不是你要找的吗?


0

DeprecationWarning 直到调用方法时才会发出,因此您必须在类上拥有一个单独的属性来存储已弃用方法的名称,然后在建议完成之前检查该属性。

或者,您可以遍历方法的 AST 寻找 DeprecationWarning,但如果类是在 C 中定义的,或者如果方法基于参数的类型或值可能会发出 DeprecationWarning,则此方法将失败。


如何控制首次使用TAB自动完成时显示的内容? - astrofrog
毫无头绪。你得在IPython源代码中瞎搞一下才行。可能与rlcompleter有关。http://docs.python.org/library/rlcompleter.html - Ignacio Vazquez-Abrams

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接