Опитвам се да обмисля добро решение за това и нищо не ми идва наум. Като упражнение се опитвам да създам контекстен мениджър, който ще обработва валидирането на данни, нещо като:
validation = lambda x: len(x) <= 10
with validator(validation):
some_data = input("Please enter a name of 10 characters or less: ")
print(some_data)
# OUTPUT
>> Please enter a name of 10 characters or less: FooBarSpamEggs
>> Please enter a name of 10 characters of less: Adam
Adam
Първоначално мислех да направя това с unittest.mock.patch
, но разбрах, че не мога да извикам оригиналната функция, докато е коригирана, напр.:
def patched(validation, *args):
while True:
p = __builtins__.input(args) # Doesn't work
if validation(p):
break
return p
with unittest.mock.patch('builtins.input', patched):
input("Some prompt here: ")
# fails on recursion error as patched calls itself
Тогава обмислих да напиша декоратор за валидиране на един ред, но това наистина е полезно само ако можете да направите нещо като:
@validate(lambda x: int(x) == 6)
p = input("How many sides does a d6 have? ")
# can't decorate a function call
Обаче съм пристрастен към тази идея за управление на контекста. За съжаление не знам дали контекстният мениджър има достъп до съдържанието си или е ограничен само до аргументите си. някакви мисли?
Като настрана, знам, че мога да направя тази функционалност във функция, например:
def validate_input(prompt, validation, msg_if_fail=None):
while True:
p = input(prompt)
if validation(p):
break
if msg_if_fail is not None:
print(msg_if_fail)
return p
Но не е толкова красиво. Това, както казах, е повече упражнение, отколкото практически проблем.