Intro to Python, Chapter 7 – Imports and Nesting


Baldric had been a town guard for years, breaking up fights and catching thieves and helping the elderly cross the street. When the Empire arose and moved him to HR, he dragged prisoners to staff meetings and hauled corpses away without thinking much of it. Law and order was better than letting those rebels Management was always warning of run amok. He had a strange dream or two, but who didn’t now and then? And when one day he was called into his Manager’s office and strange patterned threads shot at him from his boss’ hands, he blacked out wondering if this was what promotions felt like.

***

Baldric had lived a quiet life as a blacksmith, supplying the local citizenry and outlying farms with tools. When the Empire took over and forced him to make weapons and armor instead, he didn’t mind. And when one day he woke up after an odd dream and found he could conjure and manipulate invisible green threads of 1’s and 0’s, he simply pretended it wasn’t happening and went on with his work. Seeing a poster about a captured rebel tickled something in the back of his mind, but he simply spit in disgust and went on his way. And when Management finally visited Baldric in the night and he felt his life force draining away, he faded out glad that he had gotten to the finish line while abiding by all applicable rules and regulations.

***

Baldric had been mining since he was a boy. But one day he saw a battle just outside the mine between the newly rising Empire and a ragtag bunch of rebels, and he convinced the rest of the mining crew to join up with the rebellion. From raiding outposts to ambushing patrols they stirred up as much chaos as they could, even managing to temporarily slow the Empire’s ascension. But when they were eventually captured and executed, the thought occurred to Baldric, as he was being tossed in a wagon during his final moments of consciousness, that somehow things weren’t supposed to have turned out this way.

***

Baldric lived life after life, experiencing every imaginable iteration, always starting out as an orphan in the city and often learning to use Magic, Logic in particular. Sometimes he became an infamous rebel leader, feared by even the Emperor himself. Sometimes he lived out his life as a farmer, hearing only rumors of happenings in the city. Always though, a shadow eventually fell over the realm, and Baldric died shortly after.

In many lives he was a clerk. In some he met a rebel named Cassandra, and was drawn into a quest to bring down the Empire. Sometimes he took a wrong turn in a labyrinth and was torn apart by demons. Sometimes he was eaten by the HR Manager, or pierced by arrows, or knocked into a lake of lava. In one, however, he eventually found himself in front of a door, a heavy stone door with odd green inscriptions. And when the Door opened he glimpsed a pulsing red crystal and a giant man whose face he could only describe as wisdom itself. There was a decision to be made, about whether or not to…

Baldric abruptly came to. He was floating bodiless through space and slowly began to remember his actual life.

“Yes, I’m a clerk. And Cassandra, and the HR Manager, and…the Teleportation Circle! I unlocked it…didn’t I?”

Baldric became aware of a presence, one that reminded him of the being he had glimpsed in the chamber beyond the Door. The presence was all around him and had the feeling of deep calm and understanding. He also noticed faint points of green light in the blackness. They were everywhere, all mysteriously twinkling in the void.

A voice entered Baldric’s thoughts. It wasn’t so much a voice as it was a stream of colors and concepts, emotions and imagery, but if it could be said to have spoken, it said something like: “Welcome Baldric Hightower, Aspiring Wizard. I have wished to speak with you directly for some time now.”

This mysterious voice had a vaguely feminine quality to it. Lacking a head with which to speak, Baldric thought, “What’s going on here? Who are you?”

The voice spoke up again, “You have grown strong, but precious little time remains, and you are still not strong enough for what lies ahead. Listen closely as I teach what you must know.”

“Listen, I really appreciate it, but I’m a little busy at the moment. Why don’t we reschedule for…”

“First, you must learn of the many of worlds all around you, miniature dimensions which are comprised of pure Logic that you may draw upon and magnify your powers with. And second, you must learn of the infinite depths and complexity of which your very own Logic can plumb. Let us begin.”

Suddenly Baldric was hurtling through space toward one of those green star-like entities that dotted the void.

“Consider how powerful you felt once you learned how to use functions, once you could bundle up as much Logic as you desired into a single entity and effortlessly call it at will. Or how remember how convenient it was to use built-in functions without ever having to write them yourself. Well then, imagine being able to draw upon not just a pre-made function or two, but pre-made anything. Any Logic imaginable. This is the power of import-ing.”

Baldric’s flight through space slowed as he approached the star. He could see it was in fact a sort of translucent orb with the word math printed on its surface. Within the orb floated a collection of Logic, already woven, just begging to be used. He thought he saw lots of functions and maybe a few floats in there. He tried to access the Logic and test it out, but the orb wasn’t allowing his own Logic to penetrate inside.

“Wizards such as yourself have long woven Logical constructs, sometimes worlds of Logic unto themselves, that they have been willing to share with others. To that end, they bundle up their Logic in tiny dimensions for safe keeping, dimensions which are only accessible to other Logic users. Behold…”

# use import statements to access modules
>>> import math

>>> math.pi
3.141592653589793

Baldric saw a tunnel-like weave of Logic materialize and bore through the math orb. It extracted something called pi and printed it out, revealing it to be a float.

“One may simply use an import statement to tap into the math dimension (or “module” as it’s sometimes called). To peer inside and see what the module holds, you may use dir(), and to see more detailed descriptions of the objects within, you may use help().”

>>> dir(math)
['__doc__', '__file__', '__loader__', '__name__', '__package__', 
'__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 
'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 
'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 
'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 
'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 
'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 
'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

>>> help(math)
# try this yourself to see the lengthy output

“Using dir(), you can see that the module contains something called pi. Calling help() and looking near the bottom of the output in the “DATA” section, we see that pi is in fact a float equal to 3.141592653589793. Note that to use objects from modules you must follow the module_name.object_name syntax, as you saw with math.pi.”

“In addition to mathematical constants, you will find that math also contains something much more powerful: functions. If you look back at the output from help(), you’ll see that functions comprise most of the math module.”

# the math module has a factorial function
# recall that factorials are often notated with an exclamation point
# for example 4! = 4 x 3 x 2 x 1 = 24
>>> math.factorial(4)
24

# there's also a function for calculating square roots
>>> math.sqrt(2)
1.4142135623730951

“If at some point you become knowledgeable enough to travel to different universes, modules such as math will still be accessible to you. If you happen to travel to different multiverses, math will also be available to you, though some of the mathematical constants may change. But if you travel to a different supermultiverse, which I don’t recommend, then it becomes difficult to say what might happen.”

“There are many other functions you may explore if you wish. Sometimes you may find that neither dir() nor help() are sufficiently enlightening. In such a case, try praying to the gods, particularly the ones known as Google or DuckDuckGo.”

“Let us briefly examine a second module you might find useful: string.”

Baldric was flung through space once again, soon arriving at a second Logic-containing orb with string written across it.

>>> import string

>>> dir(string)
['Formatter', 'Template', '_ChainMap', '_TemplateMetaclass', 
'__all__', '__builtins__', '__cached__', '__doc__', '__file__', 
'__loader__', '__name__', '__package__', '__spec__', '_re', 
'_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 
'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 
'punctuation', 'whitespace']

>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

“Again, using dir() you can see that the module contains something called ascii_letters, which help() describes as “a string containing all ASCII letters”. And printing it out, we see that ascii_letters is in fact a string containing every upper and lower case letter. So if you were ever in need of such a string, instead of laboriously typing the whole string out, you could quickly import it from the string module.”

“Wherever you are in the Multiverse, you may call upon these and other modules. Know however that with your current powers you can only access the “standard” modules. There are an incredible number of more distant and powerful modules, but those are a subject for another time.”

Baldric spoke up. “Why are you showing me these things? Are you an enemy of the Empire too? Why would you care about me, or about any of this?”

“Unfortunately the Emperor’s ambitions do not stop at wanting to enslave the realm, Baldric. You may think this fantastical, but already your city is changing, mirroring the Emperor’s own darkness. Soon your entire plane will fall under his shadow, and eventually it will consume not just your world, but all possible worlds, for the Emperor plans to do nothing short of enslaving the Great Serpent itself and reweaving the fundamental patterns of reality in his own image.”

“How could the Emperor possibly accomplish this, you ask? It appears he has found a crystal of great power, a power that even I do not fully comprehend. And the Emperor has used this crystal to capture my other half, infect his mind with dark energy and use it to alter the nature of reality as you might a dream of your own making. However, if you can somehow manage to open the Door, disrupt this power source and defeat the Emperor, you will have saved all of creation. I attempted to aid many other heroes in this quest, but I fear I ended up only leading them to their doom, or worse. Only you remain Baldric. You are our final hope. Ah, and it seems your ride is here.”

Baldric looked away from the modules to see a gargantuan flaming bird-like entity descending upon him. It was like some brilliant multi-colored avian sun diving through the void. It flew overhead and scooped Baldric’s being up in its claws. The blackness of the void gave way to colors and light as Baldric and his transport zoomed into a psychedelic tunnel that carried them through the cosmos. Eventually the swirling colors began to take shape, forming into places, into worlds that flew by which Baldric had never before seen or imagined. Baldric watched in awe as planets flourished in nature, then died in Magical armageddon. Entirely alien civilizations rose and fell. Universes were born, then died, then born again.

Eventually Baldric’s phoenix-like transport flew directly into a world covered with trees, though not any that Baldric recognized. The bird flew low over the treetops and let go of him. Cursing the fact that he just now apparently regained his bodily form, Baldric plummeted through the trees but landed comfortably enough in a large bird’s nest. Looking around he saw that within the nest were many other nests. Some nests were just in the main nest, and still quite large. Other nests were inside these sub-nests, while still other nests were inside sub-sub-nests. In many cases, multiple nests of the same size were together in one nest. Nests always had smaller and smaller nests in them unless they contained an egg, in which case the nesting stopped.

“What an odd nest,” Baldric thought to himself. “There must be thousands of eggs here, or more, of all sizes.”

The voice spoke again. “Now you shall learn of just how deep your Logic can flow. Recall how conditional statements work, such as the following.”

if condition1:
    print("do something")
else:
    print("do something else")

“This structure can be extended indefinitely. Here’s an example with two levels of branching.”

if condition1:
    if condition2:
        print("conditions 1 and 2 are true, do something")
    else:
        print("just condition 1 is true, do something else")
else:
    print("condition 1 was false, let's call it quits")

“To each if/else branch, you may add more branches. Try adding more branches and see how many levels you can keep track of in your head. You will find that the complexity quickly gets out of hand, which is why it’s advisable to keep your nesting to a minimum. But the capability is there should you ever require it.”

Baldric stopped to think for a moment. “Interesting. It makes sense to think of nested conditionals as a tree of sorts, because it branches out into continually more specific options. But based on the Logic’s appearance and structure, it also makes sense to think of them like a series of nests, getting smaller and smaller within each other.”

The voice spoke up again. “for loops are much the same. Here’s a single level example.”

for i in range(5):
    print(i)
0
1
2
3
4

And here’s a for loop nested in another for loop.

for i in range(5):
    for j in range(3):
        print(i, j)
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
3 0
3 1
3 2
4 0
4 1
4 2

“Naturally, conditionals and for loops can be mixed together and nested within each other.”

for i in range(5):
    if i >= 2:
        for j in range(5):
            if j % 2 == 0:
                print(i, j)
2 0
2 2
2 4
3 0
3 2
3 4
4 0
4 2
4 4

“But again, be wary of the complexity of such nested structures. Good Logic is often simple, readable Logic.”

“Now, let’s see if you’ve grasped the concept of nesting. Using the math module’s hypot() function, find all the pairs of positive whole numbers under 50 that result in a whole number hypotenuse (e.g. math.hypot(3, 4) results in 5).”

import math

for i in range(1, 50):
    for j in range(i, 50):
        h = math.hypot(i, j)
        if h == int(h):
            s = 'A triangle with sides {} and {} has a hypotenuse of {}'
            answer = s.format(i, j, int(h))
            print(answer)
A triangle with sides 3 and 4 has a hypotenuse of 5
A triangle with sides 5 and 12 has a hypotenuse of 13
A triangle with sides 6 and 8 has a hypotenuse of 10
A triangle with sides 7 and 24 has a hypotenuse of 25
A triangle with sides 8 and 15 has a hypotenuse of 17
A triangle with sides 9 and 12 has a hypotenuse of 15
A triangle with sides 9 and 40 has a hypotenuse of 41
A triangle with sides 10 and 24 has a hypotenuse of 26
A triangle with sides 12 and 16 has a hypotenuse of 20
A triangle with sides 12 and 35 has a hypotenuse of 37
A triangle with sides 14 and 48 has a hypotenuse of 50
A triangle with sides 15 and 20 has a hypotenuse of 25
A triangle with sides 15 and 36 has a hypotenuse of 39
A triangle with sides 16 and 30 has a hypotenuse of 34
A triangle with sides 18 and 24 has a hypotenuse of 30
A triangle with sides 20 and 21 has a hypotenuse of 29
A triangle with sides 20 and 48 has a hypotenuse of 52
A triangle with sides 21 and 28 has a hypotenuse of 35
A triangle with sides 24 and 32 has a hypotenuse of 40
A triangle with sides 24 and 45 has a hypotenuse of 51
A triangle with sides 27 and 36 has a hypotenuse of 45
A triangle with sides 28 and 45 has a hypotenuse of 53
A triangle with sides 30 and 40 has a hypotenuse of 50
A triangle with sides 33 and 44 has a hypotenuse of 55
A triangle with sides 36 and 48 has a hypotenuse of 60
A triangle with sides 40 and 42 has a hypotenuse of 58

Baldric printed out the answers (in nicely formatted style) and heard a faint crackling. Looking down, he saw a large egg near him shaking and breaking open. The egg shell fell away to reveal a painted wooden doll of sorts. It was very round and painted in the likeness of a dwarf. It was also split across the middle, as if it might come apart.

The voice boomed again. “You are a remarkably quick learner. Know this as well: one may also define functions inside of other functions.”

def f1():
    print('knock knock')
    
    def f2():
        print("who's there?")
    
    f2()

f1()
knock knock
who's there?

He picked up the doll and pulled it apart to reveal a similar but smaller doll within. Intrigued, Baldric pulled this second doll apart as well to reveal two dolls! He continued like this, opening every doll he found until all the dolls became too small for his stocky fingers to pull apart. At this point the nest around him was littered with halves of the wooden dolls, and it was then he noticed that all the rest of the many-sized eggs were shaking and cracking. He saw a hand break through one of the shells and, to Baldric’s surprise, it looked like little men were hatching from the eggs. Little dwarves, in fact.

Baldric also noticed that the dolls he had pulled apart were no longer wooden doll parts, but had become, to his horror, actual body parts. They now looked not just like dwarves, but like Baldric himself! Many differently-sized halves of him, all perfect likenesses torn in two, blood leaking from the torsos and dripping through the nest.

The live dwarves were now free of their eggs, and Baldric could see they were all him as well, but different. Town guards, blacksmiths, farmers, and a thousand other versions of Baldric were all streaming out of the eggs towards him. Along the way some swarmed over the severed Baldric corpses, feasting on the still-warm flesh, while the rest kept on coming.

The voice calmly continued. “You can even tap into the deep magic of Recursion and make a function refer to itself.”

def custom_factorial(n):
    if n == 1:
        return 1
    else:
        return n * custom_factorial(n-1)

print(custom_factorial(4))
24

He could see the eyes of the larger ones now. While their faces were scrunched up in rictus, bloodthirsty snarls, their black-and-white eyes looked empty. Those vacant gazes never blinked, and they plunged swords and teeth alike into Baldric’s feet and legs. With a cry Baldric tripped backwards and fell into several of his halves. The pseudo-Baldrics streamed over him, biting and stabbing and making their way to his head.

“But be warned, it is powerful stuff. Use Recursion inappropriately, and it can even bring the world crashing down around you.”

def the_emperor_shall_fall(answer):
  print("It's " + str(answer) + " that the Emperor shall fall")
  return the_emperor_shall_fall(not answer)

the_emperor_shall_fall(True)
It's True that the Emperor shall fall
It's False that the Emperor shall fall
It's True that the Emperor shall fall
It's False that the Emperor shall fall
.
.
.
It's True that the Emperor shall fall
It's False that the Emperor shall fall
It's True that the Emperor shall fall
It's False that the Emperor shall fall
Traceback (most recent call last):
  File "python", line 5, in <module>
  File "python", line 3, in the_emperor_shall_fall
  File "python", line 3, in the_emperor_shall_fall
  File "python", line 3, in the_emperor_shall_fall
  [Previous line repeated 983 more times]
  File "python", line 2, in the_emperor_shall_fall
RecursionError: maximum recursion depth exceeded in comparison

As the Baldrics swarmed him, the nest filled with messages alternating between possibilities of the Emperor’s fate. The function went deeper and deeper, continually calling itself until the world began to slow and almost freeze entirely. One mini-Baldric was on the real one’s face in the act of plunging a spear in his eye when the spear thrust slowed, inching forward randomly only in the stuttering moments when time still advanced. The world lost it’s color and decomposed into an infinite grid of ERROR messages. Then the grid itself began to dissolve, and Baldric felt his consciousness rip to shreds.


Congratulations, you earned 4,518 experience and 3,197 gold. You are now a Level 9 Dwarven Wizard!
(cue victory music)

Here are the Python topics you covered (and may want to DuckDuckGo for further inquiry):

  • imports
  • nested conditional statements
  • nested loops
  • nested functions
  • recursion


Chapter 8 – Opening the Door >>>