Fun with generators


In [ ]:


In [10]:
# Simple genrator replicating range
def my_range(n):
    x = 0
    while x < n:
        yield x
        x += 1

print("'5' first reulsts of my_range")
for x in my_range(5):
    print(x)

# Try out generator expression
gen_exp = (x for x in range(5))

print("Results for generator expression try out")
for x in gen_exp:
    print(x)

# A generator function instance can remember its internal scope
print("Trying using the generator function instance directly with next")
gen = my_range(20)
print(next(gen))
print(next(gen))
print(next(gen))


'5' first reulsts of my_range
0
1
2
3
4
Results for generator expression try out
0
1
2
3
4
Trying using the generator function instance directly with next
0
1
2

In [ ]:

Fun with callable


In [26]:
class my_callable_class(object):
    def __call__(self):
        print("yeah!")

    def __init__(self):
        print("callable created")


class my_non_callable_class(object):
#    def __call__(self):
#        print("yeah!")
    def __init__(self):
        print("non callable created")


obj = my_callable_class()
obj()

obj = my_non_callable_class()
try:
    obj()
except TypeError:
    print("snif snif I can't be called")
    
    
def my_function():
    print("my function called")
    
my_function()

print(my_function.__call__)
print(dir(my_function))
my_function.__call__ = lambda: print("haha fooled you!")
my_function()


callable created
yeah!
non callable created
snif snif I can't be called
my function called
<method-wrapper '__call__' of function object at 0x1072bfc80>
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
my function called

Fun with metaclass


In [17]:
class Meta(type):
    def __prepare__(name, bases, **kwds):
        print("A class {} is being created".format(name))
        return {}
    
    def __new__(cls, name, bases, namespace, **kwds):
        result = type.__new__(cls, name, bases, dict(namespace))
        result.members = tuple(namespace)
        return result

class MyClass(metaclass=Meta):
    def pipi():
        pass

class MySubclass(MyClass):
    def caca():
        pass

c = MyClass()
print(c.members)
sc = MySubclass()
print(sc.members)


A class MyClass is being created
A class MySubclass is being created
('__module__', 'pipi', '__qualname__')
('__module__', 'caca', '__qualname__')

Fun with metaclass #2


In [32]:
class Meta(type):

    def decorator_function(self, fn):
        def wrapper(*args, **kwargs):
            print("Im decorated!!")
            return fn(*args, **kwargs)
        return wrapper

    def __new__(metaclass, name, bases, namespace, **kwds):
       result = super().__new__(metaclass, name, bases, namespace, **kwds)
       #print(result.__dict__)
       return result
    
    def __init__(self, name, bases, namespace, **kwds):
        print("Name is {}, bases are {}, namepsace is {} and kwds are {}".format(name, bases, namespace, kwds))
        super(Meta, self).__init__(name, bases, namespace, **kwds)

        print(self)

        for name, method in namespace.items():
            print(name)
            if name in ['post', 'get', 'put', 'delete']:
                setattr(self, name, self.decorator_function(getattr(self, name)))


       #print("This is the instance created {}".format(instance))

    def decorate(self):
        pass

class A(object):
   pass

class B(A, metaclass=Meta):
    def delete(self):
        print("delete() got called!")

    
class  C(B):
    def get(self):
        print("get() got called!")

    def post(self):
        pass

    def blarg(self):
        pass

b = B()

b.delete()

c = C()

c.get()
c.delete()
c.blarg()


Name is B, bases are (<class '__main__.A'>,), namepsace is {'__qualname__': 'B', 'delete': <function B.delete at 0x10e31b378>, '__module__': '__main__'} and kwds are {}
<class '__main__.B'>
__qualname__
delete
__module__
Name is C, bases are (<class '__main__.B'>,), namepsace is {'__qualname__': 'C', 'get': <function C.get at 0x10e31b268>, 'post': <function C.post at 0x10e31b1e0>, '__module__': '__main__', 'blarg': <function C.blarg at 0x10e31b158>} and kwds are {}
<class '__main__.C'>
__qualname__
get
post
__module__
blarg
Im decorated!!
delete() got called!
Im decorated!!
get() got called!
Im decorated!!
delete() got called!

Fun with class decorator


In [28]:
class MyDecorator(object):
    def __call__(self, klass):
        for name, method in klass.__dict__.items():
            if name in ['post', 'get', 'put', 'delete']:
                setattr(klass, name, self.decorator_function(method))
        return klass
    
    def decorator_function(self, fn):
        def wrapper(*args, **kwargs):
            print("{} is called !!".format(fn))
            return fn(*args, **kwargs)
        return wrapper

@MyDecorator()
class X(object):
    def get(self):
        print("get() method called")
        
    def post(self):
        print("post() method called")
        
    def util(self):
        print("util() method called")
        
x = X()

x.get()
x.post()
x.util()


<function X.get at 0x10e2d3f28> is called !!
get() method called
<function X.post at 0x10e2d3bf8> is called !!
post() method called
util() method called

A more complex generator


In [100]:
my_dict = {'a': { 'b': 2, 'c': 3}, 'd': {'e': 4}, 'f': 5}

def flatten_document(document):
    """ Convert a mongo document and its subdocuments hiearchy into a one-level document. All document leaves nodes are concated together. """
    def flatten_leaves(root):
        """ Generator function flattening all dictonary leaves nodes to one string. 
        :returns: A tuple where the first element is the flattened keys and the second element is the leave end value.
        """
        for key, value in root.items():
            if isinstance(value, dict):
                for sub_key, sub_value in flatten_leaves(value):
                    yield ":".join([key, sub_key]), sub_value
            else:
                yield key, value
    return dict(flatten_leaves(document))

flatten_document(my_dict)


Out[100]:
{'a:c': 3, 'f': 5, 'a:b': 2, 'd:e': 4}

In [63]:

Fun with __getattribute__


In [89]:
from collections import namedtuple

Clan = namedtuple("Clan", ('id', 'name', 'country'))

class LazyClan(Clan):
    
    def __new__(cls, id, clan=None, *args, **kwargs):
        if clan:
            # No need for a proxy, just use the `Clan` instance itself
            return clan
        return super(LazyClan, cls).__new__(cls, id, name=None, country=None, *args, **kwargs)
    
    def __getattribute__(self, name):
        try:
            #Get proxied object. 
            clan = object.__getattribute__(self, "clan")
        except AttributeError:
            # Object not available, fetch it (simulate with creating a a new Clan)
            clan = Clan(id=123, name='The buzz', country='canada')
            if not clan:
                # We may have concurrency issue.
                return None
            self.clan = clan
        return object.__getattribute__(clan, name)

clan1 = LazyClan(id=1)
print(clan1.id)
print(clan1.name)
print(clan1.country)


123
The buzz
canada

Fun with cookies


In [20]:
from http.cookies import SimpleCookie
cookie = SimpleCookie()
cookie.load('_xsrf=2|be215796|1e00e7427a87bdd0c8ead3ba49867ad9|1430424396; Path=/,user=; expires=Wed, 30 Apr 2014 20:06:36 GMT; Path=/')
print(cookie)
print(cookie['_xsrf'])
cookie2 = SimpleCookie()
cookie2.load('user=; expires=Wed, 30 Apr 2014 20:16:03 GMT; Path=/,_xsrf=2|33ea9c7c|cbe2b87de1e2f8dabd0a1371b7991f43|1430424963; Path=/')
print(80*"*")
print(cookie2)
print("-")
print(cookie2['user'])
#print(cookie2['_xsrf'])


Set-Cookie: _xsrf=2|be215796|1e00e7427a87bdd0c8ead3ba49867ad9|1430424396; expires=Wed, 30 Apr 2014 20:06:36 GMT; Path=/
Set-Cookie: _xsrf=2|be215796|1e00e7427a87bdd0c8ead3ba49867ad9|1430424396; expires=Wed, 30 Apr 2014 20:06:36 GMT; Path=/
********************************************************************************
Set-Cookie: user=; expires=Wed, 30 Apr 2014 20:16:03 GMT; Path=/
-
Set-Cookie: user=; expires=Wed, 30 Apr 2014 20:16:03 GMT; Path=/

In [ ]: