Рассмотрим два альтернативных определения класса Replace
import re
from dataclasses import dataclass
from typing import Callable, Match
@dataclass
class Replace1(object):
"""Dataclass that stores info about replacement protocol."""
replstr: str = ''
predicate: Callable[[str], bool] = lambda string: True
def __call__(self, match: Match[str]) -> str:
"""Callable that returns the replacement given a match."""
matched: str = match.group(0)
return match.expand(self.replstr) if self.predicate(matched) else matched # This is a complaint in self.predicate(matched)
@dataclass
class Replace2(object):
"""Dataclass that stores info about replacement protocol."""
replstr: str = ''
predicate: Callable[['Replace2', str], bool] = lambda repl, string: True
def __call__(self, match: Match[str]) -> str:
"""Callable that returns the replacement given a match."""
matched: str = match.group(0)
return match.expand(self.replstr) if self.predicate(matched) else matched
Кажется, что Replace1 и Replace2 работают одинаково
r1 = Replace1(predicate=lambda x: len(x.split()) > 5)
r2 = Replace2(predicate=lambda x: len(x.split()) > 5) # This is a complaint in lambda
pattern = re.compile(r'(?:\w+\s*)+')
match1 = re.match(pattern, 'This will prevail')
match2 = re.match(pattern, 'This is too long and will be destroyed')
assert r1(match1) == 'This will prevail'
assert r2(match1) == 'This will prevail'
assert r1(match2) == ''
assert r2(match2) == ''
Однако mypy, похоже, жалуется на self.predicate(matched)
, имеющую слишком много аргументов в Replace1. А также, кажется, жалуется на Replace2(predicate=lambda x: len(x.split()) > 5)
нехватку аргументов.
Что именно происходит? и в чем разница между Replace1 и Replace2?