Return True iff self and other have equal values. :param visited_self: A set containing the ids of all ``self`` feature structures we've already visited. :param visited_other: A set containing the ids of all ``other`` feature structures we've already
(
self, other, check_reentrance, visited_self, visited_other, visited_pairs
)
| 276 | return self._hash |
| 277 | |
| 278 | def _equal( |
| 279 | self, other, check_reentrance, visited_self, visited_other, visited_pairs |
| 280 | ): |
| 281 | """ |
| 282 | Return True iff self and other have equal values. |
| 283 | |
| 284 | :param visited_self: A set containing the ids of all ``self`` |
| 285 | feature structures we've already visited. |
| 286 | :param visited_other: A set containing the ids of all ``other`` |
| 287 | feature structures we've already visited. |
| 288 | :param visited_pairs: A set containing ``(selfid, otherid)`` pairs |
| 289 | for all pairs of feature structures we've already visited. |
| 290 | """ |
| 291 | # If we're the same object, then we're equal. |
| 292 | if self is other: |
| 293 | return True |
| 294 | |
| 295 | # If we have different classes, we're definitely not equal. |
| 296 | if self.__class__ != other.__class__: |
| 297 | return False |
| 298 | |
| 299 | # If we define different features, we're definitely not equal. |
| 300 | # (Perform len test first because it's faster -- we should |
| 301 | # do profiling to see if this actually helps) |
| 302 | if len(self) != len(other): |
| 303 | return False |
| 304 | if set(self._keys()) != set(other._keys()): |
| 305 | return False |
| 306 | |
| 307 | # If we're checking reentrance, then any time we revisit a |
| 308 | # structure, make sure that it was paired with the same |
| 309 | # feature structure that it is now. Note: if check_reentrance, |
| 310 | # then visited_pairs will never contain two pairs whose first |
| 311 | # values are equal, or two pairs whose second values are equal. |
| 312 | if check_reentrance: |
| 313 | if id(self) in visited_self or id(other) in visited_other: |
| 314 | return (id(self), id(other)) in visited_pairs |
| 315 | |
| 316 | # If we're not checking reentrance, then we still need to deal |
| 317 | # with cycles. If we encounter the same (self, other) pair a |
| 318 | # second time, then we won't learn anything more by examining |
| 319 | # their children a second time, so just return true. |
| 320 | else: |
| 321 | if (id(self), id(other)) in visited_pairs: |
| 322 | return True |
| 323 | |
| 324 | # Keep track of which nodes we've visited. |
| 325 | visited_self.add(id(self)) |
| 326 | visited_other.add(id(other)) |
| 327 | visited_pairs.add((id(self), id(other))) |
| 328 | |
| 329 | # Now we have to check all values. If any of them don't match, |
| 330 | # then return false. |
| 331 | for fname, self_fval in self._items(): |
| 332 | other_fval = other[fname] |
| 333 | if isinstance(self_fval, FeatStruct): |
| 334 | if not self_fval._equal( |
| 335 | other_fval, |