【问题标题】:python Dictionary function call in class类中的python字典函数调用
【发布时间】:2018-09-30 16:13:25
【问题描述】:

我尝试在 Python 中实现自己的堆栈。当我选择任何“pos”时,都会出现错误

class Stack:
    '''This is Stack Class'''

    def __init__(self):
        self.stack=[]

    def push(self):
        '''Enter item to push into stack'''
        self.stack.append(raw_input("Enter item to stack: "))

    def pop(self):
        '''Pops item from stack'''
        if len(self.stack)==0:
            print 'Cannot pop from empty stack'
        else:        
            i = self.stack.pop(index=-1)
            print ('Item popped: [%s]'%i)

    def show(self):
        '''Display Stack Content'''
        print self.stack

    choiceDict={'p':push, 'o':pop, 's':show, 'q':quit}

def menu():
    '''This is a menu list for stack'''
    s=Stack()

    while True:
        while True:
            print '''Enter Choice
p) push
o) pop
s) show
q) quit'''
            c=raw_input('Enter choice > ').lstrip()[0].lower()
            if c not in 'posq':
                print '**Invalid Choice'
            else:
                break

        if(c=='q'):
            break
        s.choiceDict[c]()

if __name__=='__main__':
    menu()

错误:

s.choiceDict[c]() TypeError: push() takes exactly 1 argument (0 given)

ps:如果代码中还有其他错误。我很高兴认识他们:)

顺便说一句,我只是想要解决这个问题的方法

【问题讨论】:

    标签: python class oop dictionary python-2.x


    【解决方案1】:

    Stack.choiceDict[c]中的函数不绑定任何实例,无论你是否通过实例s访问类属性choiceDict。调用函数时你仍然需要提供一个实例:

    s.choiceDict[c](s)
    

    或者说得更清楚:

    Stack.choiceDict[c](s)
    

    【讨论】:

      【解决方案2】:

      push 属于您班级的每个实例。因此,您需要您的调度字典通过self 调用属于该实例的方法。

      我建议你把它放在__init__ 中,以便在你初始化一个新的类实例时定义调度器:

      def __init__(self):
          self.stack = []
          self.choiceDict = {'p': self.push, 'o': self.pop, 's': self.show, 'q': self.quit}
      

      【讨论】:

      • 感觉没有必要为每个实例提供自己的dict
      • @schwobaseggl,我想我倾向于制作这些实例属性,以防它们需要被特定实例覆盖。我猜你是对的,如果这些是一成不变的并且不应该被覆盖。
      【解决方案3】:

      你需要将你的choiceDict移动到菜单功能并初始化如下:

      choice_dict = {'p': s.push, 'o': s.pop, 's': s.show, 'q': s.quit}
      

      然后像这样使用它:

      choice_dict[c]()
      

      这是因为你的choiceDicts 一无所知,但你所有的方法都需要self 参数:

      In [14]: class Foo:
          ...:     def foo(self):
          ...:         print('foo is called')
          ...:     methods = {'foo': foo}
          ...:
      
      In [15]: f = Foo()
      
      In [16]: f.foo()
      foo is called
      
      In [17]: f.foo
      Out[17]: <bound method Foo.foo of <__main__.Foo object at 0x111ec2048>>
      
      In [18]: f.methods['foo']
      Out[18]: <function __main__.Foo.foo>
      

      在这里您可以看到f.methods['foo']f.foo 之间的区别。第一个绑定到f,第二个只是类中的一个函数

      In [19]: f.methods['foo']()
      ---------------------------------------------------------------------------
      TypeError                                 Traceback (most recent call last)
      <ipython-input-19-a6f2f6e3b450> in <module>()
      ----> 1 f.methods['foo']()
      
      TypeError: foo() missing 1 required positional argument: 'self'
      

      使用methods dict 调用foo 会引发同样的错误,因为缺少self 参数。

      In [20]: f.methods['foo'](f)
      foo is called
      

      或者,您可以将f 传递给函数 - 这也可以,但似乎不太正确,因为您已经在表达式中使用了f。虽然这实际上与我上面建议的将choice_dict 移动到menu 函数相同。

      【讨论】:

        猜你喜欢
        • 2018-06-14
        • 1970-01-01
        • 2017-09-04
        • 1970-01-01
        • 1970-01-01
        • 2020-03-12
        • 1970-01-01
        • 1970-01-01
        • 2019-09-24
        相关资源
        最近更新 更多