+3.9 decorators

    
      
diff --git a/pythonetc/3.9/decorators.md b/pythonetc/3.9/decorators.md
new file mode 100644
index 0000000..8d1daff
--- /dev/null
+++ b/pythonetc/3.9/decorators.md
@@ -0,0 +1,64 @@
+[Syntax for decorators is limited](https://t.me/pythonetc/16) by getting attributes and calling objects:
+
+```python
+decos = {
+  'id': lambda x: x,
+}
+
+@decos['id']
+def f(): pass
+# SyntaxError: invalid syntax
+```
+
+Python 3.9 (via [PEP-614](https://www.python.org/dev/peps/pep-0614/)) relaxes with restriction allowing to have any expression as a decorator:
+
+```python
+decos = {
+  'id': lambda x: x,
+}
+
+@decos['id']
+def f(): pass
+
+f
+# 
+```
+
+You can use matrix multiplication to make it really confusing (don't try it at home!):
+
+```python
+class D:
+  f = None
+  def __init__(self, name):
+    self.name = name
+
+  def __call__(self, *args, **kwargs):
+    # on the first call save the function
+    if self.f is None:
+      self.f = args[0]
+      return self
+    # on all the next calls call the function
+    print(f'hello from {self.name}!')
+    return self.f(*args, **kwargs)
+
+  # matrix multiplication logic
+  def __matmul__(self, other):
+    return lambda f: self(other(f))
+
+# the second `@` is actually the matrix multiplication
+@D('a') @D('b')
+def f(): pass
+
+f()
+# hello from a!
+# hello from b!
+```
+
+You can use a simple wrapper function to have any expression in older python versions:
+
+```python
+_ = lambda x: x
+
+@_(D('a') @ D('b'))
+def f(): pass
+```
diff --git a/pythonetc/README.md b/pythonetc/README.md
index ae499a8..173ba9b 100644
--- a/pythonetc/README.md
+++ b/pythonetc/README.md
@@ -10,6 +10,7 @@ A bit of history and 3.9:
 1. ./3.9/generic-types.md
 1. ./hist/types.md
 1. ./3.9/unparse.md
+1. ./3.9/decorators.md
 
 Frames: