如果既不是按位运算也不是 print chevron,>> 是做什么的?

What does >> do if it is neither bitwise operation nor print chevron?

有没有人可以帮助弄清楚双大于号(即第 10 行中的 Drug >> float 和第 13 行中的 Drug >> int)在以下 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

代码复制自here并在python中运行 3.

这里的>>符号不是按位运算符。 Python's bitwise operation,比如说 x >> y,要求 y 是一个整数。很明显,这里的代码 (Drug >> float) 没有将 Drug 右移 float 位。

虽然之前问过类似的问题(见python2中的here and ), their answers mostly pointed to the so-called "print chevron",其中>>将待打印的消息重定向到紧接着指定的类文件对象>>。它们不适用于我的问题,因为这里不是打印语句的情况。

为了追踪上面代码中的>>,我将第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'

虽然有了回溯信息,我还是找不到答案。如果有人能帮助弄清楚 >> 在代码中的作用,我将不胜感激。

Drug >> float 调用 Drug__rshift__ 方法。该方法可以为所欲为;它不一定是二进制移位操作。

阅读 the owlready2 documentation 表明 domain >> range 是创建 ObjectProperty 的奇特方式。

has answered the question in brief. Below is just to save time for those who don't want to download and parse the source codes of owlready2 但仍想跟踪它在实际代码中的工作原理。

  1. Drug是在另一个对象ThingClass的基础上创建的对象,定义在/owlready2/entity.py.
  2. Drug >> float 呼叫 Drug.__rshift__(self, float) [explained].
  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),其实是不是做的二进制算术运算,但 returns/creates DataProperty 或 ObjectProperty,具体取决于 Range 的类型。