Conditions | 31 |
Total Lines | 136 |
Code Lines | 75 |
Lines | 0 |
Ratio | 0 % |
Tests | 58 |
CRAP Score | 31 |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like abydos.distance._covington.Covington.alignments() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | # Copyright 2019-2020 by Christopher C. Little. |
||
191 | def alignments( |
||
192 | self, src: str, tar: str, top_n: Optional[int] = None |
||
193 | ) -> List[Alignment]: |
||
194 | """Return the Covington alignments of two strings. |
||
195 | |||
196 | Parameters |
||
197 | ---------- |
||
198 | src : str |
||
199 | Source string for comparison |
||
200 | tar : str |
||
201 | Target string for comparison |
||
202 | top_n : int |
||
203 | The number of alignments to return. If None, all alignments will |
||
204 | be returned. If 0, all alignments with the top score will be |
||
205 | returned. |
||
206 | |||
207 | Returns |
||
208 | ------- |
||
209 | list |
||
210 | Covington alignments |
||
211 | |||
212 | Examples |
||
213 | -------- |
||
214 | >>> cmp = Covington() |
||
215 | >>> cmp.alignments('hart', 'kordis', top_n=1)[0] |
||
216 | Alignment(src='hart--', tar='kordis', score=240) |
||
217 | 1 | >>> cmp.alignments('niy', 'genu', top_n=1)[0] |
|
218 | 1 | Alignment(src='--niy', tar='genu-', score=170) |
|
219 | 1 | ||
220 | 1 | ||
221 | .. versionadded:: 0.4.0 |
||
222 | |||
223 | """ |
||
224 | if not src: |
||
225 | if not tar: |
||
226 | return [Alignment('', '', 0)] |
||
227 | 1 | return [ |
|
228 | 1 | Alignment( |
|
229 | '-' * len(tar), |
||
230 | src, |
||
231 | self._weights[7] + self._weights[6] * (len(tar) - 1), |
||
232 | ) |
||
233 | ] |
||
234 | if not tar: |
||
235 | return [ |
||
236 | 1 | Alignment( |
|
237 | src, |
||
238 | 1 | '-' * len(src), |
|
239 | 1 | self._weights[7] + self._weights[6] * (len(src) - 1), |
|
240 | 1 | ) |
|
241 | 1 | ] |
|
242 | |||
243 | 1 | terminals = [] |
|
244 | 1 | ||
245 | 1 | def _cost(s: str, t: str) -> float: |
|
246 | 1 | if s[-1:] == '-': |
|
247 | if s[-2:] == '--': |
||
248 | 1 | return self._weights[6] |
|
249 | else: |
||
250 | 1 | return self._weights[7] |
|
251 | 1 | elif t[-1:] == '-': |
|
252 | if t[-2:] == '--': |
||
253 | 1 | return self._weights[6] |
|
254 | 1 | else: |
|
255 | 1 | return self._weights[7] |
|
256 | |||
257 | 1 | s = unicode_normalize('NFC', s)[-1:] |
|
258 | t = unicode_normalize('NFC', t)[-1:] |
||
259 | 1 | ||
260 | 1 | if s == t: |
|
261 | if s in self._consonants or s in self._glides: |
||
262 | 1 | return self._weights[0] |
|
263 | 1 | else: |
|
264 | return self._weights[1] |
||
265 | 1 | ||
266 | 1 | if ''.join(sorted([s, t])) in {'iy', 'uw'}: |
|
267 | return self._weights[2] |
||
268 | 1 | ||
269 | 1 | sd = unicode_normalize('NFKD', s) |
|
270 | 1 | td = unicode_normalize('NFKD', t) |
|
271 | 1 | ||
272 | if sd[0] == td[0] and s in self._vowels: |
||
273 | 1 | return self._weights[2] |
|
274 | |||
275 | 1 | if sd[0] in self._vowels and td[0] in self._vowels: |
|
276 | 1 | return self._weights[3] |
|
277 | if sd[0] in self._consonants and td[0] in self._consonants: |
||
278 | 1 | return self._weights[4] |
|
279 | 1 | ||
280 | return self._weights[5] |
||
281 | |||
282 | def _add_alignments( |
||
283 | cost: float, src: str, tar: str, src_align: str, tar_align: str |
||
284 | ) -> None: |
||
285 | cost += _cost(src_align, tar_align) |
||
286 | 1 | ||
287 | 1 | if src and tar: |
|
288 | _add_alignments( |
||
289 | cost, |
||
290 | 1 | src[1:], |
|
291 | 1 | tar[1:], |
|
292 | src_align + src[0], |
||
293 | tar_align + tar[0], |
||
294 | ) |
||
295 | 1 | if tar and tar_align[-1] != '-': |
|
296 | 1 | _add_alignments( |
|
297 | cost, src, tar[1:], src_align + '-', tar_align + tar[0] |
||
298 | 1 | ) |
|
299 | if src and src_align[-1] != '-': |
||
300 | 1 | _add_alignments( |
|
301 | 1 | cost, src[1:], tar, src_align + src[0], tar_align + '-' |
|
302 | 1 | ) |
|
303 | |||
304 | 1 | if not src and not tar: |
|
305 | 1 | terminals.append(Alignment(src_align, tar_align, cost)) |
|
306 | |||
307 | 1 | return |
|
308 | |||
309 | 1 | _add_alignments(0, src, tar[1:], '-', tar[0]) |
|
310 | 1 | _add_alignments(0, src[1:], tar, src[0], '-') |
|
311 | 1 | _add_alignments(0, src[1:], tar[1:], src[0], tar[0]) |
|
312 | 1 | ||
313 | terminals = sorted(terminals, key=lambda al: al.score) |
||
314 | |||
315 | 1 | if top_n == 0: |
|
316 | top_score = terminals[0].score |
||
317 | 1 | top_n = 1 |
|
318 | 1 | while ( |
|
319 | top_n < len(terminals) and terminals[top_n].score == top_score |
||
320 | 1 | ): |
|
321 | top_n += 1 |
||
322 | |||
323 | if top_n is None: |
||
324 | return terminals |
||
325 | else: |
||
326 | return terminals[:top_n] |
||
327 | |||
333 |