You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is a saying [Closures are the poor mans objects](https://stackoverflow.com/questions/2497801/closures-are-poor-mans-objects-and-vice-versa-what-does-this-mean), don't know who the poor man is, some languages, like Haskell, do without object systems at all. I think, it means that both objects and closures are equivalent means of storing state.
529
529
Let's see, how this concept is put to use with decorators
530
530
531
-
## <aid='s1-3' />Decorators by means of first class functions/closures
531
+
###<aid='s1-2-2' />Decorators by means of first class functions/closures
532
532
533
533
Time to examine other options. Python people like to do decorators with first class functions, that means lots of closures and functions returning closures/function values.
534
534
In my book that is a bit of a brain damage, but let's go for it, real pythonistas are not afraid of brain damage! (i think that's quotable ;-))
## <aid='s1-4' />Decorators in the python standard library
755
+
## <aid='s1-3' />Decorators in the python standard library
756
756
757
757
758
-
### <aid='s1-4-1' />@staticmethod and @classmethod
758
+
### <aid='s1-3-1' />@staticmethod and @classmethod
759
759
760
760
@staticmethod and @classmethod are built-in decorators, you don't have to import any package in order to use them
761
761
@@ -800,8 +800,8 @@ __Result:__
800
800
801
801
```
802
802
>> absolute of a number: 3
803
-
>> random number between 0 and 1 0.8809536053849658
804
-
>> random number between 0 and 1 0.5903456526346241
803
+
>> random number between 0 and 1 0.9720065130017221
804
+
>> random number between 0 and 1 0.3578250940925185
805
805
```
806
806
807
807
A method that is declared with the @classmthod decorator, here the first parameter is the class object. Note that a method like this doesn't have a self parameter.
Copy file name to clipboardexpand all lines: decorator.py
+1-1
Original file line number
Diff line number
Diff line change
@@ -368,7 +368,7 @@ def nested_function():
368
368
Let's see, how this concept is put to use with decorators""")
369
369
370
370
371
-
header_md("Decorators by means of first class functions/closures", nesting=2)
371
+
header_md("Decorators by means of first class functions/closures", nesting=3)
372
372
373
373
print_md("""
374
374
Time to examine other options. Python people like to do decorators with first class functions, that means lots of closures and functions returning closures/function values.
If two variables have the same object id value, then they both refer to the very same object/instance!
@@ -384,9 +384,9 @@ __Result:__
384
384
385
385
```
386
386
>> *** mro in detail:
387
-
>> class-in-mro: <class '\_\_main\_\_.Foo'> id: 140503550051248 cls.\_\_dict\_\_: {'\_\_module\_\_': '\_\_main\_\_', 'class\_var': 42, 'class\_var2': 43, '\_\_init\_\_': <function Foo.\_\_init\_\_ at 0x7fc9886e8790>, 'show\_derived': <function Foo.show\_derived at 0x7fc9886e8820>, 'make\_foo': <staticmethod object at 0x7fc9886ebdc0>, '\_\_doc\_\_': None}
388
-
>> class-in-mro: <class '\_\_main\_\_.Base'> id: 140503550050304 cls.\_\_dict\_\_: {'\_\_module\_\_': '\_\_main\_\_', 'base\_class\_var': 'Base', '\_\_init\_\_': <function Base.\_\_init\_\_ at 0x7fc9886e85e0>, 'show\_base': <function Base.show\_base at 0x7fc9886e8670>, 'make\_base': <staticmethod object at 0x7fc9886ebfd0>, '\_\_dict\_\_': <attribute '\_\_dict\_\_' of 'Base' objects>, '\_\_weakref\_\_': <attribute '\_\_weakref\_\_' of 'Base' objects>, '\_\_doc\_\_': None}
389
-
>> class-in-mro: <class 'object'> id: 4311403440 cls.\_\_dict\_\_: {'\_\_repr\_\_': <slot wrapper '\_\_repr\_\_' of 'object' objects>, '\_\_hash\_\_': <slot wrapper '\_\_hash\_\_' of 'object' objects>, '\_\_str\_\_': <slot wrapper '\_\_str\_\_' of 'object' objects>, '\_\_getattribute\_\_': <slot wrapper '\_\_getattribute\_\_' of 'object' objects>, '\_\_setattr\_\_': <slot wrapper '\_\_setattr\_\_' of 'object' objects>, '\_\_delattr\_\_': <slot wrapper '\_\_delattr\_\_' of 'object' objects>, '\_\_lt\_\_': <slot wrapper '\_\_lt\_\_' of 'object' objects>, '\_\_le\_\_': <slot wrapper '\_\_le\_\_' of 'object' objects>, '\_\_eq\_\_': <slot wrapper '\_\_eq\_\_' of 'object' objects>, '\_\_ne\_\_': <slot wrapper '\_\_ne\_\_' of 'object' objects>, '\_\_gt\_\_': <slot wrapper '\_\_gt\_\_' of 'object' objects>, '\_\_ge\_\_': <slot wrapper '\_\_ge\_\_' of 'object' objects>, '\_\_init\_\_': <slot wrapper '\_\_init\_\_' of 'object' objects>, '\_\_new\_\_': <built-in method \_\_new\_\_ of type object at 0x100facbb0>, '\_\_reduce\_ex\_\_': <method '\_\_reduce\_ex\_\_' of 'object' objects>, '\_\_reduce\_\_': <method '\_\_reduce\_\_' of 'object' objects>, '\_\_subclasshook\_\_': <method '\_\_subclasshook\_\_' of 'object' objects>, '\_\_init\_subclass\_\_': <method '\_\_init\_subclass\_\_' of 'object' objects>, '\_\_format\_\_': <method '\_\_format\_\_' of 'object' objects>, '\_\_sizeof\_\_': <method '\_\_sizeof\_\_' of 'object' objects>, '\_\_dir\_\_': <method '\_\_dir\_\_' of 'object' objects>, '\_\_class\_\_': <attribute '\_\_class\_\_' of 'object' objects>, '\_\_doc\_\_': 'The base class of the class hierarchy.\n\nWhen called, it accepts no arguments and returns a new featureless\ninstance that has no instance attributes and cannot be given any.\n'}
387
+
>> class-in-mro: <class '\_\_main\_\_.Foo'> id: 140700524042176 cls.\_\_dict\_\_: {'\_\_module\_\_': '\_\_main\_\_', 'class\_var': 42, 'class\_var2': 43, '\_\_init\_\_': <function Foo.\_\_init\_\_ at 0x7ff764ee8790>, 'show\_derived': <function Foo.show\_derived at 0x7ff764ee8820>, 'make\_foo': <staticmethod object at 0x7ff764eebdc0>, '\_\_doc\_\_': None}
388
+
>> class-in-mro: <class '\_\_main\_\_.Base'> id: 140700524041232 cls.\_\_dict\_\_: {'\_\_module\_\_': '\_\_main\_\_', 'base\_class\_var': 'Base', '\_\_init\_\_': <function Base.\_\_init\_\_ at 0x7ff764ee85e0>, 'show\_base': <function Base.show\_base at 0x7ff764ee8670>, 'make\_base': <staticmethod object at 0x7ff764eebfd0>, '\_\_dict\_\_': <attribute '\_\_dict\_\_' of 'Base' objects>, '\_\_weakref\_\_': <attribute '\_\_weakref\_\_' of 'Base' objects>, '\_\_doc\_\_': None}
389
+
>> class-in-mro: <class 'object'> id: 4307454896 cls.\_\_dict\_\_: {'\_\_repr\_\_': <slot wrapper '\_\_repr\_\_' of 'object' objects>, '\_\_hash\_\_': <slot wrapper '\_\_hash\_\_' of 'object' objects>, '\_\_str\_\_': <slot wrapper '\_\_str\_\_' of 'object' objects>, '\_\_getattribute\_\_': <slot wrapper '\_\_getattribute\_\_' of 'object' objects>, '\_\_setattr\_\_': <slot wrapper '\_\_setattr\_\_' of 'object' objects>, '\_\_delattr\_\_': <slot wrapper '\_\_delattr\_\_' of 'object' objects>, '\_\_lt\_\_': <slot wrapper '\_\_lt\_\_' of 'object' objects>, '\_\_le\_\_': <slot wrapper '\_\_le\_\_' of 'object' objects>, '\_\_eq\_\_': <slot wrapper '\_\_eq\_\_' of 'object' objects>, '\_\_ne\_\_': <slot wrapper '\_\_ne\_\_' of 'object' objects>, '\_\_gt\_\_': <slot wrapper '\_\_gt\_\_' of 'object' objects>, '\_\_ge\_\_': <slot wrapper '\_\_ge\_\_' of 'object' objects>, '\_\_init\_\_': <slot wrapper '\_\_init\_\_' of 'object' objects>, '\_\_new\_\_': <built-in method \_\_new\_\_ of type object at 0x100be8bb0>, '\_\_reduce\_ex\_\_': <method '\_\_reduce\_ex\_\_' of 'object' objects>, '\_\_reduce\_\_': <method '\_\_reduce\_\_' of 'object' objects>, '\_\_subclasshook\_\_': <method '\_\_subclasshook\_\_' of 'object' objects>, '\_\_init\_subclass\_\_': <method '\_\_init\_subclass\_\_' of 'object' objects>, '\_\_format\_\_': <method '\_\_format\_\_' of 'object' objects>, '\_\_sizeof\_\_': <method '\_\_sizeof\_\_' of 'object' objects>, '\_\_dir\_\_': <method '\_\_dir\_\_' of 'object' objects>, '\_\_class\_\_': <attribute '\_\_class\_\_' of 'object' objects>, '\_\_doc\_\_': 'The base class of the class hierarchy.\n\nWhen called, it accepts no arguments and returns a new featureless\ninstance that has no instance attributes and cannot be given any.\n'}
>> inspect.getmembers(foo_obj): [('__class__', <class '__main__.Foo'>), ('__delattr__', <method-wrapper '__delattr__' of Foo object at 0x7fc9886eb2b0>), ('__dict__', {'obj_var_base': 10, 'obj_var_a': 42, 'obj_var_b': 'name'}), ('__dir__', <built-in method __dir__ of Foo object at 0x7fc9886eb2b0>), ('__doc__', None), ('__eq__', <method-wrapper '__eq__' of Foo object at 0x7fc9886eb2b0>), ('__format__', <built-in method __format__ of Foo object at 0x7fc9886eb2b0>), ('__ge__', <method-wrapper '__ge__' of Foo object at 0x7fc9886eb2b0>), ('__getattribute__', <method-wrapper '__getattribute__' of Foo object at 0x7fc9886eb2b0>), ('__gt__', <method-wrapper '__gt__' of Foo object at 0x7fc9886eb2b0>), ('__hash__', <method-wrapper '__hash__' of Foo object at 0x7fc9886eb2b0>), ('__init__', <bound method Foo.__init__ of <__main__.Foo object at 0x7fc9886eb2b0>>), ('__init_subclass__', <built-in method __init_subclass__ of type object at 0x7fc98830c3b0>), ('__le__', <method-wrapper '__le__' of Foo object at 0x7fc9886eb2b0>), ('__lt__', <method-wrapper '__lt__' of Foo object at 0x7fc9886eb2b0>), ('__module__', '__main__'), ('__ne__', <method-wrapper '__ne__' of Foo object at 0x7fc9886eb2b0>), ('__new__', <built-in method __new__ of type object at 0x100facbb0>), ('__reduce__', <built-in method __reduce__ of Foo object at 0x7fc9886eb2b0>), ('__reduce_ex__', <built-in method __reduce_ex__ of Foo object at 0x7fc9886eb2b0>), ('__repr__', <method-wrapper '__repr__' of Foo object at 0x7fc9886eb2b0>), ('__setattr__', <method-wrapper '__setattr__' of Foo object at 0x7fc9886eb2b0>), ('__sizeof__', <built-in method __sizeof__ of Foo object at 0x7fc9886eb2b0>), ('__str__', <method-wrapper '__str__' of Foo object at 0x7fc9886eb2b0>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x7fc98830c3b0>), ('__weakref__', None), ('base_class_var', 'Base'), ('class_var', 42), ('class_var2', 43), ('make_base', <function Base.make_base at 0x7fc9886e8700>), ('make_foo', <function Foo.make_foo at 0x7fc9886e88b0>), ('obj_var_a', 42), ('obj_var_b', 'name'), ('obj_var_base', 10), ('show_base', <bound method Base.show_base of <__main__.Foo object at 0x7fc9886eb2b0>>), ('show_derived', <bound method Foo.show_derived of <__main__.Foo object at 0x7fc9886eb2b0>>)]
456
+
>> inspect.getmembers(foo_obj): [('__class__', <class '__main__.Foo'>), ('__delattr__', <method-wrapper '__delattr__' of Foo object at 0x7ff764eeb2b0>), ('__dict__', {'obj_var_base': 10, 'obj_var_a': 42, 'obj_var_b': 'name'}), ('__dir__', <built-in method __dir__ of Foo object at 0x7ff764eeb2b0>), ('__doc__', None), ('__eq__', <method-wrapper '__eq__' of Foo object at 0x7ff764eeb2b0>), ('__format__', <built-in method __format__ of Foo object at 0x7ff764eeb2b0>), ('__ge__', <method-wrapper '__ge__' of Foo object at 0x7ff764eeb2b0>), ('__getattribute__', <method-wrapper '__getattribute__' of Foo object at 0x7ff764eeb2b0>), ('__gt__', <method-wrapper '__gt__' of Foo object at 0x7ff764eeb2b0>), ('__hash__', <method-wrapper '__hash__' of Foo object at 0x7ff764eeb2b0>), ('__init__', <bound method Foo.__init__ of <__main__.Foo object at 0x7ff764eeb2b0>>), ('__init_subclass__', <built-in method __init_subclass__ of type object at 0x7ff764c157c0>), ('__le__', <method-wrapper '__le__' of Foo object at 0x7ff764eeb2b0>), ('__lt__', <method-wrapper '__lt__' of Foo object at 0x7ff764eeb2b0>), ('__module__', '__main__'), ('__ne__', <method-wrapper '__ne__' of Foo object at 0x7ff764eeb2b0>), ('__new__', <built-in method __new__ of type object at 0x100be8bb0>), ('__reduce__', <built-in method __reduce__ of Foo object at 0x7ff764eeb2b0>), ('__reduce_ex__', <built-in method __reduce_ex__ of Foo object at 0x7ff764eeb2b0>), ('__repr__', <method-wrapper '__repr__' of Foo object at 0x7ff764eeb2b0>), ('__setattr__', <method-wrapper '__setattr__' of Foo object at 0x7ff764eeb2b0>), ('__sizeof__', <built-in method __sizeof__ of Foo object at 0x7ff764eeb2b0>), ('__str__', <method-wrapper '__str__' of Foo object at 0x7ff764eeb2b0>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x7ff764c157c0>), ('__weakref__', None), ('base_class_var', 'Base'), ('class_var', 42), ('class_var2', 43), ('make_base', <function Base.make_base at 0x7ff764ee8700>), ('make_foo', <function Foo.make_foo at 0x7ff764ee88b0>), ('obj_var_a', 42), ('obj_var_b', 'name'), ('obj_var_base', 10), ('show_base', <bound method Base.show_base of <__main__.Foo object at 0x7ff764eeb2b0>>), ('show_derived', <bound method Foo.show_derived of <__main__.Foo object at 0x7ff764eeb2b0>>)]
0 commit comments