From 7df49cd8184956023ca18db6d840f721bc1371d6 Mon Sep 17 00:00:00 2001 From: Satwik Date: Thu, 31 Oct 2019 00:51:48 +0530 Subject: [PATCH] Change section name to Slippery Slopes and modify nan-reflexivity example --- README.md | 116 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index bfbd48d..c80f3ff 100644 --- a/README.md +++ b/README.md @@ -1452,7 +1452,82 @@ def some_func(val): --- +### ▶ Nan-reflexivity + + + +1\. + +```py +a = float('inf') +b = float('nan') +c = float('-iNf') # These strings are case-insensitive +d = float('nan') +``` + +**Output:** + +```py +>>> a +inf +>>> b +nan +>>> c +-inf +>>> float('some_other_string') +ValueError: could not convert string to float: some_other_string +>>> a == -c # inf==inf +True +>>> None == None # None == None +True +>>> b == d # but nan!=nan +False +>>> 50 / a +0.0 +>>> a / a +nan +>>> 23 + b +nan +``` + +2\. + +```py +>>> x = float('nan') +>>> y = x / x +>>> y is y # identity holds +True +>>> y == y # equality fails of y +False +>>> [y] == [y] # but the equality succeeds for the list containing y +True +``` + + + +#### 💡 Explanation: + +- `'inf'` and `'nan'` are special strings (case-insensitive), which when explicitly typecast-ed to `float` type, are used to represent mathematical "infinity" and "not a number" respectively. + +- Since according to standards ` NaN != NaN`, implementing this breaks the reflexivity assumption of a collection element in Python i.e if `x` is a part of collection like `list`, the implementations like comparison are based on the assumption that `x == x`. Because of this assumption, the identity is compared first (since it's faster) whlie comparing two elements, and the values are compared only when the identities mismatch. Following snippet will make things clearer + + ```py + >>> x = float('nan') + >>> x == x, [x] == [x] + (False, True) + >>> y = float('nan') + >>> y == y, [y] == [y] + (False, True) + >>> x == y, [x] == [y] + (False, False) + ``` + + Since the identities of `x` and `y` are different, the values are considered, which are also different, hence the comparison returns `False` this time. + +--- + ### ▶ Mutating the immutable! + This might seem trivial if you know how references works in Python. @@ -1934,7 +2009,7 @@ Shouldn't that be 100? --- -## Section: Watch out for the landmines! +## Section: Slippery Slopes ### ▶ Modifying a dictionary while iterating over it @@ -2575,8 +2650,6 @@ def similar_recursive_func(a): 4 ``` - - #### 💡 Explanation: * For 1, the correct statement for expected behavior is `x, y = (0, 1) if True else (None, None)`. @@ -3238,44 +3311,7 @@ Let's increase the number of iterations by a factor of 10. > There should be one-- and preferably only one --obvious way to do it. ---- -### ▶ Explicit typecast of strings - -```py -a = float('inf') -b = float('nan') -c = float('-iNf') #These strings are case-insensitive -d = float('nan') -``` - -**Output:** -```py ->>> a -inf ->>> b -nan ->>> c --inf ->>> float('some_other_string') -ValueError: could not convert string to float: some_other_string ->>> a == -c #inf==inf -True ->>> None == None # None==None -True ->>> b == d #but nan!=nan -False ->>> 50/a -0.0 ->>> a/a -nan ->>> 23 + b -nan -``` - -#### 💡 Explanation: - -`'inf'` and `'nan'` are special strings (case-insensitive), which when explicitly typecast-ed to `float` type, are used to represent mathematical "infinity" and "not a number" respectively. ---