Что делает >> если это не побитовая операция и не печать шеврона? - PullRequest
0 голосов
/ 05 июля 2018

Есть ли кто-нибудь, кто мог бы помочь выяснить, что символ двойного больше чем (то есть Drug >> float в строке 10 и Drug >> int в строке 13) означает в следующих сценариях Python?

 1  from owlready2 import *
 2
 3  onto = get_ontology("http://test.org/onto.owl")
 4
 5  with onto:
 6      class Drug(Thing):
 7          def get_per_tablet_cost(self):
 8              return self.cost / self.number_of_tablets
 9
10      class has_for_cost(Drug >> float, FunctionalProperty):
11          python_name = "cost"
12
13      class has_for_number_of_tablets(Drug >> int, FunctionalProperty):
14          python_name = "number_of_tablets"
15
16  my_drug = Drug(cost = 10.0, number_of_tablets = 5)
17  print(my_drug.get_per_tablet_cost())

--- Below is the printing outcome. ---
2.0

Код скопирован с здесь и работает на python 3.

Символ >> здесь не является побитовым оператором. Битовая операция Python , скажем x >> y, требует, чтобы y было целым числом. Понятно, что код здесь (Drug >> float) не сдвигается Drug вправо на float бит.

Хотя аналогичные вопросы задавались ранее (см. здесь и здесь ), их ответы в основном указывали на так называемый «шеврон печати» в Python 2 где >> перенаправляет сообщения, предназначенные для печати, в файлоподобный объект, указанный сразу после >>. Они не относятся к моему вопросу, потому что здесь нет случая печати заявления.

Чтобы отследить >> в приведенном выше коде, я изменил скрипт в строке 10 как class has_for_cost(Drug >> list, FunctionalProperty) (а именно заменил >> float на >> list) и снова запустил код. Возникла ошибка AttributeError следующим образом:

AttributeError                            Traceback (most recent call last)
<ipython-input-1-1be374b27b04> in <module>()
      8             return self.cost / self.number_of_tablets
      9 
---> 10     class has_for_cost(Drug >> list, FunctionalProperty):
     11         python_name = "cost"
     12 

~/anaconda3/lib/python3.6/site-packages/owlready2/prop.py in __init__(Prop, name, bases, obj_dict)
    254 class ReasoningPropertyClass(PropertyClass):
    255   def __init__(Prop, name, bases, obj_dict):
--> 256     super().__init__(name, bases, obj_dict)
    257 
    258     if (not Prop.namespace.world is owl_world):

~/anaconda3/lib/python3.6/site-packages/owlready2/prop.py in __init__(Prop, name, bases, obj_dict)
     78 
     79       if not range is False:
---> 80         Prop.range.extend(range)
     81 
     82       if not inverse_property is False:

~/anaconda3/lib/python3.6/site-packages/owlready2/util.py in extend(self, l)
     58   def append(self, x):          old = list(self); super().append(x)         ; self._callback(self._obj, old)
     59   def insert(self, i, x):       old = list(self); super().insert(i, x)      ; self._callback(self._obj, old)
---> 60   def extend(self, l):          old = list(self); super().extend(l)         ; self._callback(self._obj, old)
     61   def remove(self, x):          old = list(self); super().remove(x)         ; self._callback(self._obj, old)
     62   def __delitem__(self, i):     old = list(self); super().__delitem__(i)    ; self._callback(self._obj, old)

~/anaconda3/lib/python3.6/site-packages/owlready2/prop.py in _range_changed(Prop, old)
    143     for x in new - old:
    144       if isinstance(x, ClassConstruct): x._set_ontology(Prop.namespace.ontology)
--> 145       x2 = _universal_datatype_2_abbrev.get(x) or x.storid
    146       Prop.namespace.ontology.add_triple(Prop.storid, rdf_range, x2)
    147 

AttributeError: type object 'list' has no attribute 'storid'

Хотя с информацией о трассировке я все еще не смог найти ответ. Я был бы очень благодарен, если бы кто-нибудь мог помочь выяснить, что >> делает в коде.

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Аран-Фей ответил на вопрос вкратце. Ниже просто сэкономить время для тех, кто не хочет загружать и анализировать исходные коды owlready2 , но все же хочет отследить, как это работает в реальных кодах.

  1. Drug - это объект, созданный на основе другого объекта ThingClass, как определено в /owlready2/entity.py.
  2. Drug >> float звонки Drug.__rshift__(self, float) [ объяснил ].
  3. Не Drug, а его базовый объект ThingClass имеет метод __rshift__, который читает в entity.py:

    class ThingClass(EntityClass):
        ...
        def __rshift__(Domain, Range):
            import owlready2.prop
            owlready2.prop._next_domain_range = (Domain, Range)
            if isinstance(Range, ThingClass) or isinstance(Range, ClassConstruct):
                return owlready2.prop.ObjectProperty
            else:
                return owlready2.prop.DataProperty
    
  4. Drug >> float эквивалентно __rshift__(Domain=Drug, Range=float), который на самом деле не выполняет двоичную арифметическую операцию, но возвращает / создает либо DataProperty, либо ObjectProperty, в зависимости от по типу Range.

0 голосов
/ 05 июля 2018

Drug >> float вызовы Drug s __rshift__ метод. Этот метод может делать все, что захочет; это не должна быть операция двоичного сдвига.

Чтение Документация owlready2 показывает, что domain >> range - это причудливый способ создания ObjectProperty.

...