When you are working on a project, create a new directory to organize the files associated with it. Particularly since we will organize the code so that each class definition is in a different file, put all files for a project in the same directory.
To use a class that is defined in another file, you’ll need to import it, much the way you’ve used modules like random and json. Since you want to include a class defined in another file, the syntax is
from <script name without the extension> import <class name>
So, for example, since I'll use the convention of naming the file with a class definition the same as the class name (put the IceCreamSandwich class definition in a file named IceCreamSandwich.py, we need to have the following in your main.py file which construct IceCreamSandwich instances.
from IceCreamSandwich import IceCreamSandwich
This is not a typical Python naming conventions, but will help us transition to Java!
As a general rule of thumb, use conventional identifier rules when you’re naming directories and files.
In particular, do not put spaces in directory or file names!
class IceCreamSandwich( object ):
""" Represents an ice cream sandwich. Mmmm. Ice cream. """
def __init__( self, icFlavor:str, cookie:str ):
""" Constructor (special method that must have the __init__ identifier)
creates a new ice cream sandwich with the specified flavors. """
# initialize an instance property to hold the ice cream flavor
self.__iceCreamFlavor:str = icFlavor
# initialize an instance property to hold the cookie (sandwich outer)
self.__cookieFlavor:str = cookie
# initialize that the sandwich is not melted
self.melted:bool = False
# initialize that the sandwich starts off with 6 bites as its size
self.__size:int = 6
def melt( self ) -> None:
""" Melt this ice cream sandwich. """
# update the instance property accordingly
self.melted = True
def bite( self, amount:int ) -> None:
""" Bite the given amount from this ice cream sandwich. """
# update the instance property accordingly
self.__size = self.__size-amount
# make sure we have an expected value for the instance property
# if we went negative
if self.__size < 0:
# reassign to value of 0
self.__size = 0
def __str__( self ) -> str:
""" Return a string representation of this ice cream scoop.
By using the special identifier __str__, this will allow us to
associate it with the str function (or simply print). """
# start building a description
description:str = "A " + self.__cookieFlavor + " and " + self.__iceCreamFlavor \
+ " of size " + str(self.__size) + " that is "
if not self.melted:
description += "not "
description += "melted."
return description
from IceCreamSandwich import IceCreamSandwich
def main():
# create a new instance of an IceCreamSandwich and pass the 2 required arguments to the constructor
sand1:IceCreamSandwich = IceCreamSandwich( "vanilla", "chocolate chip cookies" )
# invoke the str function, which the __str__ instance method hooks into
sand1description:str = str( sand1 )
# print the resulting value
print( sand1description )
# take a bite out of the sandwich
sand1.bite( 1 )
# print out the sandwich (this time passing it to the print function, which also looks for __str__)
print( sand1 )
# create another IceCreamSandwich instance
sand2:IceCreamSandwich = IceCreamSandwich( "strawberry", "graham crackers" )
# print it out
print( sand2 )
# ask it to melt
sand2.melt()
# print it again
print( sand2 )
# now take lots of bites from it...
for i in range( 4 ):
sand2.bite( i )
print( sand2 )
if __name__ == "__main__":
main()