Spaces:
Sleeping
Sleeping
File size: 4,283 Bytes
d916065 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
.. Copyright (C) 2001-2023 NLTK Project
.. For license information, see LICENSE.TXT
==========================================
Unit tests for the nltk.utilities module
==========================================
overridden()
~~~~~~~~~~~~
>>> from nltk.internals import overridden
The typical use case is in defining methods for an interface or
abstract base class, in such a way that subclasses don't have to
implement all of the methods:
>>> class EaterI(object):
... '''Subclass must define eat() or batch_eat().'''
... def eat(self, food):
... if overridden(self.batch_eat):
... return self.batch_eat([food])[0]
... else:
... raise NotImplementedError()
... def batch_eat(self, foods):
... return [self.eat(food) for food in foods]
As long as a subclass implements one method, it will be used to
perform the other method:
>>> class GoodEater1(EaterI):
... def eat(self, food):
... return 'yum'
>>> GoodEater1().eat('steak')
'yum'
>>> GoodEater1().batch_eat(['steak', 'peas'])
['yum', 'yum']
>>> class GoodEater2(EaterI):
... def batch_eat(self, foods):
... return ['yum' for food in foods]
>>> GoodEater2().eat('steak')
'yum'
>>> GoodEater2().batch_eat(['steak', 'peas'])
['yum', 'yum']
But if a subclass doesn't implement either one, then they'll get an
error when they try to call them. (nb this is better than infinite
recursion):
>>> class BadEater1(EaterI):
... pass
>>> BadEater1().eat('steak')
Traceback (most recent call last):
. . .
NotImplementedError
>>> BadEater1().batch_eat(['steak', 'peas'])
Traceback (most recent call last):
. . .
NotImplementedError
Trying to use the abstract base class itself will also result in an
error:
>>> class EaterI(EaterI):
... pass
>>> EaterI().eat('steak')
Traceback (most recent call last):
. . .
NotImplementedError
>>> EaterI().batch_eat(['steak', 'peas'])
Traceback (most recent call last):
. . .
NotImplementedError
It's ok to use intermediate abstract classes:
>>> class AbstractEater(EaterI):
... pass
>>> class GoodEater3(AbstractEater):
... def eat(self, food):
... return 'yum'
...
>>> GoodEater3().eat('steak')
'yum'
>>> GoodEater3().batch_eat(['steak', 'peas'])
['yum', 'yum']
>>> class GoodEater4(AbstractEater):
... def batch_eat(self, foods):
... return ['yum' for food in foods]
>>> GoodEater4().eat('steak')
'yum'
>>> GoodEater4().batch_eat(['steak', 'peas'])
['yum', 'yum']
>>> class BadEater2(AbstractEater):
... pass
>>> BadEater2().eat('steak')
Traceback (most recent call last):
. . .
NotImplementedError
>>> BadEater2().batch_eat(['steak', 'peas'])
Traceback (most recent call last):
. . .
NotImplementedError
Here's some extra tests:
>>> class A(object):
... def f(x): pass
>>> class B(A):
... def f(x): pass
>>> class C(A): pass
>>> class D(B): pass
>>> overridden(A().f)
False
>>> overridden(B().f)
True
>>> overridden(C().f)
False
>>> overridden(D().f)
True
It works for classic classes, too:
>>> class A:
... def f(x): pass
>>> class B(A):
... def f(x): pass
>>> class C(A): pass
>>> class D(B): pass
>>> overridden(A().f)
False
>>> overridden(B().f)
True
>>> overridden(C().f)
False
>>> overridden(D().f)
True
read_str()
~~~~~~~~~~~~
>>> from nltk.internals import read_str
Test valid scenarios
>>> read_str("'valid string'", 0)
('valid string', 14)
Now test invalid scenarios
>>> read_str("should error", 0)
Traceback (most recent call last):
...
nltk.internals.ReadError: Expected open quote at 0
>>> read_str("'should error", 0)
Traceback (most recent call last):
...
nltk.internals.ReadError: Expected close quote at 1
|