summaryrefslogtreecommitdiffhomepage
path: root/python.html.markdown
diff options
context:
space:
mode:
Diffstat (limited to 'python.html.markdown')
-rw-r--r--python.html.markdown84
1 files changed, 61 insertions, 23 deletions
diff --git a/python.html.markdown b/python.html.markdown
index d9eda60c..326ddb95 100644
--- a/python.html.markdown
+++ b/python.html.markdown
@@ -685,8 +685,8 @@ print(math.sqrt(16)) # => 4.0
# You can get specific functions from a module
from math import ceil, floor
-print(ceil(3.7)) # => 4.0
-print(floor(3.7)) # => 3.0
+print(ceil(3.7)) # => 4
+print(floor(3.7)) # => 3
# You can import all functions from a module.
# Warning: this is not recommended
@@ -733,7 +733,9 @@ class Human:
self.name = name
# Initialize property
- self._age = 0
+ self._age = 0 # the leading underscore indicates the "age" property is
+ # intended to be used internally
+ # do not rely on this to be enforced: it's a hint to other devs
# An instance method. All methods take "self" as the first argument
def say(self, msg):
@@ -876,7 +878,8 @@ if __name__ == '__main__':
if type(sup) is Superhero:
print('I am a superhero')
- # Get the Method Resolution search Order used by both getattr() and super()
+ # Get the "Method Resolution Order" used by both getattr() and super()
+ # (the order in which classes are searched for an attribute or method)
# This attribute is dynamic and can be updated
print(Superhero.__mro__) # => (<class '__main__.Superhero'>,
# => <class 'human.Human'>, <class 'object'>)
@@ -958,8 +961,7 @@ class Batman(Superhero, Bat):
if __name__ == '__main__':
sup = Batman()
- # Get the Method Resolution search Order used by both getattr() and super().
- # This attribute is dynamic and can be updated
+ # The Method Resolution Order
print(Batman.__mro__) # => (<class '__main__.Batman'>,
# => <class 'superhero.Superhero'>,
# => <class 'human.Human'>,
@@ -1016,31 +1018,67 @@ gen_to_list = list(values)
print(gen_to_list) # => [-1, -2, -3, -4, -5]
-# Decorators
-# In this example `beg` wraps `say`. If say_please is True then it
-# will change the returned message.
-from functools import wraps
+# Decorators are a form of syntactic sugar.
+# They make code easier to read while accomplishing clunky syntax.
+# Wrappers are one type of decorator.
+# They're really useful for adding logging to existing functions without needing to modify them.
-def beg(target_function):
- @wraps(target_function)
+def log_function(func):
def wrapper(*args, **kwargs):
- msg, say_please = target_function(*args, **kwargs)
- if say_please:
- return "{} {}".format(msg, "Please! I am poor :(")
- return msg
-
+ print("Entering function", func.__name__)
+ result = func(*args, **kwargs)
+ print("Exiting function", func.__name__)
+ return result
return wrapper
+@log_function # equivalent:
+def my_function(x,y): # def my_function(x,y):
+ return x+y # return x+y
+ # my_function = log_function(my_function)
+# The decorator @log_function tells us as we begin reading the function definition
+# for my_function that this function will be wrapped with log_function.
+# When function definitions are long, it can be hard to parse the non-decorated
+# assignment at the end of the definition.
+
+my_function(1,2) # => "Entering function my_function"
+ # => "3"
+ # => "Exiting function my_function"
+
+# But there's a problem.
+# What happens if we try to get some information about my_function?
+
+print(my_function.__name__) # => 'wrapper'
+print(my_function.__code__.co_argcount) # => 0. The argcount is 0 because both arguments in wrapper()'s signature are optional.
+
+# Because our decorator is equivalent to my_function = log_function(my_function)
+# we've replaced information about my_function with information from wrapper
+
+# Fix this using functools
+
+from functools import wraps
+
+def log_function(func):
+ @wraps(func) # this ensures docstring, function name, arguments list, etc. are all copied
+ # to the wrapped function - instead of being replaced with wrapper's info
+ def wrapper(*args, **kwargs):
+ print("Entering function", func.__name__)
+ result = func(*args, **kwargs)
+ print("Exiting function", func.__name__)
+ return result
+ return wrapper
-@beg
-def say(say_please=False):
- msg = "Can you buy me a beer?"
- return msg, say_please
+@log_function
+def my_function(x,y):
+ return x+y
+
+my_function(1,2) # => "Entering function my_function"
+ # => "3"
+ # => "Exiting function my_function"
+print(my_function.__name__) # => 'my_function'
+print(my_function.__code__.co_argcount) # => 2
-print(say()) # Can you buy me a beer?
-print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
```
### Free Online