Как выполнить логическую алгебру для пропущенных значений?

Я хочу воспроизвести логические значения NA, как они ведут себя в R:

NA является допустимым логическим объектом. Если компонент x или y является NA, результатом будет NA, если результат неоднозначен. Другими словами, NA & TRUE оценивается как NA, а NA & FALSE оценивается как FALSE. http://stat.ethz.ch/R-manual/R-devel/library/base/html/Logic.html

Я видел, что None рекомендуется для отсутствующих значений, но Python преобразует None в False при вычислении логических выражений и вычисляет None or False в False. Результат, конечно, должен был быть None, так как нельзя делать никаких выводов, учитывая отсутствующее значение.

Как мне добиться этого в Python?

EDIT Принятый ответ правильно вычисляется с помощью побитовых логических операторов, но для достижения такого же поведения с логическими операторами not, or и and, похоже, требуется изменение языка программирования Python.


person user2646234    schedule 02.08.2013    source источник


Ответы (3)


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

class NA_(object):
    instance = None # Singleton (so `val is NA` will work)
    def __new__(self):
        if NA_.instance is None:
            NA_.instance = super(NA_, self).__new__(self)
        return NA_.instance
    def __str__(self): return "NA"
    def __repr__(self): return "NA_()"
    def __and__(self, other):
        if self is other or other:
            return self
        else:
            return other
    __rand__ = __and__
    def __or__(self, other):
        if self is other or other:
            return other
        else:
            return self
    __ror__ = __or__
    def __xor__(self, other):
        return self
    __rxor__ = __xor__
    def __eq__(self, other):
        return self is other
    __req__ = __eq__
    def __nonzero__(self):
        raise TypeError("bool(NA) is undefined.")
NA = NA_()

Использовать:

>>> print NA & NA
NA
>>> print NA & True
NA
>>> print NA & False
False
>>> print NA | True
True
>>> print NA | False
NA
>>> print NA | NA
NA
>>> print NA ^ True
NA
>>> print NA ^ NA
NA
>>> if NA: print 3
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 28, in __nonzero__
TypeError: bool(NA) is undefined.
>>> if NA & False: print 3
...
>>>
>>> if NA | True: print 3
...
3
>>>
person Chris Barker    schedule 02.08.2013
comment
Мне нравится ваш ответ, но вы все еще не можете оценить NA or True до True? В ваших примерах используются побитовые операторы. - person user2646234; 05.08.2013
comment
Насколько я знаю, невозможно переопределить или и и. NA or True интерпретируется как (NA.__nonzero__() == True) | (True.__nonzero__() == True). Пожалуйста, поправьте меня, если я ошибаюсь; Я хотел бы ошибаться в этом. docs.python.org/2/reference/ - person Chris Barker; 05.08.2013

Вы можете сделать это, создав класс и переопределив методы логических операций.

>>> class NA_type(object):
        def __and__(self,other):
                if other == True:
                        return self
                else:
                        return False
        def __str__(self):
                return 'NA'


>>> 
>>> NA = NA_type()
>>> print NA & True
NA
>>> print NA & False
False
person Brien    schedule 02.08.2013
comment
NA & NA дает False. Вероятно, не желаемое поведение. Кроме того, было бы неплохо что-то сделать с тем фактом, что if NA: do_whatever() выполняет do_whatever() даже без предупреждения. - person user2357112 supports Monica; 02.08.2013
comment
@Chris Barker Да, ваш ответ гораздо полнее. Я просто дал отправную точку. - person Brien; 02.08.2013

Вы можете определить собственный класс (одиночный?) и определить пользовательскую функцию __and__ (и любую другую, которая вам нужна). Видеть это:

http://docs.python.org/2/reference/datamodel.html#emulatory-numeric-types

person freakish    schedule 02.08.2013