Метод цепочки оценки истины с методом обращения - PullRequest
0 голосов
/ 14 февраля 2019

Я хотел бы получить объект, похожий на запрос в python, который в фоновом режиме собирает валидность с помощью метода цепочки методов следующим образом:

c = Test(a=True, b=False)
c.a.is_not(b).validity()

или я могу сделать это

c.is_not(a).b.validity()

или это

c.is_not(a).is_not(b).validity()

или подобное

c.is_not(a).is_not(b).validity()

Проблема, с которой я сталкиваюсь, заключается в добавлении метода запроса, похожего на обращение, который может принимать метод свойства и возвращать истинность обращения.Это моя попытка.Однако я понял, что это не очень хороший подход, так как в случае вызова is_not():

class Test:
    def __init__(self, a, b):
        self._a = a
        self._b = b
        self._validity = True

    @property 
    def a(self):
        self._validity = self._validity == self._a
        return self

    @property 
    def b(self):
        self._validity = self._validity == self._b
        return self

    def is_not(self, truth):
        truth = not(truth)
        self._validity = self._validity == truth
        return self

    def validity(self):
        return self._validity
валидность будет изменена дважды.

1 Ответ

0 голосов
/ 14 февраля 2019

Я бы не стал менять состояние Test, создав новый объект для возврата.Вот краткая версия, но она не обязательно хорошо масштабируется:

    @classmethod
    def is_not(cls, truth):
        test = cls(not self.a, not self.b)
        test._validity = not(truth)
        return test

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

Это напоминает образец монады.Одним из возможных способов реализации этого было бы использование монады State из oslash:

import oslash 

class TestMonadic:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def is_not(self, truth: bool) -> oslash.State:
        return lambda validity: oslash.State(lambda _: (truth != validity, self))

    def validity(self, state: oslash.State):
        return state.run(self)[0]

Синтаксис становится немного громоздким в python, потому что он не предназначен для этого.Возможно, имеет смысл размещать is_not и validity вне класса, но из-за их довольно общих имен полезно связать их с классом.(В Haskell имя функции не так важно, потому что сигнатура типа функции будет вызывать диспетчеризацию).

Вот как ваши вычисления будут выглядеть в этой структуре:

>>> t = TestMonadic(a=True, b=False)
>>> t.validity(State.get() | t.is_not(t.b))
True
>>> t.validity(State.get() | t.is_not(t.a) | t.is_not(t.b))
True
>>> t.validity(State.get() | t.is_not(t.b))
False 

oslashотсутствует evalState, что validity() частично делает.

...