覆盖__dir__方法的正确方法是什么? [英] What is the correct way to override the __dir__ method?
问题描述
这个问题更多地是关于 __ dir __
而不是 numpy
。
This question is meant to be more about __dir__
than about numpy
.
我有一个的子类numpy.recarray
(在python 2.7中,numpy 1.6.2),我注意到了 recarray
在 dir
对象时未列出字段名称(因此ipython的自动完成功能不起作用)。
I have a subclass of numpy.recarray
(in python 2.7, numpy 1.6.2), and I noticed recarray
's field names are not listed when dir
ing the object (and therefore ipython's autocomplete doesn't work).
尝试修复它,我尝试在我的子类中覆盖 __ dir __
,如下所示:
Trying to fix it, I tried overriding __dir__
in my subclass, like this:
def __dir__(self):
return sorted(set(
super(MyRecArray, self).__dir__() + \
self.__dict__.keys() + self.dtype.fields.keys()))
结果为: AttributeError:'super'对象没有属性'__dir __'
。
(我发现这里这应该在python 3.3中实际工作......)
which resulted with: AttributeError: 'super' object has no attribute '__dir__'
.
(I found here this should actually work in python 3.3...)
作为解决方法,我试过:
As a workaround, I tried:
def __dir__(self):
return sorted(set(
dir(type(self)) + \
self.__dict__.keys() + self.dtype.fields.keys()))
据我所知,这个有效,但当然不是很优雅。
As far as I can tell, this one works, but of course, not as elegantly.
问题:
- 后一种解决方案在我的情况下是正确的,即对于
recarray
? - 有没有办法让它在一般情况下有效?在我看来它不适用于多重继承(打破
超级
- 调用链),当然,对于没有__ dict __ <的对象/ code> ...
- 您知道为什么
recarray
不支持列出其字段名称开头吗?仅仅是疏忽?
- Is the latter solution correct in my case, i.e. for a subclass of
recarray
? - Is there a way to make it work in the general case? It seems to me it wouldn't work with multiple inheritance (breaking the
super
-call chain), and of course, for objects with no__dict__
... - Do you know why
recarray
does not support listing its field names to begin with? mere oversight?
推荐答案
Python 2.7 +,3.3 + class mixin,简化了方法。希望它会有所帮助。 要点。
Python 2.7+, 3.3+ class mixin that simplifies implementation of __dir__ method in subclasses. Hope it will help. Gist.
import six
class DirMixIn:
""" Mix-in to make implementing __dir__ method in subclasses simpler
"""
def __dir__(self):
if six.PY3:
return super(DirMixIn, self).__dir__()
else:
# code is based on
# http://www.quora.com/How-dir-is-implemented-Is-there-any-PEP-related-to-that
def get_attrs(obj):
import types
if not hasattr(obj, '__dict__'):
return [] # slots only
if not isinstance(obj.__dict__, (dict, types.DictProxyType)):
raise TypeError("%s.__dict__ is not a dictionary"
"" % obj.__name__)
return obj.__dict__.keys()
def dir2(obj):
attrs = set()
if not hasattr(obj, '__bases__'):
# obj is an instance
if not hasattr(obj, '__class__'):
# slots
return sorted(get_attrs(obj))
klass = obj.__class__
attrs.update(get_attrs(klass))
else:
# obj is a class
klass = obj
for cls in klass.__bases__:
attrs.update(get_attrs(cls))
attrs.update(dir2(cls))
attrs.update(get_attrs(obj))
return list(attrs)
return dir2(self)
这篇关于覆盖__dir__方法的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!