Skip to content

1. Whitespaces and Newlines

Crowthebird edited this page Aug 23, 2021 · 3 revisions

This chapter is using the same representations of spaces and tabs in IFcoltransG's esoteric python guide (· for space and for tab).

Indentation and Operators

In PEP8, 4 spaces is the recommended indentation; no tabs are used as indentation; and spaces are put around operators (except for . and the unary operators). But anyways, to make esoteric code, we can choose not to do that.

Figure 1.1
if1:
↹ ↹ · ↹ ↹ · 'Hey, this works!'
· ↹ · ↹ ↹ · "But this doesn't work, because we replaced the first tab with a space"
↹ ↹ ↹ · ↹ · "This also doesn't work, because the order of spaces and tabs are switched"
Figure 1.2
while · 2:
· · · 'We can use three spaces'
· · · [
· · · · · ↹ · · · 'But in these hanging indents',
· 'We can use any indentation we want!',
· · · ↹ ↹ 'This works',
↹ · ↹ · ↹ · · 'This also does',
↹ · ↹ · ↹]
· · · if'a': # We can use absolutely no spaces at all between a keyword and a string
↹ · ↹ · ↹ · "This doesn't work, because the first three characters for indentation is a tab, a space, and a tab instead of three spaces"
· · · ↹ · ↹ · ↹ · 'But this works, because the first three characters for indentation are three spaces'
Figure 1.3
2. # There's a difference between this
2 · . # And this (this causes a `SyntaxError`); the explanation is if there's some one-line whitespace[s] between an object and a dot, the dot is 
interpreted as an attribute access operator instead
print(2 ↹ · ↹ . ↹ ↹ ↹ ↹ ↹ ↹ ↹ ↹ ↹ ↹ __class__)
<class 'int'>
print(2..__class__)
<class 'float'>

Space Places

· for space and for tab ends in this page from here
Confusing things can be made when spaces are put where they shouldn't be put. Like this example:

a = [0x_for x in (1, 2, 3)]
print(a)

Figure 1.4-1a

Output:

[15]

Figure 1.4-1b

Explanation to Figure 1.4-1

Python allows using underscores (_) to make a number more readable. With non-decimal numbers (prefixed with any of these: 0x, 0o, 0b), an underscore can be put after the number prefix, but a valid digit according to the number prefix has to be put after the underscore. This tells us that Python checks only for digits at the right side of an underscore. Figure 1.4-1a is therefore interpreted instead as:

a = [(0xf) or (x in (1, 2, 3))] # The hexadecimal number `0xf` is the same thing as the decimal number `15`
print(a)

Figure 1.4-2

Boolean short-circuiting (will be expanded in another chapter) results in only 0x_f (0xf or 15) being evaluated, so it doesn't matter whether x is defined or not.


Also confusing is the 'pistol operator' to assign the first and only element of a one-element list to a variable:

>>> list_obj = [42]
>>> the_meaning_of_life ,= list_obj
>>> the_meaning_of_life
42

Figure 1.5-1

Explanation to Figure 1.5-1

Python allows sortable ordered iterables as left operands for unpacking assignments, examples:

>>> (a, b) = [1, 2]
>>> a
1
>>> b
2
>>> [a, b] = [3, 4]
>>> a
3
>>> b
4

Figure 1.5-2.1a

>>> (a,) = 1
>>> a
1
>>> [a,] = 2
>>> a
2

Figure 1.5-2.1b

Comma-separated assignment—

a, b, c, d = 1, 2, 3, 4

Figure 1.5-2.2a

—just translates to—

(a, b, c, d) = 1, 2, 3, 4

Figure 1.5-2.2b

—so, Figure 1.5-1 is interpreted as:

>>> list_obj = [42]
>>> (the_meaning_of_life,) = list_obj
>>> the_meaning_of_life
42

Figure 1.5-2.3



Semicolons

Newlines can be replaced by semicolons (;), as in this code example:

print('a');print('b');True

Figure 1.6

But beware, scoping keywords (atleast that's what I call them, e.g. while, if, elif, else, for, def, and class) cannot come after a semicolon:

print('Not valid');while True:

Figure 1.7a

  File "<stdin>", line 1
    print('Not valid');while True:
                       ^^^^^
SyntaxError: invalid syntax

Figure 1.7b

While some, like import and from, are allowed:

>>> print('A');import math;from random import randint
A
>>> math
<module 'math' (built-in)>
>>> randint
<bound method Random.randint of <random.Random object at [hex address]>>

Figure 1.8

If you only have one level of indent within a block, you can use semicolons instead of newlines and indents. Note that any statement separated by semicolons in a one-line scope is part of the same scope.

>>> n = 5
>>> if n%4:print('Not a',end=' ');print('leap year')
Not a leap year
>>> 

Figure 1.9

Clone this wiki locally