— python, learning — 3 min read
When we build programs sometimes they get big. The same way we split little pieces of logic with Methods, Functions and Classes we might want to start segregating our code in multiple files, for many reasons, the most common one is to reuse a piece of code that we already wrote. Let's see how all that works.
When we writing the first few programs in earlier posts, we created
a file named like cat.py
and then keep appending more code at the end
of the file.
Let's try to use our file in another program!
Create a new file by opening a terminal and type:
1$ touch main.py
Note: Whenever you see $ at the beginning of commands it means it should be typed in your terminal.
Now let's add the following content to our file:
1import cat
Now let's run our new script:
1$ python main.py2ฅ^•ﻌ•^ฅ Meoooooooow3ฅ^•ﻌ•^ฅ Meow4ฅ^•ﻌ•^ฅ Meoooow5
6ฅ^•ﻌ•^ฅ Meooooow7ฅ^•ﻌ•^ฅ Meoow8ฅ^•ﻌ•^ฅ Meoooooooooow9
10a == b Not the same Cat!11
12a == a Same Cat13
14b == b Same Cat15
16a == b It's not the same cat!17
18a == a It's the same cat!
What we're seeing is the output of cat.py
. Why is that? When we use other imports
we usually don't get this kind of output!
When Python reads our file it starts "interpreting" our statements from top to bottom, line by line. Therefore adding the following line:
1import module_name
Acts as a copying and pasting cat.py
in our main.py
at the top of the file.
Rad. Except when it's not. Most of the time, what we want to do when reusing code this way is to import the definitions. In our example above we want to get just the Cat definition, but we don't want to execute all those meows.
To do that, we need to go back to the original cat.py
and make a few adjustments:
1class Cat:2 def __init__(self,3 oos_when_hungry,4 oos_when_playful,5 oos_when_open_door):6 self.oos_when_hungry = oos_when_hungry7 self.oos_when_playful = oos_when_playful8 self.oos_when_open_door = oos_when_open_door9
10 @staticmethod11 def meow(number_of_os):12 print("ฅ^•ﻌ•^ฅ Me" + "o" * number_of_os + "w")13
14 def open_the_door(self):15 Cat.meow(self.oos_when_open_door)16
17 def hungry(self):18 Cat.meow(self.oos_when_hungry)19
20 def i_wanna_play(self):21 Cat.meow(self.oos_when_playful)22
23 def equals(self, other_cat):24 if self.oos_when_hungry == other_cat.oos_when_hungry and \25 self.oos_when_playful == other_cat.oos_when_playful and \26 self.oos_when_open_door == other_cat.oos_when_open_door:27 return True28 else:29 return False30
31 def __equals__(self, other_cat):32 return self.equals(other_cat)33
34
35# Let me tell you about my girly kitty's morning36a = Cat(1, 4, 8)37a.open_the_door()38a.hungry()39a.i_wanna_play()40
41print() # Let's add some space for readability. This line has nothing to do with the cats.42
43# Let me tell you about my big macho kitty44b = Cat(2, 10, 5)45b.open_the_door()46b.hungry()47b.i_wanna_play()48
49print() # Let's add some space for readability. This line has nothing to do with the cats.50
51if a.equals(b):52 print("a == b Same Cat")53else:54 print("a == b Not the same Cat!")55
56print() # Let's add some space for readability. This line has nothing to do with the cats.57
58if a.equals(a):59 print("a == a Same Cat")60else:61 print("a == a Not the same Cat!")62
63print() # Let's add some space for readability. This line has nothing to do with the cats.64
65if b.equals(b):66 print("b == b Same Cat")67else:68 print("b == b Not the same Cat!")69
70print() # Let's add some space for readability. This line has nothing to do with the cats.71
72if a == b:73 print("a == b It's the same cat!")74else:75 print("a == b It's not the same cat!")76
77print() # Let's add some space for readability. This line has nothing to do with the cats.78
79if a == a:80 print("a == a It's the same cat!")81else:82 print("a == a It's not the same cat!")
First, let's review what we mean by "definitions":
1
A definition is every time we describe the behavior of a class, a method or a function.
1
Later on, we use these definitions when we instantiate/create objects of the class or when we invoke those methods and functions.
1import cat2
3# Let me tell you about my girly kitty's morning4a = Cat(1, 4, 8)5a.open_the_door()6a.hungry()7a.i_wanna_play()8
9print() # Let's add some space for readability. This line has nothing to do with the cats.10
11# Let me tell you about my big macho kitty12b = Cat(2, 10, 5)13b.open_the_door()14b.hungry()15b.i_wanna_play()16
17print() # Let's add some space for readability. This line has nothing to do with the cats.18
19if a.equals(b):20 print("a == b Same Cat")21else:22 print("a == b Not the same Cat!")23
24print() # Let's add some space for readability. This line has nothing to do with the cats.25
26if a.equals(a):27 print("a == a Same Cat")28else:29 print("a == a Not the same Cat!")30
31print() # Let's add some space for readability. This line has nothing to do with the cats.32
33if b.equals(b):34 print("b == b Same Cat")35else:36 print("b == b Not the same Cat!")37
38print() # Let's add some space for readability. This line has nothing to do with the cats.39
40if a == b:41 print("a == b It's the same cat!")42else:43 print("a == b It's not the same cat!")44
45print() # Let's add some space for readability. This line has nothing to do with the cats.46
47if a == a:48 print("a == a It's the same cat!")49else:50 print("a == a It's not the same cat!")
We can reuse those definitions by "importing" them in our main.py
from our cat.py
module.
1import cat2
3# Let me tell you about my girly kitty's morning4a = Cat(1, 4, 8)5a.open_the_door()6a.hungry()7a.i_wanna_play()8
9print() # Let's add some space for readability. This line has nothing to do with the cats.10
11# Let me tell you about my big macho kitty12b = Cat(2, 10, 5)13b.open_the_door()14b.hungry()15b.i_wanna_play()16
17print() # Let's add some space for readability. This line has nothing to do with the cats.18
19if a.equals(b):20 print("a == b Same Cat")21else:22 print("a == b Not the same Cat!")23
24print() # Let's add some space for readability. This line has nothing to do with the cats.25
26if a.equals(a):27 print("a == a Same Cat")28else:29 print("a == a Not the same Cat!")30
31print() # Let's add some space for readability. This line has nothing to do with the cats.32
33if b.equals(b):34 print("b == b Same Cat")35else:36 print("b == b Not the same Cat!")37
38print() # Let's add some space for readability. This line has nothing to do with the cats.39
40if a == b:41 print("a == b It's the same cat!")42else:43 print("a == b It's not the same cat!")44
45print() # Let's add some space for readability. This line has nothing to do with the cats.46
47if a == a:48 print("a == a It's the same cat!")49else:50 print("a == a It's not the same cat!")
But what about those extra meows we got when we imported the cat
module the first time?
Let's go back to cat.py
for a moment.
1class Cat:2 def __init__(self,3 oos_when_hungry,4 oos_when_playful,5 oos_when_open_door):6 self.oos_when_hungry = oos_when_hungry7 self.oos_when_playful = oos_when_playful8 self.oos_when_open_door = oos_when_open_door9
10 @staticmethod11 def meow(number_of_os):12 print("ฅ^•ﻌ•^ฅ Me" + "o" * number_of_os + "w")13
14 def open_the_door(self):15 Cat.meow(self.oos_when_open_door)16
17 def hungry(self):18 Cat.meow(self.oos_when_hungry)19
20 def i_wanna_play(self):21 Cat.meow(self.oos_when_playful)22
23 def equals(self, other_cat):24 if self.oos_when_hungry == other_cat.oos_when_hungry and \25 self.oos_when_playful == other_cat.oos_when_playful and \26 self.oos_when_open_door == other_cat.oos_when_open_door:27 return True28 else:29 return False30
31 def __equals__(self, other_cat):32 return self.equals(other_cat)33
34
35# Let me tell you about my girly kitty's morning36a = Cat(1, 4, 8)37a.open_the_door()38a.hungry()39a.i_wanna_play()40
41print() # Let's add some space for readability. This line has nothing to do with the cats.42
43# Let me tell you about my big macho kitty44b = Cat(2, 10, 5)45b.open_the_door()46b.hungry()47b.i_wanna_play()48
49print() # Let's add some space for readability. This line has nothing to do with the cats.50
51if a.equals(b):52 print("a == b Same Cat")53else:54 print("a == b Not the same Cat!")55
56print() # Let's add some space for readability. This line has nothing to do with the cats.57
58if a.equals(a):59 print("a == a Same Cat")60else:61 print("a == a Not the same Cat!")62
63print() # Let's add some space for readability. This line has nothing to do with the cats.64
65if b.equals(b):66 print("b == b Same Cat")67else:68 print("b == b Not the same Cat!")69
70print() # Let's add some space for readability. This line has nothing to do with the cats.71
72if a == b:73 print("a == b It's the same cat!")74else:75 print("a == b It's not the same cat!")76
77print() # Let's add some space for readability. This line has nothing to do with the cats.78
79if a == a:80 print("a == a It's the same cat!")81else:82 print("a == a It's not the same cat!")
You can prevent executing those statements by checking if the file cat.py
was invoked as
a module or as a script by checking its name.
1class Cat:2 def __init__(self,3 oos_when_hungry,4 oos_when_playful,5 oos_when_open_door):6 self.oos_when_hungry = oos_when_hungry7 self.oos_when_playful = oos_when_playful8 self.oos_when_open_door = oos_when_open_door9
10 @staticmethod11 def meow(number_of_os):12 print("ฅ^•ﻌ•^ฅ Me" + "o" * number_of_os + "w")13
14 def open_the_door(self):15 Cat.meow(self.oos_when_open_door)16
17 def hungry(self):18 Cat.meow(self.oos_when_hungry)19
20 def i_wanna_play(self):21 Cat.meow(self.oos_when_playful)22
23 def equals(self, other_cat):24 if self.oos_when_hungry == other_cat.oos_when_hungry and \25 self.oos_when_playful == other_cat.oos_when_playful and \26 self.oos_when_open_door == other_cat.oos_when_open_door:27 return True28 else:29 return False30
31 def __equals__(self, other_cat):32 return self.equals(other_cat)33
34
35if __name__ == "__main__":36 # Let me tell you about my girly kitty's morning37 a = Cat(1, 4, 8)38 a.open_the_door()39 a.hungry()40 a.i_wanna_play()41
42 print() # Let's add some space for readability. This line has nothing to do with the cats.43
44 # Let me tell you about my big macho kitty45 b = Cat(2, 10, 5)46 b.open_the_door()47 b.hungry()48 b.i_wanna_play()49
50 print() # Let's add some space for readability. This line has nothing to do with the cats.51
52 if a.equals(b):53 print("a == b Same Cat")54 else:55 print("a == b Not the same Cat!")56
57 print() # Let's add some space for readability. This line has nothing to do with the cats.58
59 if a.equals(a):60 print("a == a Same Cat")61 else:62 print("a == a Not the same Cat!")63
64 print() # Let's add some space for readability. This line has nothing to do with the cats.65
66 if b.equals(b):67 print("b == b Same Cat")68 else:69 print("b == b Not the same Cat!")70
71 print() # Let's add some space for readability. This line has nothing to do with the cats.72
73 if a == b:74 print("a == b It's the same cat!")75 else:76 print("a == b It's not the same cat!")77
78 print() # Let's add some space for readability. This line has nothing to do with the cats.79
80 if a == a:81 print("a == a It's the same cat!")82 else:83 print("a == a It's not the same cat!")
You achieve that by checking the special variable __name__
and compare it
to the string "__main__"
. Don't forget to indent the code that instantiates
and tests the code to match the if statement in your condition.
Let's take a look at a module we didn't write: jira
. Let's install that module first:
Note: make sure you run the steps in setting up your development environment
1$ pipenv run pip install jira
1from jira import JIRA2
3options = {"server": "https://jira.atlassian.com"}4jira = JIRA(options)5
6# Get all projects viewable by anonymous users.7projects = jira.projects()8
9print(projects)
Let's analyze the following code line by line:
1
From the jira
module, get the JIRA class definition.
1
Construct a dictionary (a dict
object) with key server
and value https://jira.atlassian.com, and assign the value to
the options variable.
1
With those options, instantiate a jira object from the JIRA class.
1
Invoke the projects function from my new jira object and assign the results to the projects variable.
1
Print the object projects.
1
But... how does python know where to find the jira
module. What does it mean
"to install it"?
If you compare the jira example from above to our cat
module example. One important
difference is that cat.py
was located in the same directory as our main.py
file.
Like most programming languages, Python cares where you place your files, and it follows a series of rules to find modules. You can read more about those rules here.
I'll try to simplify what that page says here:
Note: you can modify this behavior but that's a bit out of scope for this tutorial.
cat.py
!)site-packages
).i.e. installing the jira
module means to get the files from some location on the internet
and placing them in the right location in your computer.
Now that we know that, the really cool fact is that the JIRA class we're using in our code is not that special. Someone else wrote it, published it in pypi.org and made it available for everyone.
When we ran:
1$ pipenv run pip install jira
the command pipenv
just helped us to place all those bits we downloaded in the right place.
You can even learn how jira
was implemented (which is just a fancy word to say "coded" or "written")
You can read how the JIRA class has
an __init__
method. Or the projects
function.