def add_time(self, h: int = 0, m: int = 0, d: int = 0, dw: int = 0, mh: int = 0, y: int = 0):
if any(v < 0 for v in [h,m,d,dw,mh,y]):
raise ValueError()
args = {'h':h, 'm':m, 'd':d, 'dw':dw, 'mh':mh, 'y':y}
bad = list(filter(lambda k: args[k] < 0, args.keys()))
if bad:
raise ValueError('Invalid values for: ' + ','.join(bad))
import functools
import inspect
# пусть чек-функция имеет вид (value) -> bool, и возвращает True для "хороших" значений. Пример:
def not_whitespace(s: str) -> bool:
'String must not contain only whitespace' # док строка будет использоваться в сообщении об ошибке
return bool(s.strip()) # проверяем что строка не состоит из одних пробелов.
# чек-функции можно генерировать и на ходу:
def in_range(low, high):
def check(value):
return (low is None or low <= value) and (high is None or value <= high)
check.__doc__ = f'Value must be between {low} and {high}.'
return check
# теперь сделаем декоратор, который умеет принимать чек-функции и применять их перед вызовом цели
def check(**checks):
def wrapper(func):
sign = inspect.signature(func)
names = list(sign.parameters.keys()) # имена параметров по порядку
not_found = set(checks.keys()) - set(names) # все ли чеки ссылаются на известные параметры?
if not_found:
# у нас есть чек на неизвестный параметр!
raise NameError(', '.join(not_found))
# всё ок, делаем обёртку над функцией
@functools.wraps(func)
def wrapped(*args, **kwargs):
bad = []
for param_name, check_func in checks.items():
idx = names.index(param_name)
if idx < len(args):
# параметр был передан через args
value = args[idx]
if not check_func(value): # вызываем чек-функцию
err = getattr(check_func, '__doc__', '')
if err:
bad.append(f'{param_name} ({err})')
else:
bad.append(param_name)
else:
pass # могут быть хитрости с kwargs-only параметрами. Тут уж извини, мне влом писать.
if bad: # нашли ошибки?
raise ValueError('Bad value for parameters: '+', '.join(bad))
# тут ещё можно помудрить над скрытием последнего фрейма в traceback, но мне опять влом
else: # не нашли, вызываем функцию
return func(*args, **kwargs)
return wrapped
return wrapper
# пример использования
# строка должна быть не из одних пробелов
# число должно быть в пределах от 1 до 10 включительно
@check(s=not_whitespace, n=in_range(1, 10))
def repeat(s: str, n: int) -> str:
return s * n
print(repeat('test ', 3))
try:
print(repeat('test ', 20))
except ValueError as err:
print('yep! it failed!', err)
try:
print(repeat('test ', -1))
except ValueError as err:
print('yep! it failed!', err)
try:
print(repeat(' ', 5))
except ValueError as err:
print('yep! it failed!', err)
try:
print(repeat(' ', 15))
except ValueError as err:
print('yep! it failed!', err)
На фотографии представлен веб-браузер Qutebrowser с 7 открытыми вкладками, в режиме работы с QtWebkit. Как видно, даже с 7 вкладками (2 из которых — страницы Википедии с большим количеством картинок) браузер потребляет около 140 мегабайт, что позволяет комфортно сёрфить интернет на смешных 512 МБ RAM.
Из других браузеров, до сих пор поддерживающих QtWebkit, можно отметить Otter Browser и KDE’шный Konqueror, который дополнительно поддерживает еще и KHTML (3 движка в одном браузере), но в Debian собран только с WebEngine. Первый в репозиториях Debian не присутствует.
Браузер Seamonkey, актуальная версия которого построена на базе движка из Firefox 60, работает более-менее сносно, но не блестяще — рендерит дольше QtWebkit’а примерно в 2-3 раза, потребляет заметно больше памяти, зато работает со всеми современными сайтами. Можно использовать в качестве запасного варианта, когда QtWebkit не справляется.
import datetime
total_time = datetime.timedelta()
lst = ["00:33:33", "00:23:34", "01:32:21"]
for time in lst:
hours, minutes, seconds = time.split(":")
hours, minutes, seconds = int(hours), int(minutes), int(seconds)
total_time += datetime.timedelta(hours=hours, minutes=minutes, seconds=seconds)
print(total_time)
async def command(ctx, a: str, b: str, c:str)
!command раз два три
a, b, c == "раз", "два", "три"
async def command(ctx, a: str, b: str)
!command "раз два" три
a, b == "раз два", "три"
async def command(ctx, a: str, *b: str)
!command раз два три
a, b == "раз", ("два", "три")
async def command(ctx, a: str, *, b: str)
!command раз два три
a, b == "раз", "два три"
txt = "Next, use short sentences, because grandma, like anyone of us, if you make very long sentences, she gets to the end and she can't remember what you said in the beginning, anymore."
try:
A = txt.index("remember")
B = txt.index("grandma")
if int(A) - int(B) < 0:
print('Слово A находится до слова B')
else:
print('Слово A находится после слова B')
except ValueError:
print('Не найдено как минимум одно из слов в строке')