python jedi,动态属性的自动补全

python jedi, autocompletion for dynamic attribute

我正在尝试写 class。 class 的对象可以采用 label/value 对并以 label 可以作为属性访问的方式存储它,返回 valueobj.label -> value

此处的主要目标是在 jupyter notebooks 中实现自动完成,因此 obj.<tab> 应该生成标签列表作为自动完成建议。下面的 class 实现了这个:

class Autocompleter:
    def __init__(self, ):
        self._funcs = {}
    
    def add(self, label):
        self._funcs[label] = 1.
        
    def __dir__(self):
        return list(self._funcs.keys())
    
    def __getattr__(self, name):
        if name in dir(self):
            return self._funcs[name]

问题:访问无效属性时,__getattr__ 只是 returns None。我宁愿让它抛出异常。我可以想到两种方法来实现这一点,但不幸的是,这两种方法都破坏了自动完成:

__getattr__ 更改为:

def __getattr__(self, name):
    return self._funcs[name]

def __getattr__(self, name):
    if name in dir(self):
        return self._funcs[name]
    else:
        raise Exception('invalid name')

产生了所需的异常,但中断了自动完成:

a = Autocompleter()
a.add('foo')

现在 a.<tab> 不建议 foo 自动完成,它什么都不做。据我所知,jediterlab 中默认使用 jedi 进行自动完成。 问题:有没有办法既使无效名称异常又使自动完成功能正常工作?

我自己想出来了。处理无效属性名称的正确方法是引发 AttributeError。这才可以被jedi看懂。

def __getattr__(self, name):
    if name in dir(self):
        return self._funcs[name]
    raise AttributeError(name)

请注意,__dir__ 方法仍然需要。