我有一个像类一样的字典,其方法可以返回其键,值和项的视图。这样做的方法尽可能简单:
class MyType(collections.MutableMapping):
def keys(self):
return collections.KeysView(self)
然而,创建一个如此简单的方法似乎毫无意义;我正在做的就是将self
传递给另一个可调用者。我更愿意将KeysView
的类构造函数视为绑定方法。执行以下操作会创建一个嵌套类(这很好,因为有时这正是您想要的),但它看起来更接近我想要做的事情:
class MyType(collections.MutableMapping):
keys = collections.KeysView
有没有内置到Python或其标准库来执行此操作?也许是这样的:
class MyType(collections.MutableMapping):
keys = bind_constructor_as_method(collections.KeysView)
我觉得functools
中应该有一些可以完成这项任务的东西,但是没有任何东西可以作为正确的答案乍一看。也许是functools.partial
,但这个名字并不能说明我想要做的事情。
我是否只需要手动滚动一个自定义描述符类来制作这样的工作?
注意:
对于工作,我经常需要使用Python 2.7,所以尽管Python 3.x的答案仍然受到赞赏(并且很有用),但它们可能不会完全缓解我个人的问题。但是,他们可能会帮助其他人解决这个问题,所以请仍然包括他们!
答案 0 :(得分:1)
functools.partialmethod()
正是您要找的。这创建了一个方法,其中self
是第一个参数。
import functools
class MyType(collections.MutableMapping):
keys = functools.partialmethod(collections.KeysView)
您还可以指定其他参数,例如,如果您想将self, 1, 2, key=5
传递给func()
,则可以functools.partialmethod(func, 1, 2, key=5)
。
但请注意,这仅适用于Python 3.4及更高版本。
答案 1 :(得分:0)
经过一番思考(以及来自这篇SO here的一些帮助),我提出了另一个适用于Python版本2和3的解决方案,尽管它不那么惯用。当@Artyer建议使用partialmethod
时,发生的事情肯定不是很清楚。实际上,这就是Python在创建新实例时所做的事情,但更明确;你看看香肠是怎么制作的。 :/
import types
import collections
class MyType(collections.MutableMapping):
def __init__(self, *args, **kwargs):
# do class specific stuff here
# create bound method per instance
self.keys = types.MethodType(collections.KeysView, self)
更好的是,我们可以在__new__
中做到更加确定继承的类得到它:
import types
import collections
class MyType(collections.MutableMapping):
def __new__(cls, *args, **kwargs):
self = super(MyType, cls).__new__(cls)
# create bound method per instance
self.keys = types.MethodType(collections.KeysView, self)
return self
如果您不喜欢types.MethodType
相对无证的性质,则可以使用functools.partial
代替:
import functools
import collections
class MyType(collections.MutableMapping):
def __new__(cls, *args, **kwargs):
self = super(MyType).__new__(cls)
# create bound method per instance
self.keys = functools.partial(collections.KeysView, self)
return self
注意:对于Python 2/3兼容性,您应该 不 使用{{1}的第三个可选class
参数}};它存在于Python 2中,但在Python 3中显然已被删除。