my net house

WAHEGURU….!

Funtionaly Funtions in Pythonistic Python(s) by Pythonista! Part-2

6. having a wrapper outside and inside.

Importance of function wrapper is handling your data behaviour but also making sure , your wrapper is able to handle any kind of behaviour.

>>> def escape_unicode(f):                                                      
...     def wrap(*args, **kwargs):                                              
...         x = f(*args, **kwargs)                                              
...         return ascii(x)                                                     
...     return wrap                                                             
...                                                                             
>>> def northern_city():                                                        
...     return 'Tromsø'                                                         
...                                                                             
>>> print(northern_city())                                                      
Tromsø                                                                          
>>> @escape_unicode                                                             
... def northern_city():                                                        
...     return 'Tromsø'                                                         
...                                                                             
>>> print(northern_city())                                                      
'Troms\xf8'                                                                     

7. Using Class to create wapper/Decorator

Any class level attribute inside __call__() would be a Attribute for function in which Class is Wrapped around!

>>> class CallCount:                                                            
...     def __init__(self, f):                                                  
...         self.f = f                                                          
...         self.count = 0                                                      
...     def __call__(self, *args, **kwargs):                                    
...         self.count += 1                                                     
...         return self.f(*args, **kwargs)                                      
...                                                                             
>>> @CallCount                                                                  
... def hello(name):                                                            
...     print('Hello, {}!'.format(name))                                        
...                                                                             
>>> hello('Fred')                                                               
Hello, Fred!                                                                    
>>> hello('Wilma')                                                              
Hello, Wilma!                                                                   
>>> hello('Betty')                                                              
Hello, Betty!                                                                   
>>> hello('Barney')                                                             
Hello, Barney!                                                                  
>>> hello.count                                                                 
4

8. A wrapper inside class __call__() can be used to Turn Wrapper On and Off.

>>> class Trace:                                                                
...     def __init__(self):                                                     
...         self.enabled = True                                                 
...     def __call__(self, f):                                                  
...         def wrap(*args, **kwargs):                                          
...             if self.enabled:                                                
...                 print('Calling {}'.format(f))                               
...             return f(*args, **kwargs)                                       
...         return wrap                                                         
...                                                                             
>>> tracer = Trace()                                                            
>>> @tracer                                                                     
... @escape_unicode                                                             
... def norwegian_island_maker(name):                                           
...     return name + 'øy'                                                      
...                                                                             
>>> norwegian_island_maker('Llama')                                             
Calling <function escape_unicode.<locals>.wrap at 0x103b22ee0>                  
'Llama\\xf8y'                                                                   
>>> norwegian_island_maker('Python')                                            
Calling <function escape_unicode.<locals>.wrap at 0x103b22ee0>                  
'Python\\xf8y'                                                                  
>>> norwegian_island_maker('Troll')                                             
Calling <function escape_unicode.<locals>.wrap at 0x103b22ee0>                  
'Troll\\xf8y'                                                                   
>>> tracer.enabled = False                                                      
>>> norwegian_island_maker('Llama')                                             
'Llama\\xf8y'                                                                   
>>> norwegian_island_maker('Python')                                            
'Python\\xf8y'                                                                  
>>> norwegian_island_maker('Troll')                                             
'Troll\\xf8y'    

9. Map would be able to accept multiple arguents if Functions who is being mapped able to accept Multiple argument.

>>> colors = ['lavender', 'teal', 'burnt orange']                               
>>> animals = ['koala', 'platypus', 'salamander']                               
>>> def combine(size, color, animal):                                           
...     return '{} {} {}'.format(size, color, animal)                           
...                                                                             
>>> list(map(combine, sizes, colors, animals))                                  
['small lavender koala', 'medium teal platypus', 'large burnt orange salamander'
] 

10. List Comprehensions can be more lazy and complex with multipe For Loops and If statements.

>>> values = [x / (x - y) for x in range(100) if x > 50 for y in range(100) if x
 - y != 0]                                                                      
>>> values = [x / (x - y)                                                       
...           for x in range(100)                                               
...           if x > 50                                                         
...           for y in range(100)                                               
...           if x - y != 0]                                                    
>>> values = []                                                                 
>>> for x in range(100):                                                        
...     if x > 50:                                                              
...         for y in range(100):                                                
...             if x - y != 0:                                                  
...                 values.append(x / (x - y))                                  
...                                

11. list comprehensions could be Nested as well.

>>> vals = [[y * 3 for y in range(x)] for x in range(10)]                       
>>> outer = []                                                                  
>>> for x in range(10):                                                         
...     inner = []                                                              
...     for y in range(x):                                                      
...         inner.append(y * 3)                                                 
...     outer.append(inner)                                                     
...                                                                             
>>> vals                                                                        
[[], [0], [0, 3], [0, 3, 6], [0, 3, 6, 9], [0, 3, 6, 9, 12], [0, 3, 6, 9, 12, 15
], [0, 3, 6, 9, 12, 15, 18], [0, 3, 6, 9, 12, 15, 18, 21], [0, 3, 6, 9, 12, 15, 
18, 21, 24]]                

12. Some ideas for Code interospection!

  1. type() is of class type
>>> repr(int)                                                                   
"<class 'int'>"                                                                 
>>> type(i) is int                                                              
True                                                                            
>>> type(i)(78)                                                                 
78                                                                              
>>> type(type(i))                                                               
<class 'type'>                                                                  
>>> i.__class__                                                                 
<class 'int'>

2. isinstance and issubclass is type-checking subclass of class Type()

>>> issubclass(type, object)                                                    
True                                                                            
>>> type(object)                                                                
<class 'type'>                                                                  
>>> isinstance(i, int)                                                          
True                                                                         

3. To check if class object has specific attibute Eists.

 

>>> getattr(a, 'conjugate')                                                     
<built-in method conjugate of int object at 0x10ff2cfb0>                        
>>> callable(getattr(a, 'conjugate'))                                           
True                                                                            
>>> a.conjugate.__class__.__name__                                              
'builtin_function_or_method'                                                    
>>> getattr(a, 'index')                                                         
Traceback (most recent call last):                                              
  File "<stdin>", line 1, in <module>                                           
AttributeError: 'int' object has no attribute 'index'                           
>>> hasattr(a, 'bit_length')                                                    
True                                                                            
>>> hasattr(a, 'index')                                                         
False

4. Globas() and Locals() is Dict whch keep track of your globals and Locals.

>>> globals()                                                                   
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <cl
ass '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {
}, '__builtins__': <module 'builtins' (built-in)>}                              
>>> a = 42                                                                      
>>> globals()                                                                   
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <cl
ass '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {
}, '__builtins__': <module 'builtins' (built-in)>, 'a': 42}                     
>>> globals()['tau'] = 6.283185                                                 
>>> tau                                                                         
6.283185                                                                        
>>> tau / 2                                                                     
3.1415925                                                                       

>>> locals()                                                                    
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <cl
ass '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {
}, '__builtins__': <module 'builtins' (built-in)>}                              
>>> def report_scope(arg):                                                      
...     from pprint import pprint as pp                                         
...     x = 496                                                                 
...     pp(locals(), width=10)                                                  
...                                                                             
>>> report_scope(42)                                                            
{'arg': 42,                                                                     
 'pp': <function pprint at 0x10e70bee0>,                                        
 'x': 496}                                                                      
>>>                                                                             

5. import inspect.

Just like Golang’s reflect package.

>>> def num_vowels(text: str) -> int:                                           
...     return sum(1 if c.lower() in 'aeiou' else 0                             
...                for c in text)                                               
...                                                                             
>>> import inspect                                                              
>>> sig = inspect.signature(num_vowels)                                         
>>> sig.parameters['text']                                                      
<Parameter "text: str">                                                         
>>> sig.parameters['text'].annotation                                           
<class 'str'>                                                                   
>>> sig                                                                         
<Signature (text: str) -> int>                                                  
>>> sig.return_annotation                                                       
<class 'int'>                                                                   
>>> num_vowels.__annotations__                                                  
{'text': <class 'str'>, 'return': <class 'int'>}                                

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: