3

我想控制当用户在 ipython 中的自定义对象上使用制表符完成时出现哪些方法 - 特别是,我想隐藏我已弃用的​​函数。我仍然希望这些方法是可调用的,但我不希望用户在检查对象时看到它们并开始使用它们。这是可能的吗?

4

4 回答 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,那么此 hack 将不起作用。另外,我很确定会影响性能,因为您在内部定义了每个 dep'd 函数__getattr__。这不会影响您的其他属性查找(如果我将它们放入__getattribute__,那将是另一回事),但它会减慢对那些已弃用的方法的访问速度。通过将每个函数定义放在其自己的 if 块中,而不是进行列表成员资格检查,这可以(很大程度上但不是完全)否定,但是,根据您的函数有多大,维护起来可能真的很烦人。

更新:

1)如果您想制作已弃用的函数方法(并且您确实这样做了),只需使用

import types
return types.MethodType(eval(attrname), self)

代替

return eval(attrname)

在上面的代码片段中,添加 self 作为函数 defs 的第一个参数。它将它们转换为实例方法(因此您可以随心所欲地使用 im_class、im_func 和 im_self)。

2)如果__getattr__钩子没有让你兴奋,还有另一种选择(我知道)(albiet,有它自己的警告,我们会谈到那些):将不推荐使用的函数定义放在里面__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__属性中,用户可以在其中发现它们。

于 2010-04-06T16:44:13.970 回答
1

似乎有一种特殊的魔法方法可以用于 dir(): 调用的 introcpection __dir__()。这不是你要找的吗?

于 2010-04-09T20:17:36.127 回答
0

DeprecationWarning调用方法之前不会发出 ,因此您必须在类上具有一个单独的属性来存储不推荐使用的方法的名称,然后在建议完成之前检查它。

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

于 2010-03-28T01:01:17.543 回答
0

关于 IPython 中的完成机制,记录在这里:

http://ipython.scipy.org/doc/manual/html/api/generated/IPython.core.completer.html#ipcompleter

但是对你来说一个非常有趣的例子是特征完成器,它正是你想要做的:它从自动完成中隐藏了一些方法(基于它们的名称)。

这是代码:

http://projects.scipy.org/ipython/ipython/browser/ipython/trunk/IPython/Extensions/ipy_traits_completer.py

于 2010-04-09T19:43:25.850 回答