Skip to content

Commit

Permalink
more changes to decorators
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel2409 committed Mar 23, 2021
1 parent 598327a commit fd05234
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 22 deletions.
12 changes: 12 additions & 0 deletions 51_dict_implementation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# %% [markdown]
# # dicts in python
"""
also see c1_09 file
creating a dict + basic methods
eq and hash
crazy dict : override a key
OrderedDict + __reversed__
defaultdict + __missing__
chainMap
readonly dict with MappingProxyTypes
"""
# %%
my_dict = {'key1': "value1", "key2": 9, 45: "ff", (45, 78): 39}
print(my_dict)
Expand Down
8 changes: 8 additions & 0 deletions 52_array_datastruct.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# %%
"""
lists, tuples
array
str
bytes
ascii experiments
"""
# %% Array are contiguous data structures : They store information in adjoining blocks of memory. (by opposition to linked data structure which are chunks of memory linked by pointer, like linked-lists)

# %% lists are dynamic array : elements can be added or removed and python will automatically add or release memory
Expand Down
6 changes: 6 additions & 0 deletions 53_records_struct_datatransfer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""
namedtuples
struct
simplenamespace
"""

#%% named tuple : a good way to write more readable code by enforcing the structure of your data : you can't mispell a field
from collections import namedtuple
p1 = namedtuple("Point", "x y z")(1,2,3)
Expand Down
6 changes: 6 additions & 0 deletions c2_12_sanitizing_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#%%
"\x00".isprintable()
# %%
"\x00".isascii()

# %%
66 changes: 61 additions & 5 deletions c9_09_class_decorators.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#%%
"""
class decorator : basic
class decorator : __get__
"""

#%% [markdown]
# # Class decorators for functions
#%%
Expand Down Expand Up @@ -43,18 +49,19 @@ def passer2():
# %%
passer2() # increase because passer2 is now an instance of Profiled. The decorator does that
# %% [markdown]
# # make your class decorator method compatible
# # Make your class decorator method compatible
#%%
class Test:
@Profiled
def test(self):
def fail(self):
print(42)


Test().test() # error ! why ?
Test().fail() # error ! why ?
# %%
"""
If we decompose : we have test = Profiled(test) whihch means test is now an attribute of Test. When I access Test().test(), it calls the __get__ method of the test attribute..
In conclusion, if you define a decorator as a class, you need to implement the __get__ method in order to use it inside classes
If we decompose : we have fail = Profiled(fail) which means fail is now an attribute of Test. When I access Test().fail(), it calls the __get__ method of the fail attribute..
In conclusion, if you define a decorator as a class, you need to implement the __get__ method in order to use it inside other classes
"""

class Profiled2:
Expand Down Expand Up @@ -118,6 +125,55 @@ def baz():
"""
Further investigation needed on the __get__ and types.MethodType
"""
# %%
"""
Exercise : rewrite the Profiled2 decorator as a function decorator
"""
# %%




























# %%
def profiled2(func):
ncalls = 0
@wraps(func)
def wrapper(*args, **kwargs):
nonlocal ncalls
ncalls +=1
print("CALL", ncalls)
return func(*args, **kwargs)

return wrapper

@profiled2
def passtime():
pass

# %%
passtime()
# %%
100 changes: 83 additions & 17 deletions c9_09_descriptor_property_class_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
The right way to use property
class and static methods
stack decorator with class and static method
lazy property
"""

#%% [markdown]
Expand Down Expand Up @@ -91,7 +92,6 @@ def delval(self):
"""val = property(fget=getval, fset=setval, fdel=delval, doc="val property")
is the same as the 4 lines above where i instantiate property and then define the getter, setter and deleter.
"""

val = property()
val = val.getter(getval)
# I can also replace the two lines above with val = property(getval)
Expand Down Expand Up @@ -177,7 +177,6 @@ def __get__(self, instance, owner=None):
return self.f



class ClassMethod:
"Emulate PyClassMethod_Type() in Objects/funcobject.c and adds print of instance and owner"""
def __init__(self, f):
Expand Down Expand Up @@ -259,30 +258,97 @@ def passer():
pass

Ok.passer()
#%%

aa = {"a":1, "b":2, "c":0}

min(aa[key] for key in ["a", "n"] & aa.keys())
# %%
def lazy_property(fn):
'''Decorator that makes a property lazy-evaluated.
'''
attr_name = '_lazy_' + fn.__name__

class Field:
def __init__(self,val):
self.val = val
@property
def _lazy_property(self):
if not hasattr(self, attr_name):
setattr(self, attr_name, fn(self))
return getattr(self, attr_name)
return _lazy_property

def __repr__(self):
return f"<Field : val {self.val:f}>"
class Person:
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation

@lazy_property
def relatives(self):
# Get all relatives
for _ in range(100000000):
pass

return 5

# %%
a = Person("a","d")

a = {"aa":Field(5)}
# %%
a["aa"]
a.relatives
# %%
a["aa"].val = 9
dir(a)
# %%
aa = set((1,2,5,6))
aa.add(6)
class User1:
def __init__(self, username):
self.username = username
self._profile_data = None
print(f"{self.__class__.__name__} instance created")

@property
def profile_data(self):
if self._profile_data is None:
print("self._profile_data is None")
self._profile_data = self._get_profile_data()
else:
print("self._profile_data is set")
return self._profile_data

def _get_profile_data(self):
# get the data from the server and load it to memory
print("Run the expensive operation")
fetched_data = "The mock data of a large size"
return fetched_data
# %%
aa
u = User1(5)
# %%
u.profile_data
# %%
u.profile_data
# %%
import json
from json import JSONEncoder

class MyJSONEncoder(JSONEncoder):
def default(self, o):
if hasattr(o, 'toJSON'):
return o.toJSON()
return super().default(o)


class C:
def __init__(self, name):
self.name = name
def toJSON(self):
return {"name":self.name}

c = C("jon")
class D:
def __init__(self, name, cc):
self.name = name
self.cc = cc

def toJSON(self):
return {"name":self.name, "cc":self.cc}


d = D("ff", c)


print(json.dumps(d, cls=MyJSONEncoder))
with open("gg.json", "w+") as fp:
json.dump(d, fp, indent=4, cls=MyJSONEncoder)

0 comments on commit fd05234

Please sign in to comment.