Python функциональный объект как атрибут класса - PullRequest
0 голосов
/ 02 апреля 2020

Рассмотрим два альтернативных определения класса 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?

...