0
class class_name:
    def foo1(self):
        print "foo1"

    def foo2(self):
        print "foo2"

    def foo(self, key):
        self.dictionary[key]()

dictionary = {
'key1' : class_name.foo1,
'key2' : class_name.foo2
}

>>>class_name().foo('key1')

错误:AttributeError: class_name instance has no attribute 'dictionary'

虽然我理解错误,但我不知道如何纠正它。

即使我在类中定义字典“通过将其缩进到类定义中,它也会生成错误 NameError: name 'class_name' is not defined” *

任何有关如何解决此问题的建议表示赞赏。

编辑:我需要一个类的字典,而不是每个对象实例一个字典

对真正问题的一点见解:我正在做一个国际象棋游戏。所以在定义游戏逻辑的同时,每个棋子都有自己的移动风格。我想调用一个函数来根据棋盘的当前状态给我合法的移动。这个单个函数(在示例中为 foo())必须根据棋子的类型调用其他函数,并为这些函数提供对象实例(和其他参数),以便它们可以计算移动。我面临的问题是将对象实例传递给特定于片段的函数(foo1() 和 foo2())。

也许这会有所帮助。这就是我想在函数中实现的foo()

switch(key){
    case 'key1':
        self.foo1();
        break;
    case 'key2':
        self.foo2();
        break;
}

* 从评论中添加

4

4 回答 4

1

在类之外定义时遇到的问题dictionary是该类没有dictionaryas 属性。你可以解决这个问题:

class_name.dictionary = {'foo1': class_name.foo1, 'foo2': class_name.foo2}

类定义之后。

您在类中定义时看到的错误dictionary是由于您无法在类定义中引用该类,因为执行该代码时该类不存在。

你必须记住的是,python 没有任何类型的“声明”语句。所有语句执行代码。因此,类的主体由解释器在新范围内运行,然后将创建的范围设置为__dict__类对象的范围。

由于执行了类定义,因此您可以直接从该范围引用foo1and函数:foo2

In [9]: class A(object):
   ...:     def foo1(self):
   ...:         print('foo1')
   ...:     def foo2(self):
   ...:         print('foo2')
   ...:     def foo(self, key):
   ...:         self.dictionary[key](self)
   ...:     dictionary = {'foo1': foo1, 'foo2': foo2}  # NOTE: do NOT use cls_name.method

In [10]: a = A()

In [11]: a.foo('foo1')
foo1

In [12]: a.foo('foo2')
foo2

但是请注意,在foo方法内部(即使是第一个解决方案),您还必须手动传递self参数。

发生这种情况是因为在创建时dictionary您正在分配函数(或 python2 中的未绑定方法)foo1foo2,而不是实例方法,因此这些值没有关于它们被调用的实例的信息。


我同意另一个答案,这种模式并不是真的有用,因为您可以使用getattr来实现相同的功能而无需使用dicts 。干脆做getattr(instance, method_name)()

于 2013-09-25T11:30:43.987 回答
1

您可以存储函数名称并使用 getattr 访问它们,而不是将函数存储在字典中。

class class_name:
    dictionary = {
    'key1' : 'foo1',
    'key2' : 'foo2'
    }

    def foo1(self):
        print "foo1"

    def foo2(self):
        print "foo2"

    def foo(self, key):
        getattr(self, self.dictionary[key])()

您现在可以执行此操作

>>> class_name().foo('key1')
foo1

字典对于所有实例都是相同的。

>>> c1 = class_name()
>>> c2 = class_name()
>>> c2.dictionary['key3'] = 'foo1'
>>> c1.foo('key3')
foo1

也就是说,我不太确定您想要实现什么以及这是否是正确的方法。

为什么特定于片段的函数不是片段基类的一部分并在不同的特定片段类中被覆盖?像这样的东西

class class_name:
    def foo(self, piece):
        print piece.get_valid_moves()

class BasePiece:
    def get_valid_moves():
        raise NotImplementedError

class Queen:
    def get_valid_moves():
        return ['diagonal', 'vertical', 'horizontal']

class Tower:
    def get_valid_moves():
        return ['vertical', 'horizontal']
于 2013-09-25T11:32:53.557 回答
0

你已经dictionary在你的班级之外定义了,所以self.dictionary没有意义。
如果您想在每个类实例中都有一个字典,请在__init__ See here for details中设置它

试试这个

class class_name:
    def foo1(self):
        print "foo1"

    def foo2(self):
        print "foo2"

    def foo(self, key):
        self.dictionary[key]()

    def __init__(self):
        self.dictionary = {
        'key1' : self.foo1,
        'key2' : self.foo2
        }

编辑 如果您希望 class_name 的所有实例在同一个字典中使用相同的 foo1 和 foo2,并且这些方法是实例方法,那么您打算使用哪个实例?或者 foo1 和 foo2 不应该是实例方法?在这种情况下,您为什么还要使用课程?

于 2013-09-25T10:58:40.520 回答
0

您要么需要创建一个对象,然后将此对象传递给字典,例如:

my_object = class_name()
dictionary = {
    'key1' : my_object.foo1,
    'key2' : my_object.foo2
}

或者创建静态方法:

class class_name:
    @staticmethod
    def foo1():
        print "foo1"

    @staticmethod
    def foo2():
        print "foo2"

    def foo(self, key):
        self.dictionary[key]()  # This doesn't make sense, your class doesn't have an attribute called dictionnary

dictionary = {
    'key1' : class_name.foo1,
    'key2' : class_name.foo2
}

编辑:你不需要这种东西的字典。采用getattr

就像是:

method = gettatr(my_current_object, 'method_name')
method()
于 2013-09-25T10:59:22.627 回答