как объект nltk.tree.Tree генерирует строковое представление дерева? - PullRequest
1 голос
/ 08 мая 2019

Я пытаюсь понять модуль nltk.tree. Я запутался, почему при печати объекта nltk.tree.Tree адрес не распечатывается. Вместо этого он выводит строковое представление дерева.

Я посмотрел исходный код в nltk.tree, но я определил, какая часть кода форматирует дерево в строку.

import nltk
from nltk.tree import Tree
print(Tree(1, [2, Tree(3, [4]), 5]))
print(type(Tree(1, [2, Tree(3, [4]), 5])))

выход

(1 2 (3 4) 5)
<class 'nltk.tree.Tree'>

Если определить пример класса

class example():
    def __init__(self):
        ''
this_class = example()
print(this_class)
print(type(this_one))

Выход:

<__main__.example object at 0x000001397F255668>
<class '__main__.example'>

Я понял это. Почему это?

1 Ответ

0 голосов
/ 10 мая 2019

Чтобы было ясно, я предположил, что вопрос заключается в том, почему входные данные для объекта Tree в NLTK являются целыми числами, но при печати представление выводит строку без каких-либо ошибок.

Давайте немного углубимся в код.

Часть, которая печатает Tree в читаемом человеком формате анализа в скобках, - это функция __str__() при https://github.com/nltk/nltk/blob/develop/nltk/tree.py#L820

Если мы посмотрим поближе, то вызовет функцию pformat():

    def __str__(self):
        return self.pformat()

Функция pformat() при https://github.com/nltk/nltk/blob/develop/nltk/tree.py#L835:

def pformat(self, margin=70, indent=0, nodesep='', parens='()', quotes=False):
    """
    :return: A pretty-printed string representation of this tree.
    :rtype: str
    :param margin: The right margin at which to do line-wrapping.
    :type margin: int
    :param indent: The indentation level at which printing
        begins.  This number is used to decide how far to indent
        subsequent lines.
    :type indent: int
    :param nodesep: A string that is used to separate the node
        from the children.  E.g., the default value ``':'`` gives
        trees like ``(S: (NP: I) (VP: (V: saw) (NP: it)))``.
    """

    # Try writing it on one line.
    s = self._pformat_flat(nodesep, parens, quotes)
    if len(s) + indent < margin:
        return s

    # If it doesn't fit on one line, then write it on multi-lines.
    if isinstance(self._label, string_types):
        s = '%s%s%s' % (parens[0], self._label, nodesep)
    else:
        s = '%s%s%s' % (parens[0], unicode_repr(self._label), nodesep)
    for child in self:
        if isinstance(child, Tree):
            s += (
                '\n'
                + ' ' * (indent + 2)
                + child.pformat(margin, indent + 2, nodesep, parens, quotes)
            )
        elif isinstance(child, tuple):
            s += '\n' + ' ' * (indent + 2) + "/".join(child)
        elif isinstance(child, string_types) and not quotes:
            s += '\n' + ' ' * (indent + 2) + '%s' % child
        else:
            s += '\n' + ' ' * (indent + 2) + unicode_repr(child)
    return s + parens[1]

Если мы посмотрим, как создается переменная string s в функции pformat, мы увидим многократное использование unicode_repr().

Вот где входные данные преобразуются в строку внутри pformat при печати, но дочерний элемент и значения в объекте Tree по-прежнему остаются того же типа, что и при вводе.

Теперь, если мы посмотрим на unicode_repr в nltk.tree.py,

from nltk.compat import python_2_unicode_compatible, unicode_repr

Мы видим, что оно исходит от nltk.compat с https://github.com/nltk/nltk/blob/develop/nltk/compat.py#L298

def unicode_repr(obj):
    """
    For classes that was fixed with @python_2_unicode_compatible
    ``unicode_repr`` returns ``obj.unicode_repr()``; for unicode strings
    the result is returned without "u" letter (to make output the
    same under Python 2.x and Python 3.x); for other variables
    it is the same as ``repr``.
    """
    if PY3:
        return repr(obj)

    # Python 2.x
    if hasattr(obj, 'unicode_repr'):
        return obj.unicode_repr()

    if isinstance(obj, text_type):
        return repr(obj)[1:]  # strip "u" letter from output

    return repr(obj)

В Python 3 nltk.compat.unicode_repr просто возвращает repr, который по умолчанию в Юникоде, в частности utf8 IIRC.

Но в Python 2 он сначала проверяет, есть ли у объекта функция unicode_repr() monkey-patch.

Затем он проверяет, что это тип text_type из библиотеки six, если это так, он распечатает вывод без префикса u, например. u"..."

Наконец, это Python 2, и объект не имеет unicode_repr() и не six.text_type, он просто распечатает repr(obj).

Итак, возвращаясь к вопросу, в случае, когда объект является целым числом, repr(int) будет преобразован в строку.

>>> type(1)
<class 'int'>
>>> repr(1)
'1'
>>> type(repr(1))
<class 'str'>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...