我正在编写一个包含int
方法映射的dict的类。但是,在此dict中设置值会导致dict填充未绑定的函数。
class A:
def meth_a: ...
def meth_b: ...
...
map = {1: meth_a, 2: meth_b, ...}
for int in ...:
map[int] = meth_x
由于以下几个原因,这不起作用:
dict
中?__get__
手动绑定方法,因为类名尚未绑定到任何命名空间。所以:
__get__
来绑定它们吗?这些方法将按如下方式调用:
def func(self, int):
return self.map[int]()
关于数字索引/列表:并非所有索引都存在。我不知道在Python中可以做list([1]=a, [2]=b, [1337]=leet)
,是否有相同的东西?我应该只分配一个任意长度列表并设置具体值吗?我唯一感兴趣的是最小化查找时间,它是否真的与O(1)
哈希{}
不同?我现在忽略了这个过早的优化。
答案 0 :(得分:3)
我不确定为什么你正在做你正在做的事情,但你肯定可以在课程定义中做到这一点;你不需要__init__
。
class A:
def meth_a(self): pass
m = {1: meth_a}
def foo(self, number):
self.m[number](self)
a = A()
a.foo(1)
“未绑定”实例方法只需要您手动传递该类的实例,并且它可以正常工作。
另外,请不要使用int
作为变量的名称,它也是内置的。
字典绝对是这类事物的正确类型。
编辑:如果您使用新式课程,这也适用于staticmethod
和classmethod
。
答案 1 :(得分:2)
首先不要使用变量“map”,因为将获取python函数映射中的构建。
您需要使用init方法并使用self在init方法中初始化字典。现在的字典只是类的一部分,而不是类的实例的一部分。如果你希望类的实例也有字典,你需要创建一个init方法并在那里初始化你的字典。所以你需要这样做:
def __init__(self):
self.mymap[int] = self.meth_x
或者如果你想让字典成为一个类变量,那么:
def __init__(self):
A.mymap[int] = self.meth_x
答案 2 :(得分:2)
目前还不完全清楚你要做的事情。我怀疑你想编写像
这样的代码class Foo(object):
def __init__(self, name):
self.name = name
def method_1(self, bar):
print self.name, bar
# ... something here
my_foo = Foo('baz')
my_foo.methods[1]('quux')
# prints "baz quux"
所以,methods
属性需要以某种方式返回绑定的实例方法,但不能直接调用。这是使用descriptor
的好机会。我们需要做一些在通过实例访问时返回特殊对象的东西,并且我们需要该特殊对象在索引时返回绑定方法。让我们从内部开始,逐步解决。
>>> import types
>>> class BindMapping(object):
... def __init__(self, instance, mapping):
... self.instance, self.mapping = instance, mapping
...
... def __getitem__(self, key):
... func = self.mapping[key]
... if isinstance(func, types.MethodType):
... return types.MethodType(func.im_func, self.instance, func.im_class)
... else:
... return types.MethodType(func, self.instance, type(self))
...
我们只是实现映射协议的最小最小值,并完全推迟到底层集合。这里我们使用types.MethodType
在需要时获取一个真实的实例方法,包括绑定已经是实例方法的东西。我们会在一分钟内看到它的用处。
我们可以直接实现描述符,但出于此目的,property
已经从描述符中完成了我们需要的所有操作,因此我们只需定义一个返回正确构造的BindMapping
实例。
>>> class Foo(object):
... def method_1(self):
... print "1"
... def method_2(self):
... print "2"
...
... _mapping = [method_1, method_2]
...
... @property
... def mapping(self):
... return BindMapping(self, self._mapping)
...
只是为了踢,我们还在课堂体外引入了一些额外的方法。注意在类体内添加的方法是函数,就像在外面添加的函数一样;在类体外添加的方法是实际的实例方法(尽管是未绑定的)。
>>> def method_3(self):
... print "3"
...
>>> Foo._mapping.append(method_3)
>>> Foo._mapping.append(Foo.method_1)
>>> map(type, Foo._mapping)
[<type 'function'>, <type 'function'>, <type 'function'>, <type 'instancemethod'>]
它的工作原理如下:
>>> f = Foo()
>>> for i in range(len(f._mapping)):
... f.mapping[i]()
...
1
2
3
1
>>>
答案 3 :(得分:1)
这对我来说似乎有点令人费解。最终目标是什么?
如果您真的想要这样做,您可以利用这些方法包含在映射中的事实(__dict__
)。
class A(object):
def meth_1(self):
print("method 1")
def meth_2(self):
print("method 2")
def func(self, i):
return getattr(self, "meth_{}".format(i))()
a = A()
a.func(2)
这种模式可以在一些现有的库模块中找到。