# float posts, scopes, is warning

    

index dda8c71..149978e 100644
@@ -76,9 +76,13 @@ More:
1. ./tau.md                     (24 December 2020, 18:00)
1. ./str-append.md              (29 December 2020, 18:00)
1. ./new-year.md                (31 December 2020, 18:00)
+1. ./scopes.md
1. ./str-concat.md
1. ./bytearray.md
1. ./join-lists.md
+1. ./is-warning.md
+1. ./float.md
+1. ./inf.md

Out of order:

diff --git a/pythonetc/float.md b/pythonetc/float.md
new file mode 100644
index 0000000..757759c
--- /dev/null
+++ b/pythonetc/float.md
@@ -0,0 +1,50 @@
+[Floating point numbers](https://en.wikipedia.org/wiki/Floating-point_arithmetic) in Python and most of the modern languages are implemented according to [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754). The most interesting and hradcore part is "arithmetic formats" which defines a few special values:
+
++ inf and -inf representing infinity.
++ nan representing a special "Not a Number" value.
++ -0.0 representing "negative zero"
+
+Negative zero is the easiest case, for all operations it considered to be the same as the positive zero:
+
+python
+-.0 == .0  # True
+-.0 < .0   # False
+
+
+Nan returns False for all comparison operations (except !=) including comparison with inf:
+
+python
+import math
+
+math.nan < 10        # False
+math.nan > 10        # False
+math.nan < math.inf  # False
+math.nan > math.inf  # False
+math.nan == math.nan # False
+math.nan != 10       # True
+
+
+And all binary operations on nan return nan:
+
+python
+math.nan + 10  # nan
+1 / math.nan   # nan
+
+
+
++ https://t.me/pythonetc/561
++ https://t.me/pythonetc/597
+
+Infinity is bigger than anything else (except nan). However, unlike in pure math, infinity is equal to infinity:
+
+python
+10 < math.inf         # True
+math.inf == math.inf  # True
+
+
+Sum of positive an negative infinity is nan:
+
+python
+-math.inf + math.inf  # nan
+
diff --git a/pythonetc/inf.md b/pythonetc/inf.md
new file mode 100644
index 0000000..0a898c2
--- /dev/null
+++ b/pythonetc/inf.md
@@ -0,0 +1,41 @@
+Infinity has an interesting behavior on division operations. Some of them are expected, some of them are surprising. Without further talking, there is a table:
+
+python
+truediv (/)
+     |   -8 |    8 | -inf |  inf
+  -8 |  1.0 | -1.0 |  0.0 | -0.0
+   8 | -1.0 |  1.0 | -0.0 |  0.0
+-inf |  inf | -inf |  nan |  nan
+ inf | -inf |  inf |  nan |  nan
+
+floordiv (//)
+     |   -8 |    8 | -inf |  inf
+  -8 |    1 |   -1 |  0.0 | -1.0
+   8 |   -1 |    1 | -1.0 |  0.0
+-inf |  nan |  nan |  nan |  nan
+ inf |  nan |  nan |  nan |  nan
+
+mod (%)
+     |   -8 |    8 | -inf |  inf
+  -8 |    0 |    0 | -8.0 |  inf
+   8 |    0 |    0 | -inf |  8.0
+-inf |  nan |  nan |  nan |  nan
+ inf |  nan |  nan |  nan |  nan
+
+
+The code used to generate the table:
+
+python
+import operator
+cases = (-8, 8, float('-inf'), float('inf'))
+ops = (operator.truediv, operator.floordiv, operator.mod)
+for op in ops:
+  print(op.__name__)
+  row = ['{:4}'.format(x) for x in cases]
+  print(' ' * 6, ' | '.join(row))
+  for x in cases:
+    row = ['{:4}'.format(x)]
+    for y in cases:
+      row.append('{:4}'.format(op(x, y)))
+    print(' | '.join(row))
+
diff --git a/pythonetc/is-warning.md b/pythonetc/is-warning.md
new file mode 100644
index 0000000..48abd70
--- /dev/null
+++ b/pythonetc/is-warning.md
@@ -0,0 +1,29 @@
+Starting Python 3.8, interpreter started to warn about is comparison of literals.
+
+Python 3.7:
+
+python
+>>> 0 is 0
+True
+
+
+Python 3.8:
+
+python
+>>> 0 is 0
+:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
+True
+
+
+The reason is that it is a famous gotcha. == is used to use values comparison (which is implemented by calling __eq__ magic method, in a nutshell) while is compares memory addresses of objects. While it holds true for ints from -5 to 256, it won't work for ints out of this range or object of other types:
+
+python
+a = -5
+a is -5   # True
+a = -6
+a is -6   # False
+a = 256
+a is 256  # True
+a = 257
+a is 257  # False
+
diff --git a/pythonetc/scopes.md b/pythonetc/scopes.md
new file mode 100644
index 0000000..07eee59
--- /dev/null
+++ b/pythonetc/scopes.md
@@ -0,0 +1,43 @@
+So, let's talk a bit more about scopes.
+
+Any class and function can implicitly use variables from the global scope:
+
+python
+v = 'global'
+def f():
+  print(f'{v=}')
+f()
+# v='global'
+
+
+Or from any other enclosing scope, even if it is defined after the fucntion definition:
+
+python
+def f():
+  v1 = 'local1'
+  def f2():
+    def f3():
+      print(f'{v1=}')
+      print(f'{v2=}')
+    v2 = 'local2'
+    f3()
+  f2()
+f()
+# v1='local1'
+# v2='local2'
+
+
+Class body is a tricky case. It is not considered an enclosing scope for functions defined inside of it:
+
+python
+v = 'global'
+class A:
+  v = 'local'
+  print(f'A {v=}')
+  def f():
+    print(f'f {v=}')
+# A v='local'
+
+A.f()
+# f v='global'
+