Skip to content
tsouvarev edited this page May 26, 2013 · 18 revisions

Далее используются примеры из онтологии

Оглавление

Использование пространств имен

Получение класса по URI

Получение подклассов для класса

Получение экземпляров класса

Получение объекта по URI

Воссоздание иерархии наследования классов

Получение свойств объекта, итерация по свойствам

В онтологии уже существует класс, необходимо получить экземпляры класса c определенным значением свойства

Создание нового класса

Создание нового объекта класса

Использование пространств имен

Чтобы каждый раз не прописывать длинный префикс к каждому свойству, можно использовать пространства имен:

from rdflib import Namespace

db = AllegroBackend(<route to triplestore>)
c = Connection(db)

factory = Factory(c)
# хештег в конце ссылки на пространство обязателен
local = Namespace("http://www.owl-ontologies.com/Ontology1359802755.owl#")

cl = factory.get_class(local.User)

print local.User
print cl.uri
http://www.owl-ontologies.com/Ontology1359802755.owl#User
http://www.owl-ontologies.com/Ontology1359802755.owl#User

Далее в примерах кода будет предполагаться, что factory и пространство имен local уже созданы

Получение класса по URI

Класс можно получить по полному URI или сокращенному.

cl1 = factory.get_class(local.User)
cl2 = factory.get_class("http://www.owl-ontologies.com/Ontology1359802755.owl#User")
print "short URI", cl1.uri
print "full URI", cl2.uri
print "are they equal?", cl1 == cl2
short URI http://www.owl-ontologies.com/Ontology1359802755.owl#User
full URI http://www.owl-ontologies.com/Ontology1359802755.owl#User
are they equal? True

Получение подклассов для класса

cls = factory.get_class(local.SectionElement)
print cls.get_subclasses()
[class TermDefinition, class Article, class Post, class Term]

Получение экземпляров класса

Все экземпляры класса будут типизированы классом из онтологии. То есть, если искать объекты класса http://www.owl-ontologies.com/Ontology1359802755.owl#User, то получим список объектов типа User с URI, соответствущими искомым объектам из онтологии

users = factory.get_class(local.User)
for x in users.get_objects():
    print "%s, %s" % (type(x), x)
class User, object Elena
class User, object Emma
class User, object Sarah

Получение объекта по URI

Объект можно получить по полному URI или сокращенному

obj = factory.get_object(local.Sarah)
obj2 = factory.get_object("http://www.owl-ontologies.com/Ontology1359802755.owl#Sarah")

print obj.uri 
print obj2.uri
print "are they equal?", obj == obj2
u'http://www.owl-ontologies.com/Ontology1359802755.owl#Sarah'
u'http://www.owl-ontologies.com/Ontology1359802755.owl#Sarah'
are they equal? True

Воссоздание иерархии наследования классов

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

cl = factory.get_class(local.Article)
print cl
pprint(cl.__mro__)

obj = factory.get_object(local.ArticleAboutAuthor)
print obj
pprint(obj.__class__.__mro__)
class Article
(class Article,
 class SectionElement,
 <class 'one.SemanticObjects.SemanticObjects.Thing'>,
 <type 'object'>)

object ArticleAboutAuthor
(class Article,
 class SectionElement,
 <class 'one.SemanticObjects.SemanticObjects.Thing'>,
 <type 'object'>)

Получение свойств объекта, итерация по свойствам

Все свойства для объекта или класса доступны в виде обычных атрибутов Python.

cl = factory.get_class(local.Article)
print cl
pprint(dir(cl))

obj = factory.get_object(local.ArticleAboutAuthor)
print obj
pprint(dir(obj))
class Article
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'factory',
 'filter',
 'get_objects',
 'get_subclasses',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#belongsToSection',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#hasImage',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#hasSectionElementContent',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#hasTxtContent',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#precedes',
 'uri']

object ArticleAboutAuthor
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'factory',
 'filter',
 'get_objects',
 'get_subclasses',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#belongsToSection',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#hasImage',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#hasSectionElementContent',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#hasTxtArticleContent',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#hasTxtContent',
 'http://www.owl-ontologies.com/Ontology1359802755.owl#precedes',
 'http://www.w3.org/2000/01/rdf-schema#label',
 'uri']

Легко можно заметить, что часть свойств определена в классе, а часть - в объекте.

cl = factory.get_class(local.Article)
obj = factory.get_object(local.ArticleAboutAuthor)
pprint(set(dir(obj))-set(dir(cl)))
set(['http://www.owl-ontologies.com/Ontology1359802755.owl#hasTxtArticleContent',
     'http://www.w3.org/2000/01/rdf-schema#label'])

Все свойства типизированы. Для классов свойства это соответствующие классы Python, для объектов - объекты этих классов.

obj = factory.get_object(local.ArticleAboutAuthor)
pprint([(x, type(getattr(obj, x)[0]), getattr(obj, x)) for x in obj.__dict__])
[('http://www.owl-ontologies.com/Ontology1359802755.owl#hasTxtArticleContent',
  <type 'unicode'>,
  [u'It is very short article about J. K. Rowling.']),
 ('http://www.owl-ontologies.com/Ontology1359802755.owl#hasSectionElementContent',
  <class 'rdflib.term.Literal'>,
  [rdflib.term.Literal(u'British novelist, best known as the author of the Harry Potter fantasy series. The Potter books have gained worldwide attention, won multiple awards, and sold more than 400 million copies. They have become the best-selling book series in history, and been the basis for a series of films which has become the highest-grossing film series in history. Rowling had overall approval on the scripts as well as maintaining creative control by serving as a producer on the final instalment.', lang=u'en')]),
 ('http://www.w3.org/2000/01/rdf-schema#label',
  <class 'rdflib.term.Literal'>,
  Label(en=rdflib.term.Literal(u'Article about Author', lang=u'en'))),
 ('uri',
  <type 'unicode'>,
  u'http://www.owl-ontologies.com/Ontology1359802755.owl#ArticleAboutAuthor'),
 ('http://www.owl-ontologies.com/Ontology1359802755.owl#belongsToSection',
  class Section,
  [object Author])]
obj = factory.get_class(local.Section)
pprint([(x, getattr(obj, x)) for x in obj.__dict__])
[('factory',
  <one.SemanticObjects.SemanticObjects.Factory object at 0x7ff30019ce50>),
 ('__module__', 'one.SemanticObjects.SemanticObjects'),
 ('http://www.owl-ontologies.com/Ontology1359802755.owl#hasTxtContent',
  class string),
 ('http://www.owl-ontologies.com/Ontology1359802755.owl#subSectionOf',
  class Section),
 ('uri',
  rdflib.term.URIRef(u'http://www.owl-ontologies.com/Ontology1359802755.owl#Section')),
 ('http://www.owl-ontologies.com/Ontology1359802755.owl#hasSectionElement',
  class SectionElement),
 ('__doc__', None)]

Языковые литералы отображаются в именованный кортеж, ключами которого являются языки.

obj = factory.get_object(local.Author)
pprint([(x, getattr(obj, x)) for x in obj.__dict__])
[('http://www.owl-ontologies.com/Ontology1359802755.owl#hasSectionElement',
  [object PostFilmRights, object ArticleAboutAuthor]),
 ('http://www.w3.org/2000/01/rdf-schema#label',
  Label(ru=rdflib.term.Literal(u'\u0410\u0432\u0442\u043e\u0440', lang=u'ru'), en=rdflib.term.Literal(u'Author', lang=u'en'))),
 ('uri', u'http://www.owl-ontologies.com/Ontology1359802755.owl#Author'),
 ('http://www.owl-ontologies.com/Ontology1359802755.owl#subSectionOf',
  [object HarryPotter])]

При этом сохраняется возможность итерации по ним, как по остальным свойствам.

bj = factory.get_object(local.Author)
pprint(obj.__dict__)
for key, values in obj.__dict__.items():
    for value in values:
        print "%s that %s" % (key, value)
http://www.owl-ontologies.com/Ontology1359802755.owl#hasSectionElement that object PostFilmRights
http://www.owl-ontologies.com/Ontology1359802755.owl#hasSectionElement that object ArticleAboutAuthor
http://www.w3.org/2000/01/rdf-schema#label that Автор
http://www.w3.org/2000/01/rdf-schema#label that Author

Работают стандартные способы проверки принадлежности атрибута классу или объекту.

obj = factory.get_object(local.Author)
print "hasattr?", hasattr(obj, RDFS.label)
print "getattr:", getattr(obj, RDFS.label).ru
print "getattr:", getattr(obj, RDFS.label)
hasattr? True
getattr: Автор
getattr: Label(ru=rdflib.term.Literal(u'\u0410\u0432\u0442\u043e\u0440', lang=u'ru'), en=rdflib.term.Literal(u'Author', lang=u'en'))

В онтологии уже существует класс, необходимо получить экземпляры класса c определенным значением свойства

Передача условий фильтрации идет через именованные аргументы. Для удобства можно передавать словарь без предварительной распаковки.

kwargs = {local.knows: local.Sarah, local.adds: local.ElenaWorkspace}
print factory.get_class(local.User).filter(**kwargs)
print factory.get_class(local.User).filter(kwargs)
[object Elena]
[object Elena]

Создание нового класса

Если factory передать uri, которого нет в онтологии - будет создан новый класс. Отдельного метода для сохранения нет! Сохранение идет в момент вызова get_class

cls = factory.get_class(local.SectionElement1)

В результате выполнения в онтологии появится запись вида:

http://www.owl-ontologies.com/Ontology1359802755.owl#SectionElement1 a rdfs:Class

Создание нового объекта класса

Для этого применяется схема, стандартная для Django: получается класс и через его инстанцирование создается объект.

cls = factory.get_class(local.SectionElement)
new_section = cls(local.NewSectionElement)

В результате выполнения в онтологии появится запись вида:

http://www.owl-ontologies.com/Ontology1359802755.owl#NewSectionElement a http://www.owl-ontologies.com/Ontology1359802755.owl#SectionElement