Python Словарь функции вызова в классе - PullRequest
0 голосов
/ 30 сентября 2018

Я попытался реализовать свой собственный стек в 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: если в коде есть другие ошибки.Я буду рад узнать их:)

И, кстати, я просто хочу, чтобы решить эту проблему

Ответы [ 3 ]

0 голосов
/ 30 сентября 2018

Вам необходимо переместить choiceDict в функцию меню и инициализировать следующим образом:

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

Затем используйте его следующим образом:

choice_dict[c]()

Это потому, что ваш choiceDictничего не знает о s, но все ваши методы требуют self param:

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'

Вызов foo с использованием methods dict вызывает ту же ошибку, поскольку пропущен параметр self.

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

В качестве альтернативы, вы можете передать f функции - это также будет работать, но, кажется, не совсем правильно, потому что вы уже используете f в выражении.Хотя по сути это то же самое, что перейти choice_dict к функции menu, как я предлагал выше.

0 голосов
/ 30 сентября 2018

push принадлежит каждому экземпляру вашего класса.Поэтому вам нужен ваш диспетчерский словарь для вызова метода, принадлежащего этому экземпляру, через self.

Я рекомендую вам указать это в __init__, чтобы диспетчер был определен при инициализации нового экземпляра класса:

def __init__(self):
    self.stack = []
    self.choiceDict = {'p': self.push, 'o': self.pop, 's': self.show, 'q': self.quit}
0 голосов
/ 30 сентября 2018

Функции в Stack.choiceDict[c] не привязаны ни к какому экземпляру, независимо от того, обращаетесь ли вы к атрибуту класса choiceDict через экземпляр s.Вам все равно придется предоставить экземпляр при вызове функции:

s.choiceDict[c](s)

Или более показательно:

Stack.choiceDict[c](s)
...