Цикл while для атрибута класса Python - PullRequest
2 голосов
/ 08 марта 2012

«Пока» не «ломается», когда self.text устанавливается в '' функцией kill.

Может кто-нибудь помочь мне сделать эту работу или предложить лучший способ? Необходимо запустить строку через 10+ функций, выход из которых, если строка становится '' Возвращение внутрь каждой функции кажется излишним.

class Class(object):
    def run(self, text):
        self.text = text

        while self.text:
            self.nothing1()
            self.kill()
            self.nothing2()
            return self.text # stop if all functions run

    def nothing1(self):
        print 'nothing1'
        self.text = self.text

    def kill(self):
        print 'kill'
        self.text = ''

    def nothing2(self):
        print 'nothing2'
        self.text = self.text

C = Class()
C.run('some string')

Пояснение: Цель состоит в том, чтобы пропустить строку через множество функций, чтобы один раз остановить работу, если какая-либо из функций устанавливает строку в «», я, очевидно, неправильно понимаю, как работает «время», мне кажется, это самый чистый способ.

Ответы [ 4 ]

4 голосов
/ 08 марта 2012

Обновление 2: если ваша цель состоит в том, чтобы пропустить строку через несколько функций, то ваш дизайн по существу полностью неверен.

Каждая функция НЕ должна устанавливать член, но вместо этого принимает строку и возвращает строку,Затем ваш цикл должен проверить, является ли значение хорошим:

currstr = 'foo'
for f in (self.nothing1, self.kill, self.nothing2):
    tmpstr = f(currstr)
    if not tmpstr: break # or return, or raise exception
    currstr = tmpstr

Обновление: очевидно, ваша проблема в том, что вам не нравится, как работают циклы while.В то время как циклы прерываются только тогда, когда выполнение попадает в тест, то есть, когда выполнение входит в тело, без прерывания или исключения, оно продолжается до конца блока и только после этого тест будет переоценен.

Вероятно, самый чистый способ сделать это - обернуть self.text свойством .

Затем у вас есть три разумных варианта логики в вашей функции свойства:

  1. Вы можете создать систему обработчиков, которые вызываются при изменении свойства, и делать все, что вам нравится.там (включая логику одной из следующих двух опций);
  2. Включите определенный тест для пустой строки, создайте исключение для этого и обработайте его вне цикла;или
  3. Вызывать исключение при каждом отдельном изменении и обрабатывать его внутри цикла.

У вас также есть другой вариант, который заключается в том, чтобы вызвать исключение в kill во многих случаях.так же, как описано выше.


Ваш код отлично работает для меня:

In [139]: cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:class Class(object):
:    def run(self, text):
:        self.text = text
:
:        while self.text:
:            self.nothing1()
:            self.kill()
:            self.nothing2()
:
:    def nothing1(self):
:        print 'nothing1'
:        self.text = self.text
:
:    def kill(self):
:        print 'kill'
:        self.text = ''
:
:    def nothing2(self):
:        print 'nothing2'
:        self.text = self.text
:
:C = Class()
:C.run('some string')
:--
nothing1
kill
nothing2
2 голосов
/ 08 марта 2012

Вам нужно добавить проверку text, являющуюся '', после выполнения каждой функции:

class Class(object):
    def run(self, text):
        self.text = text

        func_to_exec = [self.nothing1,self.kill,self.nothing2]
        while True:
            for func in func_to_exec:
                func()
                if not self.text:
                    break
            else:
                continue #executed only if no 'break' was met (starts the next iteration of `while` loop)
            break #get out of the 'while True' loop


    def nothing1(self):
        print 'nothing1'
        self.text = self.text

    def kill(self):
        print 'kill'
        self.text = ''

    def nothing2(self):
        print 'nothing2'
        self.text = self.text

Выход:

>>> C.run('some string')
nothing1
kill
1 голос
/ 08 марта 2012

Хотя это может показаться избыточным, вы можете сократить цикл, если вы вернете строку в каждой функции. Это более функциональный подход к проблеме, использующий ленивую оценку:

def run(self, text):
        self.text = text

        func_to_exec = [self.nothing1, self.kill, self.nothing2]
        all(func() for func in func_to_exec) # generator will evaluate func lazily

Хорошо и понятно с комментарием.

0 голосов
/ 08 марта 2012

Напишите декоратор, который вызывает StopIteration, если атрибут становится ''.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...