рдпрд╣ рдореЗрд░реЗ рдЯреЗрд▓реАрдЧреНрд░рд╛рдо-рдЪреИрдирд▓ @pythonetc рд╕реЗ рдкрд╛рдпрдерди рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реБрдЭрд╛рд╡реЛрдВ рдФрд░ рдЯреНрд░рд┐рдХреНрд╕ рдХрд╛ рдПрдХ рдирдпрд╛ рдЪрдпрди рд╣реИред
Ations 
рдкрд┐рдЫрд▓рд╛ рдкреНрд░рдХрд╛рд╢рдиbreak рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдЕрдкрд╡рд╛рдж рдХреЛ рджрдмрд╛ 
break , рдЬрдм 
finally рдореЗрдВ рдмреНрд▓реЙрдХ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ рднреА 
finally рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
 for i in range(10): try: 1 / i finally: print('finally') break print('after try') print('after while') 
рдЖрдЙрдЯрдкреБрдЯ:
 finally after while 
continue рд▓рд┐рдП рднреА рдпрд╣реА рд╕рдЪ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐ рдЗрд╕реЗ 
finally рдкрд╛рдпрдерди 3.8 рддрдХ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
 SyntaxError: 'continue' not supported inside 'finally' clause 
рдЖрдк рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдореЗрдВ рдпреВрдирд┐рдХреЛрдб рд╡рд░реНрдгреЛрдВ рдХреЛ рди рдХреЗрд╡рд▓ рдЗрд╕рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдЗрд╕рдХреЗ рдирд╛рдо рд╕реЗ рднреА рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред
 >>> '\N{EM DASH}' 'тАФ' >>> '\u2014' 'тАФ' 
рдпрд╣ рдПрдл-рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рднреА рд╕рдВрдЧрдд рд╣реИ:
 >>> width = 800 >>> f'Width \N{EM DASH} {width}' 'Width тАФ 800' 
рдкрд╛рдпрдерди рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдЫрд╣ рдЬрд╛рджреВ рдХреЗ рддрд░реАрдХреЗ рд╣реИрдВ рдЬреЛ рддреБрд▓рдирд╛ рдирд┐рдпрдореЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
- __lt__рд▓рд┐рдП- <
 
- __gt__рд▓рд┐рдП- >
 
- __le__рд▓рд┐рдП- <=
 
- __ge__рд▓рд┐рдП- >=
 
- __eq__рд▓рд┐рдП- ==
 
- __ne__рд▓рд┐рдП- !=
 
рдпрджрд┐ рдЗрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рд╡рд┐рдзрд┐рдпрд╛рдБ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рд╣реИрдВ рдпрд╛ 
NotImplemented , рддреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рдпрдо рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ:
- a.__lt__(b)- b.__gt__(a)
- a.__le__(b)- b.__ge__(a)
- a.__eq__(b)рдПрдХ рд╣реА- not a.__ne__(b)(рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ- aрдФрд░- bрдХреЛ рд╕реНрд╡реИрдк рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)
рд╣рд╛рд▓рд╛рдВрдХрд┐, 
a >= b рдФрд░ 
a != b рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ 
a > b ред 
functools.total_ordering ред 
functools.total_ordering рдбреЗрдХреЛрд░реЗрдЯрд░ 
__eq__ рдФрд░ рдирд┐рдореНрди рдореЗрдВ рд╕реЗ рдПрдХ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╕рднреА рдЫрд╣ рд╡рд┐рдзрд┐рдпрд╛рдБ рдмрдирд╛рддреЗ рд╣реИрдВ: 
__lt__ , 
__gt__ , 
__le__ , рдпрд╛ 
__ge__ ред
 from functools import total_ordering @total_ordering class User: def __init__(self, pk, name): self.pk = pk self.name = name def __le__(self, other): return self.pk <= other.pk def __eq__(self, other): return self.pk == other.pk assert User(2, 'Vadim') < User(13, 'Catherine') 
рдХрднреА-рдХрднреА рдЖрдк рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдЬрд╛рдП рдЧрдП рдФрд░ рдЕрдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рд╡рд┐рд╢реЗрд╖ рдбреЗрдХреЛрд░реЗрдЯрд░ рд╕рд┐рдВрдЯреИрдХреНрд╕ ( 
@ рд╕рд╛рде рдПрдХ) рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВ рдФрд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕рдЬрд╛рдпрд╛ рдЧрдпрд╛ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдВ:
 import json def ensure_list(f): def decorated(*args, **kwargs): result = f(*args, **kwargs) if isinstance(result, list): return result else: return [result] return decorated def load_data_orig(string): return json.loads(string) load_data = ensure_list(load_data_orig) print(load_data('3'))  
рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ, рдЖрдк рдПрдХ рдЕрдиреНрдп рдбреЗрдХреЛрд░реЗрдЯрд░ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдирдП рдХреЗ 
orig рдЧреБрдг рдореЗрдВ рдЗрд╕рдХреЗ рдореВрд▓ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд╕рдВрд░рдХреНрд╖рд┐рдд рдХрд░рддреЗ рд╣реБрдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдЬрд╛рддреЗ рд╣реИрдВ:
 import json def saving_orig(another_decorator): def decorator(f): decorated = another_decorator(f) decorated.orig = f return decorated return decorator def ensure_list(f): ... @saving_orig(ensure_list) def load_data(string): return json.loads(string) print(load_data('3'))  
рдпрджрд┐ рд╕рднреА рд╕рдЬреНрдЬрд╛рдХрд╛рд░ рдЖрдкрдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдк 
functools.wraps рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ 
functools.wraps рддреЛ рдЖрдк 
__wrapped__ рдлрд╝рдВрдХреНрд╢рди рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП 
__wrapped__ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 import json from functools import wraps def ensure_list(f): @wraps(f) def decorated(*args, **kwargs): result = f(*args, **kwargs) if isinstance(result, list): return result else: return [result] return decorated @ensure_list def load_data(string): return json.loads(string) print(load_data('3'))  
рдорди, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рджреНрд╡рд╛рд░рд╛ рд╕рдЬрд╛рдП рдЧрдП рд╣реИрдВ: рдЖрдкрдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП рдкреНрд░рддреНрдпреЗрдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рд▓рд┐рдП 
__wrapped__ рдХрд╛ рдЙрдкрдпреЛрдЧ 
__wrapped__ :
 def ensure_list(f): ... def ensure_ints(f): @wraps(f) def decorated(*args, **kwargs): result = f(*args, **kwargs) return [int(x) for x in result] return decorated @ensure_ints @ensure_list def load_data(string): return json.loads(string) for f in ( load_data, load_data.__wrapped__, load_data.__wrapped__.__wrapped__, ): print(repr(f('"4"'))) 
рдЖрдЙрдЯрдкреБрдЯ:
 [4] ['4'] '4' 
рдКрдкрд░ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд 
@saving_orig рдПрдХ рдЕрдиреНрдп рд╕рдЬреНрдЬрд╛рдХрд╛рд░ рдХреЛ рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдЙрд╕ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рдкреИрд░рд╛рдЯреНрд░рд╛рдЗрдЬреНрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рдЦреИрд░, рдЪреВрдВрдХрд┐ рдкреИрд░рд╛рдореАрдЯрд░рд╛рдЗрдЬрд╝рд░ рдбреЗрдХреЛрд░реЗрдЯрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдпрд╣ рдорд╛рдорд▓рд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
 import json from functools import wraps def saving_orig(another_decorator): def decorator(f): decorated = another_decorator(f) decorated.orig = f return decorated return decorator def ensure_ints(*, default=None): def decorator(f): @wraps(f) def decorated(*args, **kwargs): result = f(*args, **kwargs) ints = [] for x in result: try: x_int = int(x) except ValueError: if default is None: raise else: x_int = default ints.append(x_int) return ints return decorated return decorator @saving_orig(ensure_ints(default=0)) def load_data(string): return json.loads(string) print(repr(load_data('["2", "3", "A"]'))) print(repr(load_data.orig('["2", "3", "A"]'))) 
@saving_orig рдбреЗрдХреЛрд░реЗрдЯрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╡рд╣ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рд▓рд╛рдЧреВ рд╣реЛрдВред рд╣рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдРрд╕реЗ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
 import json from functools import wraps def saving_orig(another_decorator): def decorator(f): decorated = another_decorator(f) decorated.orig = f return decorated return decorator def ensure_list(f): ... def ensure_ints(*, default=None): ... @saving_orig(ensure_ints(default=42)) @saving_orig(ensure_list) def load_data(string): return json.loads(string) for f in ( load_data, load_data.orig, load_data.orig.orig, ): print(repr(f('"X"'))) 
рдЖрдЙрдЯрдкреБрдЯ:
 [42] ['X'] 'X' 
рд╣рдо 
saving_orig рддрд░реНрдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдЬреНрдЬрд╛рдХрд╛рд░реЛрдВ рдХреА рдордирдорд╛рдиреА рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдХреЗ рдЗрд╕реЗ рдареАрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 def saving_orig(*decorators): def decorator(f): decorated = f for d in reversed(decorators): decorated = d(decorated) decorated.orig = f return decorated return decorator ... @saving_orig( ensure_ints(default=42), ensure_list, ) def load_data(string): return json.loads(string) for f in ( load_data, load_data.orig, ): print(repr(f('"X"'))) 
рдЖрдЙрдЯрдкреБрдЯ:
 [42] 'X' 
рдПрдХ рдФрд░ рдЙрдкрд╛рдп рд╣реИ 
saving_orig рд╕реНрдорд╛рд░реНрдЯ рдмрдирд╛рдирд╛ 
saving_orig рдПрдХ рд╕рдЬрд╛рдпрд╛ рдлрдВрдХреНрд╢рди рд╕реЗ рджреВрд╕рд░реЗ рдореЗрдВ рдкрд╛рд╕ рд╣реЛ рд╕рдХреЗ:
 def saving_orig(another_decorator): def decorator(f): decorated = another_decorator(f) if hasattr(f, 'orig'): decorated.orig = f.orig else: decorated.orig = f return decorated return decorator @saving_orig(ensure_ints(default=42)) @saving_orig(ensure_list) def load_data(string): return json.loads(string) 
рдпрджрд┐ рдЖрдк рдЬреЛ рдбреЗрдХреЛрд░реЗрдЯрд░ рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВ рд╡рд╣ рдмрд╣реБрдд рдЬрдЯрд┐рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ 
__call__ рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рдлрдВрдХреНрд╢рди рд╕реЗ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдмрджрд▓рдирд╛ рдЙрдЪрд┐рдд рд╣реЛ рд╕рдХрддрд╛ рд╣реИ
 class SavingOrig: def __init__(self, another_decorator): self._another = another_decorator def __call__(self, f): decorated = self._another(f) if hasattr(f, 'orig'): decorated.orig = f.orig else: decorated.orig = f return decorated saving_orig = SavingOrig 
рдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ рдЖрдкрдХреЛ рдКрдВрдЯ рдорд╛рдорд▓реЗ рдХреЗ рд╕рд╛рде рд╡рд░реНрдЧ рдХрд╛ рдирд╛рдо рдФрд░ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХрд╛ рдирд╛рдо рд╕рд╛рдБрдк рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд░рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред
рд╕рдЬрд╛рдП рдЧрдП рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЖрдк рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдмрдЬрд╛рдп рдЕрдкрдиреЗ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╡рд░реНрдЧ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:
 class CallableWithOrig: def __init__(self, to_call, orig): self._to_call = to_call self._orig = orig def __call__(self, *args, **kwargs): return self._to_call(*args, **kwargs) @property def orig(self): if isinstance(self._orig, type(self)): return self._orig.orig else: return self._orig class SavingOrig: def __init__(self, another_decorator): self._another = another_decorator def __call__(self, f): return CallableWithOrig(self._another(f), f) saving_orig = SavingOrig 
рдкреВрд░рд╛ рдХреЛрдб 
рдпрд╣рд╛рдВ рджреЗрдЦреЗрдВ