@Pythonetc рд╕рдВрдХрд▓рди, рдордИ 2019



рдпрд╣ рдореЗрд░реА @pythonetc рдлреАрдб рд╕реЗ рдкрд╛рдпрдерди рдЯрд┐рдкреНрд╕ рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХрд╛ рдЧреНрдпрд╛рд░рд╣рд╡рд╛рдВ рдЪрдпрди рд╣реИред

тЖР рдкрд┐рдЫрд▓рд╛ рд╕рдВрдЧреНрд░рд╣


break рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЛ рдмреНрд▓реЙрдХ рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ finally рдмреНрд▓реЙрдХ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдмреНрд▓реЙрдХ except рдХреЛрдИ рднреА рд╣реЛ:

 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 рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╕рднреА рдЫрд╣ рд╡рд┐рдзрд┐рдпрд╛рдБ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЗрдирдореЗрдВ рд╕реЗ рдПрдХ: __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')) # [3] print(load_data_orig('4')) 4 

рдпрд╛ рдЖрдк рдПрдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдЬрд╛рддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдЗрд╕рдХреА 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')) # [3] print(load_data.orig('4')) # 4 

рдпрджрд┐ рдЖрдкрдХреЗ рд╕рднреА рдбреЗрдХреЛрд░реЗрдЯрд░ 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')) # [3] print(load_data.__wrapped__('4')) # 4 

рд▓реЗрдХрд┐рди рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рд╕реЗ рд╕рдЬрд╛рдП рдЧрдП рд╣реИрдВ: рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ __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 рдбреЗрдХреЛрд░реЗрдЯрд░ @saving_orig рдирд╣реАрдВ @saving_orig рдЬреЛ рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдлрдВрдХреНрд╢рди рдореЗрдВ рдХрдИ рдбреЗрдХреЛрд░реЗрдЯрд░ @saving_orig ред рдлрд┐рд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ 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 рдХреЛ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдЬреНрдЬрд╛рдХрд╛рд░ рдХреА рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдХреЗ saving_orig рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ 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 рдкрд╛рд╕ 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 

рд╕рднреА рдХреЛрдб рдпрд╣рд╛рдБ рдЙрдкрд▓рдмреНрдз рд╣реИред

Source: https://habr.com/ru/post/hi454646/


All Articles