我试图了解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'>
我明白了。为什么会这样?
答案 0 :(得分:0)
为清楚起见,我以为问题是在问为什么NLTK中Tree
对象的输入是整数,但是在打印时,表示形式会打印出字符串而不会引起任何错误。
让我们深入研究一下代码。
以易于理解的括号分析格式输出Tree
的部分是https://github.com/nltk/nltk/blob/develop/nltk/tree.py#L820处的__str__()
函数
如果我们仔细观察,它将调用pformat()
函数:
def __str__(self):
return self.pformat()
位于https://github.com/nltk/nltk/blob/develop/nltk/tree.py#L835的pformat()
函数:
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]
如果我们查看在s
函数中如何创建字符串pformat
变量,我们会看到unicode_repr()
的多次使用。
这是在打印时将输入转换为pformat内的字符串的地方,但是Tree
对象中的子级和值仍然与输入的类型相同。
现在,如果我们查看unicode_repr
中的nltk.tree.py
,
from nltk.compat import python_2_unicode_compatible, unicode_repr
我们看到它来自https://github.com/nltk/nltk/blob/develop/nltk/compat.py#L298的nltk.compat
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
仅返回Unicode默认的repr
,特别是utf8
IIRC。
但是在Python 2中,它首先检查对象是否具有unicode_repr()
猴子补丁功能。
然后它检查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'>