“以编程方式”将内容添加到课程中?

时间:2011-08-05 01:47:29

标签: python class dictionary initialization python-3.x

我正在编写一个包含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

由于以下几个原因,这不起作用:

  1. 初始化类时,方法没有绑定,因为它们不在类dict中?
  2. 我无法使用__get__手动绑定方法,因为类名尚未绑定到任何命名空间。
  3. 所以:

    1. 我该怎么做?
    2. 我是否必须退出课程并在课程初始化后定义dict?
    3. 是否真的有必要在方法上调用__get__来绑定它们吗?
    4. Update0

      这些方法将按如下方式调用:

      def func(self, int):
          return self.map[int]()
      

      关于数字索引/列表:并非所有索引都存在。我不知道在Python中可以做list([1]=a, [2]=b, [1337]=leet),是否有相同的东西?我应该只分配一个任意长度列表并设置具体值吗?我唯一感兴趣的是最小化查找时间,它是否真的与O(1)哈希{}不同?我现在忽略了这个过早的优化。

4 个答案:

答案 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作为变量的名称,它也是内置的。

字典绝对是这类事物的正确类型。

编辑:如果您使用新式课程,这也适用于staticmethodclassmethod

答案 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)

这种模式可以在一些现有的库模块中找到。