diff --git a/DataTypes.rst b/DataTypes.rst index 7932fa8..efc36a0 100644 --- a/DataTypes.rst +++ b/DataTypes.rst @@ -1,846 +1,1397 @@ -Chapter 2: Data Types and Referencing -+++++++++++++++++++++++++++++++++++++ - -We all know that programming languages and applications need data. We define applications to work with data, -and we need to have containers that can be used to hold it. This chapter is all about defining containers and -using them to work with application data. This is the foundation of any programming language...it is how we get -tasks accomplished. Whether the data we are using is coming from a keyboard entry or if we are working with a -database, there needs to be a way to temporarily store it in our programs so that it can be manipulated and used. +Chapter 2: Data Types and Referencing +++++++++++++++++++++++++++++++++++++++ + +Programming languages and applications need data. +We define applications to work with data, and we need to have containers that can be used to hold it. +This chapter is all about defining containers and using them to work with application data. +Whether the data we are using is coming from a keyboard entry or if we are working with a database, there needs to be a way to temporarily store it in our programs so that it can be manipulated and used. Once we're done working with the data then these temporary containers can be destroyed in order to make room for new constructs. -We'll start by taking a look at the different data types that are offered by the Python language, and then we'll -follow by discussing how to use that data once it has been collected and stored. We will compare and contrast the -different types of structures that we have in our arsenal, and I'll give some examples of which structures to use -for working with different types of data. There are a multitude of tasks that can be accomplished through the use -of lists, dictionaries, and tuples and I will cover the majority of them. Once you learn how to define and use these -structures, then we'll talk a bit about what happens to them once they are no longer needed by our application. +We’ll start by taking a look at the different data types that are offered by the Python language, and then we'll follow by discussing how to use that data once it has been collected and stored. +We will compare and contrast the different types of structures that we have in our arsenal, and we’ll give some examples of which structures to use for working with different types of data. +There are a multitude of tasks that can be accomplished through the use of lists, dictionaries, and tuples and we will try to cover many of them. +Once you learn how to define and use these structures, then we’ll talk a bit about what happens to them once they are no longer needed by our application. -Lets begin our journey into exploring data types and structures within the Python programming language...these are skills -that you will use in each and every practical Jython program. +Let’s begin our journey into exploring data types and structures within the Python programming language. . .these are skills that you will use in each and every practical Jython program. Python Data Types ================= -As we’ve discussed, there is a need to store and manipulate data within programs. In order to do so then we must also -have the ability to create containers used to hold that data so that the program can use it. The language needs to know -how to handle data once it is stored, and we can do that by assigning data type to our containers. However, in Python -it is not a requirement to do so because the interpreter is able to determine which type of data we are storing in a dynamic fashion. - -The following table lists each data type and gives a brief description of the characteristics that define each of them. - +As we’ve discussed, there is a need to store and manipulate data within programs. +In order to do so then we must also have the ability to create containers used to hold that data so that the program can use it. +The language needs to know how to handle data once it is stored, and we can do that by assigning data type to our containers in Java. +However, in Python it is not a requirement to do so because the interpreter is able to determine which type of data we are storing in a dynamic fashion. + +Table 2-1 lists each data type and gives a brief description of the characteristics that define each of them. + +*Table 2-1. Python Data Types* + ++-----------+------------------------------------------------------------------------------------------+ +| Data Type | Characteristics | ++===========+==========================================================================================+ +| None | NULL value object. | ++-----------+------------------------------------------------------------------------------------------+ +| int | Plain integer (e.g. 32). | ++-----------+------------------------------------------------------------------------------------------+ +| long | Long integer. Integer literal with an 'L' suffix, too long to be a plain integer. | ++-----------+------------------------------------------------------------------------------------------+ +| float | Floating-point number. Numeric literal containing decimal or exponent sign. | ++-----------+------------------------------------------------------------------------------------------+ +| complex | Complex number. Expressed as a sum of a numeric literal with a real and imaginary part. | ++-----------+------------------------------------------------------------------------------------------+ +| Boolean | True or False value (also characterized as numeric values of 1 and 0 respectively). | ++-----------+------------------------------------------------------------------------------------------+ +| Sequence | Includes the following types: string, unicode string, basestring, list, tuple. | ++-----------+------------------------------------------------------------------------------------------+ +| Mapping | Includes the dictionary type. | ++-----------+------------------------------------------------------------------------------------------+ +| Set | Unordered collection of distinct objects; includes the following types: set, frozenset. | ++-----------+------------------------------------------------------------------------------------------+ +| File | Used to make use of file system objects. | ++-----------+------------------------------------------------------------------------------------------+ +| Iterator | Allows for iteration over a container. See section on Iterators for more details. | ++-----------+------------------------------------------------------------------------------------------+ + + +Given all of that information and the example above, we should officially discuss how to declare a variable in the Python language. +Let’s take a look at some examples of defining variables in the following lines of code. + +*Listing 2-1. Defining Variables in Jython*:: + + # Defining a String + x = 'Hello World' + x = "Hello World Two" + + # Defining an integer + y = 10 + + # Float + z = 8.75 + + # Complex + i = 1 + 8.07j + +An important point to note is that there really are no types in Jython. +Every object is an instance of a class. +In order to find the type of an object, simply use the type() function. + +*Listing 2-2.*:: + + # Return the type of an object using the type function + >>> i = 1 + 8.07j + >>> type(i) + + >>> a = 'Hello' + >>> type(a) + + +A nice feature to note is multiple assignment. +Quite often it is necessary to assign a number of values to different variables. +Using multiple assignment in Python, it is possible to do this in one line. + +*Listing 2-3. Multiple Assignment*:: + + >>> x, y, z = 1, 2, 3 + >>> print x + 1 + >>> print z + 3 +Strings and String Methods +========================== + +Strings are a special type within most programming languages because they are often used to manipulate data. +A string in Python is a sequence of characters, which is immutable. +An immutable object is one that cannot be changed after it is created. +The opposite would be a mutable object, which can be altered after creation. +This is very important to know as it has a large impact on the overall understanding of strings. +However, there are quite a few string methods that can be used to manipulate the contents of a particular string. +We never actually manipulate the contents though, these methods return a manipulated copy of the string. +The original string is left unchanged. + +Prior to the release of Jython 2.5.0, CPython and Jython treated strings a bit differently. +There are two types of string objects in CPython, these are known as Standard strings and Unicode strings. +There is a lot of documentation available that specifically focuses on the differences between the two types of strings, this reference will only cover the basics. +It is worth noting that Python contains an abstract string type known as basestring so that it is possible to check any type of string to ensure that it is a string instance. + +Prior to the release of Jython 2.5.0 there was only one string type. +The string type in Jython supported full two-byte Unicode characters and all functions contained in the string module were Unicode-aware. +If the u'' string modifier is specified, it is ignored by Jython. +Since the release of 2.5.0, strings in Jython are treated just like those in CPython, so the same rules will apply to both implementations. +If you are interested in learning more about String encoding, there are many great references available on the topic. +It is also worth noting that Jython uses character methods from the Java platform. +Therefore properties such as isupper and islower, which we will discuss later in the section, are based upon the Java methods, although they actually work the same way as their CPython counterparts + +In the remainder of this section, we will go through each of the many string functions that are at our disposal. +These functions will work on both Standard and Unicode strings. +As with many of the other features in Python and other programming languages, at times there is more than one way to accomplish a task. +In the case of strings and string manipulation, this holds true. +However, you will find that in most cases, although there are more than one way to do things, Python experts have added functions which allow us to achieve better performing and easier to read code. + +Table 2-2 lists all of the string methods that have been built into the Python language as of the 2.5 release. +Because Python is an evolving language, this list is sure to change in future releases. +Most often, additions to the language will be made, or existing features are enhanced. +Following the table, we will give numerous examples of the methods and how they are used. +Although we cannot provide an example of how each of these methods work (that would be a book in itself), they all function in the same manner so it should be rather easy to pick up. + +*Table 2-2. String Methods* + ++----------------------------------+------------------------------------------------------+ +| Method | Description of Functionality | ++==================================+======================================================+ +| capitalize() | Returns a capitalized copy of string | ++----------------------------------+------------------------------------------------------+ +| center (width[,fill]) | Returns a repositioned string with specified width | +| | and provide optional padding filler character | ++----------------------------------+------------------------------------------------------+ +| count(sub[,start[,end]]) | Count the number of distinct times the substring | +| | occurs within the string | ++----------------------------------+------------------------------------------------------+ +| decode([encoding[,errors]]) | Decodes and returns Unicode string | ++----------------------------------+------------------------------------------------------+ +| encode([encoding[,errors]]) | Returns an encoded version of a string | ++----------------------------------+------------------------------------------------------+ +| endswith(suffix[,start[,end]]) | Returns a boolean to state whether the string ends | +| | in a given pattern | ++----------------------------------+------------------------------------------------------+ +| expandtabs([tabsize]) | Converts tabs within a string into spaces | ++----------------------------------+------------------------------------------------------+ +| find(sub[,start[,end]]) | Returns the index of the position where the first | +| | occurrence of the given substring begins | ++----------------------------------+------------------------------------------------------+ +| index(sub[,start[,end]) | Returns the index of the position where the first | +| | occurrence of the given substring begins. Raises a | +| | ValueError with the substring is not found. | ++----------------------------------+------------------------------------------------------+ +| isalnum() | Returns a boolean to state whether the string | +| | contain only alphabetic and numeric characters | ++----------------------------------+------------------------------------------------------+ +| isalpha() | Returns a boolean to state whether the string | +| | contains all alphabetic characters | ++----------------------------------+------------------------------------------------------+ +| isdigit() | Returns a boolean to state whether the string | +| | contains all numeric characters | ++----------------------------------+------------------------------------------------------+ +| islower() | Returns a boolean to state whether a string contains | +| | all lowercase characters | ++----------------------------------+------------------------------------------------------+ +| isspace() | Returns a boolean to state whether the string | +| | consists of all whitespace | ++----------------------------------+------------------------------------------------------+ +| istitle() | Returns a boolean to state whether the first | +| | character of each word in the string is capitalized | ++----------------------------------+------------------------------------------------------+ +| isupper() | Returns a boolean to state whether all characters | +| | within the string are uppercase | ++----------------------------------+------------------------------------------------------+ +| join(sequence) | Returns a copy of sequence joined together with the | +| | original string placed between each element | ++----------------------------------+------------------------------------------------------+ +| ljust(width[,fillchar]) | Returns a string of the specified width along with a | +| | copy of the original string at the leftmost bit. | +| | (Optionally padding empty space with fillchar) | ++----------------------------------+------------------------------------------------------+ +| lower() | Returns a copy of the original string with  all | +| | characters in the string converted to lowercase | ++----------------------------------+------------------------------------------------------+ +| lstrip([chars]) | Removes the first found characters in the string | +| | from the left that match the given characters. Also | +| | removes whitespace from the left. Whitespace removal | +| | is default when specified with no arguments. | ++----------------------------------+------------------------------------------------------+ +| partition(separator) | Returns a partitioned string starting from the left | +| | using the provided separator | ++----------------------------------+------------------------------------------------------+ +| replace(old,new[,count]) | Returns a copy of the original string replacing the | +| | portion of string given in old with the portion | +| | given in new | ++----------------------------------+------------------------------------------------------+ +| rfind(sub[,start[,end]]) | Searches string from right to left and finds the | +| | first occurrence of the given string and returns | +| | highest index where sub is found | ++----------------------------------+------------------------------------------------------+ +| rindex(sub[,start[,end]]) | Searches string from right to left and finds the | +| | first occurrence of the given string and either | +| | returns highest index where sub is found or raises | +| | an exception | ++----------------------------------+------------------------------------------------------+ +| rjust(width[,fillchar]) | Returns copy of string Aligned  to the right by | +| | width | ++----------------------------------+------------------------------------------------------+ +| rpartition(separator) | Returns a copy of stringPartitioned starting from | +| | the right using the provided separator object | ++----------------------------------+------------------------------------------------------+ +| rsplit([separator[,maxsplit]]) | Returns list of words in string and splits the | +| | string from the right side and uses the given | +| | separator as a delimiter. If maxsplit is specified | +| | then at most maxsplit splits are done (from the | +| | right). | ++----------------------------------+------------------------------------------------------+ +| rstrip([chars]) | Returns copy of string removing the first found | +| | characters in the string from the right that match | +| | those given. Also removes whitespace from the right | +| | when no argument is specified. | ++----------------------------------+------------------------------------------------------+ +| split([separator[,maxsplit]]) | Returns a list of words in string and splits the | +| | string from the left side and uses the given | +| | separator as a delimiter. | ++----------------------------------+------------------------------------------------------+ +| splitlines([keepends]) | Splits the string into a list of lines. Keepends | +| | denotes if newline delimiters are removed. | +| | Returns the list of lines in the string. | ++----------------------------------+------------------------------------------------------+ +| startswith(prefix[,start[,end]]) | Returns a boolean to state whether the string | +| | starts with the given prefix | ++----------------------------------+------------------------------------------------------+ +| strip([chars]) | Returns a copy of string with the given | +| | characters removed from the string. If no | +| | argument is specified then whitespace is removed. | ++----------------------------------+------------------------------------------------------+ +| swapcase() | Returns a copy of the string the case of each | +| | character in the string converted. | ++----------------------------------+------------------------------------------------------+ +| title() | Returns a copy of the string with the first | +| | character in each word uppercase. | ++----------------------------------+------------------------------------------------------+ +| translate(table[,deletechars]) | Returns a copy of the string using the given | +| | character translation table to translate the | +| | string. All characters occurring in optional | +| | deletechars argument are removed. | ++----------------------------------+------------------------------------------------------+ +| upper() | Returns a copy of string with  all of the | +| | characters in the string converted to  uppercase | ++----------------------------------+------------------------------------------------------+ +| zfill(width) | Returns a numeric string padded  from the left | +| | with zeros for the specified width. | ++----------------------------------+------------------------------------------------------+ + + + +Now let’s take a look at some examples so that you get an idea of how to use the string methods. +As stated previously, most of them work in a similar manner. + +*Listing 2-4. Using String Methods*:: + + our_string='python is the best language ever' + + # Capitalize first character of a String + >>> our_string.capitalize() + 'Python is the best language ever' + + # Center string + >>> our_string.center(50) + '         python is the best language ever         ' + >>> our_string.center(50,'-') + '---------python is the best language ever---------' + + # Count substring within a string + >>> our_string.count('a') + 2 + + # Count occurrences of substrings + >>> state = 'Mississippi' + >>> state.count('ss') + 2 + + # Partition a string returning a 3-tuple including the portion of string + # prior to separator, the separator + # and the portion of string after the separator + >>> x = "Hello, my name is Josh" + >>> x.partition('n') + ('Hello, my ', 'n', 'ame is Josh') + + # Assuming the same x as above, split the string using 'l' as the separator + >>> x.split('l') + ['He', '', 'o, my name is Josh'] + + # As you can see, the tuple returned does not contain the separator value + # Now if we add maxsplits value of 1, you can see that the right-most split + # is taken.  If we specify maxsplits value of 2, the two right-most splits + # are taken + >>> x.split('l',1) + ['He', 'lo, my name is Josh'] + >>> x.split('l',2) + ['He', '', 'o, my name is Josh'] -=========== ========================================================================================= -Data Type Characteristics -=========== ========================================================================================= -None NULL value object -Numeric A data type used to hold numeric values of integer, decimal, float, complex, and long -Boolean True or False value (also characterized as numeric values of 1 and 0 respectively) -Sequence Includes the following types: string, unicode string, basestring, xrange, list, tuple -Mapping Includes the dictionary type -Set Unordered collection of distinct objects; includes the following types: set, frozenset -File Used to make use of file system objects -Iterator Allows for iteration over a container - -=========== ========================================================================================= +String Formatting +----------------- + +You have many options when printing strings using the print statement. +Much like the C programming language, Python string formatting allows you to make use of a number of different conversion types when printing. + +*Listing 2-5. Using String Formatting*:: + + # The two syntaxes below work the same + >>> x = "Josh" + >>> print "My name is %s" % (x) + My name is Josh + >>> print "My name is %s" % x + My name is Josh + + # An example using more than one argument + >>> name = 'Josh' + >>> language = 'Python' + >>> print "My name is %s and I speak %s" % (name, language) + My name is Josh and I speak Python + + # And now for some fun, here's a different conversion type + # Mind you, I'm not sure where in the world the temperature would + # fluctuate so much! + >>> day1_temp = 65 + >>> day2_temp = 68 + >>> day3_temp = 84 + >>> print "Given the temparatures %d, %d, and %d, the average would be %f" % (day1_temp, day2_temp, day3_temp, (day1_temp + day2_temp + day3_temp)/3) + Given the temperatures 65, 68, and 83, the average would be 72.333333 + +Table 2-3 lists the conversion types. + +*Table 2-3. Conversion Types* + ++---+---------------------------------------------------------------------------+ +| | | ++---+---------------------------------------------------------------------------+ +| d | signed integer decimal | ++---+---------------------------------------------------------------------------+ +| i | signed integer | ++---+---------------------------------------------------------------------------+ +| o | unsigned octal | ++---+---------------------------------------------------------------------------+ +| u | unsigned decimal | ++---+---------------------------------------------------------------------------+ +| x | unsigned hexidecimal (lowercase) | ++---+---------------------------------------------------------------------------+ +| X | unsigned hexidecimal (uppercase letters) | ++---+---------------------------------------------------------------------------+ +| E | floating point exponential format (uppercase 'E') | ++---+---------------------------------------------------------------------------+ +| e | floating point exponential format (lowercase 'e') | ++---+---------------------------------------------------------------------------+ +| f | floating point decimal format (lowercase) | ++---+---------------------------------------------------------------------------+ +| F | floating point decimal format (same as 'f') | ++---+---------------------------------------------------------------------------+ +| g | floating point exponential format if exponent < -4, otherwise float | ++---+---------------------------------------------------------------------------+ +| G | floating point exponential format (uppercase) if exponent < -4, otherwise | +| | float | ++---+---------------------------------------------------------------------------+ +| c | single character | ++---+---------------------------------------------------------------------------+ +| r | string (converts any python object using repr()) | ++---+---------------------------------------------------------------------------+ +| s | string (converts any python object using str()) | ++---+---------------------------------------------------------------------------+ +| % | no conversion, results in a percent (%) character if specified twice | ++---+---------------------------------------------------------------------------+ + + +*Listing 2-6.*:: + + >>> x = 10 + >>> y = 5.75 + >>> print 'The expression %d * %f results in %f' % (x, y, x*y) + The expression 10 * 5.750000 results in 57.500000 + + # Example of using percentage + >>> test1 = 87 + >>> test2 = 89 + >>> test3 = 92 + >>> "The gradepoint average of three students is %d%%" % (avg) + 'The gradepoint average of three students is 89%' -Table 2-1. Python Data Types +Lists, Dictionaries, Sets, and Tuples +===================================== +Lists, dictionaries, sets, and tuples all offer similar functionality and usability, but they each have their own niche in the language. +We’ll go through several examples of each since they all play an important role under certain circumstances. +Unlike strings, all of the containers discussed in this section (except tuples) are mutable objects, so they can be manipulated after they have been created. +Because these containers are so important, we’ll go through an exercise at the end of this chapter, which will give you a chance to try them out for yourself. -Given all of that information and the example above, we need to know a way to declare a variable in the Python language. -You’ve seen some examples in the previous chapter, but here I will formally show how it is done. Let’s take a look at some -examples of defining variables in the following lines of code. :: +Lists +----- +Perhaps one of the most used constructs within the Python programming language is the list. +Most other programming languages provide similar containers for storing and manipulating data within an application. +The Python list provides an advantage over those similar constructs that are available in statically typed languages. +The dynamic tendencies of the Python language help the list construct to harness the great feature of having the ability to contain values of different types. +This means that a list can be used to store any Python data type, and these types can be mixed within a single list. +In other languages, this type of construct is often defined as a typed object, which locks the construct to using only one data type. + +The creation and usage of Python lists is just the same as the rest of the language...very simple and easy to use. +Simply assigning a set of empty square brackets to a variable creates an empty list. +We can also use the built-in list() function to create a list. +The list can be constructed and modified as the application runs, they are not declared with a static length. +They are easy to traverse through the usage of loops, and indexes can also be used for positional placement or removal of particular items in the list. +We’ll start out by showing some examples of defining lists, and then go through each of the different avenues which the Python language provides us for working with lists. + +*Listing 2-7. Defining Lists*:: + + # Define an empty list + my_list = [] + my_list = list()  # rarely used + + # Single Item List + >>> my_list = [1] + >>> my_list           # note that there is no need to use print to display a variable in the interpreter + [1] + + # Define a list of string values + my_string_list = ['Hello', 'Jython' ,'Lists'] + + # Define a list containing mulitple data types + multi_list = [1, 2, 'three', 4, 'five', 'six'] + + # Define a list containing a list + combo_list = [1, my_string_list, multi_list] + + # Define a list containing a list inline + >>> my_new_list = ['new_item1', 'new_item2', [1, 2, 3, 4], 'new_item3'] + >>> print my_new_list + ['new_item1', 'new_item2', [1, 2, 3, 4], 'new_item3'] + +As stated previously, in order to obtain the values from a list we can make use of indexes. +Much like the Array in the Java language, using the list[index] notation will allow us to access an item. +If we wish to obtain a range or set of values from a list, we can provide a starting index, and/or an ending index. +This technique is also known as slicing. +What’s more, we can also return a set of values from the list along with a stepping pattern by providing a step index as well. +One key to remember is that while accessing a list via indexing, the first element in the list is contained within the 0 index. +Note that when slicing a list, a new list is always returned. +One way to create a shallow copy of a list is to use slice notation without specifying an upper or lower bound. +The lower bound defaults to zero, and the upper bound defaults to the length of the list. + +Note that a shallow copy constructs a new compound object (list or other object containing objects) and then inserts references into it to the original objects. +A deep copy constructs a new compound object and then inserts copies into it based upon the objects found in the original. + +*Listing 2-8. Accessing a List*:: + + # Obtain elements in the list + >>> my_string_list[0] + 'Hello' + >>> my_string_list[2] + 'Lists' + + # Negative indexes start with the last element in the list and work back towards the + first + + # item + >>> my_string_list[-1] + 'Lists' + >>> my_string_list[-2] + 'Jython' + + # Using slicing (Note that slice includes element at starting index and excludes the + end) + >>> my_string_list[0:2] + ['Hello', 'Jython'] + + # Create a shallow copy of a list using slice + >>> my_string_list_copy = my_string_list[:] + >>> my_string_list_copy + ['Hello', 'Jython', 'Lists'] + + # Return every other element in a list + >>> new_list=[2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + # Using a third parameter in the slice will cause a stepping action to take place + + # In this example we step by one + >>> new_list[0:10:1] + [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + + # And here we step by two + >>> new_list[0:10:2] + [2, 6, 10, 14, 18] + + # Leaving a positional index blank will also work as the default is 0 for the start, + and the length of the string for the end. + >>> new_list[::2] + [2, 6, 10, 14, 18] + +Modifying a list is much the same, you can  use the index in order to insert or remove items from a particular position. +There are also many other ways that you can insert or remove elements from the list. +Python provides each of these different options as they provide different functionality for your operations. + +*Listing 2-9.*:: + + # Modify an element in a list.  In this case we'll modify the element in the 9th + position + >>> new_list[9] = 25 + >>> new_list + [2, 4, 6, 8, 10, 12, 14, 16, 18, 25] + +You can make use of the append() method in order to add an item to the end of a list. +The extend() method allows you to add copy of  an entire list or sequence to the end of a list. +Lastly, the insert() method allows you to place an item or another list into a particular position of an existing list by utilizing positional indexes. +If another list is inserted into an existing list then it is not combined with the original list, but rather it acts as a separate item contained within the original list. +You will find examples of each method below. + +Similarly, we have plenty of options for removing items from a list. +The del statement, as explained in Chapter 1, can be used to remove or delete an entire list or values from a list using the index notation. +You can also use the pop() or remove() method to remove single values from a list. +The pop() method will remove a single value from the end of the list, and it will also return that value at the same time. +If an index is provided to the pop() function, then it will remove and return the value at that index. +The remove() method can be used to find and remove a particular value in the list. +In other words, remove() will delete the first matching element from the list. +If more than one value in the list matches the value passed into the remove() function, the first one will be removed. +Another note about the remove() function is that the value removed is not returned. +Let’s take a look at these examples of modifying a list. + +*Listing 2-10. Modifying a List*:: + + # Adding values to a list using the append method + >>> new_list=['a','b','c','d','e','f','g'] + >>> new_list.append('h') + >>> print new_list + ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] + + # Add another list to the existing list + >>> new_list2=['h','i','j','k','l','m','n','o','p'] + >>> new_list.extend(new_list2) + >>> print new_list + ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] + + # Insert a value into a particular location via the index. + # In this example, we add a 'c' into the third position in the list + # (Remember that list indicies start with 0, so the second index is actually the third + # position) + >>> new_list.insert(2,'c') + >>> print new_list + ['a', 'b', 'c', 'c', 'd', 'e', 'f', 'g', 'h', 'h','i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p'] + + # Insert a list into a particular postion via the index + >>> another_list = ['a', 'b', 'c'] + >>> another_list.insert(2, new_list) + >>> another_list + ['a', 'b', [2, 4, 8, 10, 12, 14, 16, 18, 25], 'c'] + + # Use the slice notation to overwrite part of a list or sequence + >>> new_listA=[100,200,300,400] + >>> new_listB=[500,600,700,800] + >>> new_listA[0:2]=new_listB + >>> print new_listA + [500, 600, 700, 800, 300, 400] + + # Assign a list to another list using the empty slice notation + >>> one = ['a', 'b', 'c', 'd'] + >>> two = ['e', 'f'] + >>> one + ['a', 'b', 'c', 'd'] + >>> two + ['e', 'f'] + + # Obtain an empty slice from a list by using the same start and end position. + + # Any start and end position will work, as long as they are the same number. + >>> one[2:2] + [] + + # In itself, this is not very interesting – you could have made an empty list + + # very easily. The useful thing about this is that you can assign to this empty slice + + # Now, assign the 'two' list to an empty slice for the 'one' list which essentially + + # inserts the 'two' list into the 'one' list + >>> one[2:2] = two + # the empty list between elements 1 and 2 of list 'one' is replaced by the list 'two' + >>> one + ['a', 'b', 'c', 'd', 'e', 'f'] + + # Use the del statement to remove a value or range of values from a list + # Note that all other elements are shifted to fill the empty space + >>> new_list3=['a','b','c','d','e','f'] + >>> del new_list3[2] + >>> new_list3 + ['a', 'b', 'd', 'e', 'f'] + >>> del new_list3[1:3] + >>> new_list3 + ['a', 'e', 'f'] + + # Use the del statement to delete a list + >>> new_list3=[1,2,3,4,5] + >>> print new_list3 + [1, 2, 3, 4, 5] + >>> del new_list3 + >>> print new_list3 + Traceback (most recent call last): + File "", line 1, in + NameError: name 'new_list3' is not defined + + # Remove values from a list using pop and remove functions + >>> print new_list + ['a', 'b', 'c', 'c', 'd', 'e', 'f', 'g', 'h','h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] + + # pop the element at index 2 + >>> new_list.pop(2) + 'c' + >>> print new_list + ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] + + # Remove the first occurrence of the letter 'h' from the list + >>> new_list.remove('h') + >>> print new_list + ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] + + # Useful example of using pop() function + >>> x = 5 + >>> times_list = [1,2,3,4,5] + >>> while times_list: + ...     print x * times_list.pop(0) + ... + 5 + 10 + 15 + 20 + 25 - # Defining a String - x = ‘Hello World’ - x = “Hello World Two” +Now that we know how to add and remove items from a list, it is time to learn how to manipulate the data within them. +Python provides a number of different methods that can be used to help us manage our lists. +See Table 2-4 for a list of these functions and what they can do. + +*Table 2-4. Python List Methods* + ++---------+----------------------------------------------------------------------------+ +| Method | Tasks Performed | ++=========+============================================================================+ +| index | Returns the index of the first value in the list which matches a given | +| | value. | ++---------+----------------------------------------------------------------------------+ +| count | Returns the number of items in the list which equal a given value. | ++---------+----------------------------------------------------------------------------+ +| sort | Sorts the items contained within the list and returns the list | ++---------+----------------------------------------------------------------------------+ +| reverse | Reverses the order of the items contained within the list, and returns the | +| | list | ++---------+----------------------------------------------------------------------------+ + + +Let’s take a look at some examples of how these functions can be used on lists. + +*Listing 2-11. Utilizing List Functions*:: + + # Returning the index for any given value + >>> new_list=[1,2,3,4,5,6,7,8,9,10] + >>> new_list.index(4) + 3 + + #  Change the value of the element at index 4 + >>> new_list[4] = 30 + >>> new_list + [1, 2, 3, 4, 30, 6, 7, 8, 9, 10] + + # Ok, let's change it back + >>> new_list[4] = 5 + >>> new_list + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + # Add a duplicate value into the list and then return the index + + # Note that index returns the index of the first matching value it encounters + >>> new_list.append(6) + >>> new_list + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 6] + >>> new_list.index(6) + 5 + + # Using count() function to return the number of items which  equal a given value + >>> new_list.count(2) + 1 + >>> new_list.count(6) + 2 + + # Sort the values in the list + >>> new_list.sort() + >>> new_list + [1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 10] + + # Reverse the order of the value in the list + >>> new_list.reverse() + >>> new_list + [10, 9, 8, 7, 6, 6, 5, 4, 3, 2, 1] + +Traversing and Searching Lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Moving around within a list is quite simple. +Once a list is populated, often times we wish to traverse through it and perform some action against each element contained within it. +You can use any of the Python looping constructs to traverse through each element within a list. +While there are plenty of options available, the for loop works especially well. +This is because of the simple syntax that the Python for loop uses. +This section will show you how to traverse a list using each of the different Python looping constructs. +You will see that each of them has advantages and disadvantages. + +Let’s first take a look at the syntax that is used to traverse a list using a for loop. +This is by far one of the easiest modes of going through each of the values contained within a list. +The for loop traverses the list one element at a time, allowing the developer to perform some action on each element if so desired. + +*Listing 2-12. Traversing a List Using a 'for' Loop*:: + + >>> ourList=[1,2,3,4,5,6,7,8,9,10] + >>> for elem in ourList: + ...    print elem + ... + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + +As you can see from this simple example, it is quite easy to go through a list and work with each item individually. +The for loop syntax requires a variable to which each element in the list will be assigned for each pass of the loop. + +It is also possible to combine slicing with the use of the for loop. +In this case, we’ll simply use a list slice to retrieve the exact elements we want to see. +For instance, take a look a the following code which traverses through the first 5 elements in our list. + +*Listing 2-13.*:: + + >>> for elem in ourList[:5]: + ...     print elem + ... + 1 + 2 + 3 + 4 + 5 - # Defining a number - y = 10 +As you can see, doing so is quite easy by simply making use of the built-in features that Python offers. - # Float - z = 8.75 +List Comprehensions +~~~~~~~~~~~~~~~~~~~ - # Complex - i = 8.07j +As we've seen in the previous section, we can create a copy of a list using the slicing. +Another more powerful way to do so is via the list comprehension. +There are some advanced features for lists that can help to make a developer’s life easier. +One such feature is known as a list comprehension. +While this concept may be daunting at first, it offers a good alternative to creating many separate lists manually. +List comprehensions take a given list, and then iterate through it and apply a given expression against each of the objects in the list. -An important point to note is that there really are no types in Jython. Every object is an instance of a class. Therefore, -in order to find the type of an object in Jython it is perfectly valid to write obj.__class__. :: +*Listing 2-14. Simple List Comprehension*:: + # Multiply each number in a list by 2 using a list comprehension + # Note that list comprehension returns a new list + >>> num_list = [1, 2, 3, 4] + >>> [num * 2 for num in num_list] + [2, 4, 6, 8] - # Return the type of an object in Jython using __class__ - >>> a = 'Hello' - >>> a.__class__ - - - -Strings and String Methods --------------------------- - -Strings are a special type within most programming languages because they are often used to manipulate data. A string -in Python is a sequence of characters, which is immutable. This is very important to know as it has a large impact on -the overall understanding of strings. Once a string has been defined it cannot be changed. However, there are a large -amount of string methods that can be used to manipulate the contents of a particular string. Although we can manipulate -the contents, Python really gives us a manipulated copy of the string…the original string is left unchanged. - -Prior to the 2.5.0 release of Jython, CPython and Jython treated strings a bit differently. There are two types of string objects in CPython, these are known as -*Standard* strings and *Unicode* strings. Standard strings contain 8-bit data, whereas Unicode strings are sequences of data -composed of 16-bit characters. There is a lot of documentation available that specifically focuses on the differences between -the two types of strings, this reference will only cover the basics. It is worth noting that Python contains an abstract string -type known as *basestring* so that it is possible to check any type of string to ensure that it is a string instance. - -Prior to the 2.5.0 release of Jython, there was only one string type. The string type in Jython supported full two-byte Unicode characters and all functions -contained in the string module are Unicode-aware. If the u’’ string modifier was specified, it was ignored by Jython. Since the release of 2.5.0, strings in Jython are treated -just like those in CPython, so the same rules will apply to both implementations. It is also -worth noting that Jython uses character properties from the Java platform. Therefore properties such as isupper and islower, which -we will discuss later in the section, are based upon the Java properties. - -In remainder of this section we will go through each of the many string functions that are at our disposal. These functions will -work on both Standard and Unicode strings. As with many of the other features in Python and other programming languages, there are -often times more than one way to accomplish a task. In the case of strings and string manipulation, this definitely holds true. -However, you will find that in most cases, although there are more than one way to do things, Python experts have added functions -which allow us to achieve better performing and easier to read code. Sometimes one way to perform a task is better achieved by -utilizing a certain function in one case, and doing something different in another case. - -The following table lists all of the string methods that have been built into the Python language as of the 2.5 release. Since Python -is an evolving language, this list is sure to change in future releases. Most often, additions to the language will be made, or -existing features are enhanced. Following the table, I will give numerous examples of the methods and how they are used. Although -I cannot provide an example of how each of these methods work (that would be a book in itself), they all function in the same manner -so it should be rather easy to pick up. - - - -================================== ========================================================================================================================================= === -Method Description of Functionality -================================== ========================================================================================================================================= === -capitalize() Capitalize string -center(width[,fill]) Reposition string and provide optional padding filler character -count(sub[,start[,end]]) Count the number of times the substring occurs within the string -decode([encoding[,errors]]) Decodes and returns Unicode string -encode([encoding[,errors]]) Produces an encoded version of a string -endswith(suffix[,start[,end]]) Returns a boolean to state whether the string ends in a given pattern -expandtabs([tabsize]) Converts tabs within a string into spaces -find(sub[,start[,end]]) Returns the index of the position where the first occurrence of the given substring begins -index(sub[,start[,end]) Returns the index of the position where the first occurrence of the given substring begins -isalnum() Returns a boolean to state whether the string contain both alphabetic and numeric characters -isalpha() Returns a boolean to state whether the string contains all alphabetic characters -isdigit() Returns a boolean to state whether the string contains all numeric characters -islower() Returns a boolean to state whether a string contains all lowercase characters -isspace() Returns a boolean to state whether the string consists of all whitespace -istitle() Returns a boolean to state whether the first character of each word in the string is capitalized -isupper() Returns a boolean to state whether all characters within the string are uppercase -join(sequence) Joins two strings by combining -ljust(width[,fillchar]) Align the string to the left by width -lower() Converts all characters in the string to lowercase -lstrip([chars]) Removes the first found characters in the string from the left that match the given characters. Also removes whitespace from the left. -partition(separator) Partitions a string starting from the left using the provided separator -replace(old,new[,count]) Replaces the portion of string given in *old* with the portion given in *new* -rfind(sub[,start[,end]]) Searches and finds the first occurrence from the end of the given string -rindex(sub[,start[,end]]) Searches and finds the first occurrence of the given string or returns an error -rjust(width[,fillchar]) Align the string to the right by width -rpartition(separator) Partitions a string starting from the right using the provided separator object -rsplit([separator[,maxsplit]]) Splits the string from the right side and uses the given separator as a delimiter -rstrip([chars]) Removes the first found characters in the string from the right that match those given. Also removes whitespace from the right. -split([separator[,maxsplit]]) Splits the string and uses the given separator as a delimiter. -splitlines([keepends]) Splits the string into a list of lines. Keepends denotes if newline delimiters are removed. -startswith(prefix[,start[,end]]) Returns a boolean to state whether the string starts with the given prefix -strip([chars]) Removes the given characters from the string. -swapcase() Converts the case of each character in the string. -title() Returns the string with the first character in each word uppercase. -translate(table[,deletechars]) Use the given character translation table to translate the string. -upper() Converts all of the characters in the string to lowercase. -zfill(width) Pads the string from the left with zeros for the specified width. -================================== ========================================================================================================================================= === - -Table 2-2. String Methods - -Now let’s take a look at some examples so that you get an idea of how to use the string methods. As stated previously, most of them work in a similar manner. :: - - - - ourString=’python is the best language ever’ - - - # Capitalize a String - >>> ourString.capitalize() - 'Python is the best language ever' - - # Center string - >>> ourString.center(50) - ' python is the best language ever ' - >>> ourString.center(50,'-') - '---------python is the best language ever---------' - - # Count substring within a string - >>> ourString.count('a') - 2 - - # Partition a string - >>> x = "Hello, my name is Josh" - >>> x.partition('n') - ('Hello, my ', 'n', 'ame is Josh') + # We could assign a list comprehension to a variable + >>> num_list2 = [num * 2 for num in num_list] + >>> num_list2 + [2, 4, 6, 8] +As you can see, this allows one to quickly take a list and alter it via the use of the provided expression. +Of course, as with many other Python methods the list comprehension returns an altered copy of the list. +The list comprehension produces a new list and the original list is left untouched. -String Formatting -~~~~~~~~~~~~~~~~~ - -You have many options when printing strings using the *print* statement. Much like the C programming language, Python string -formatting allows you to make use of a number of different conversion types when printing. :: - - - Using String Formatting - # The two syntaxes below work the same - >>> x = "Josh" - >>> print "My name is %s" % (x) - My name is Josh - >>> print "My name is %s" % x - My name is Josh - - -====== ============================================================================ -Type Description -====== ============================================================================ -d signed integer decimal -i signed integer decimal -o unsigned octal -u unsigned decimal -x unsigned hexidecimal -X unsigned hexidecimal (upper) -E floating point exponential format (upper) -e floating point exponential format -f floating point decimal format -F floating point decimal format (upper) -g floating point exponential format if exponent > -4, otherwise float -G floating point exponential format (uppr) if exponent > -4, otherwise float -c single character -r string (converts any python object using repr()) -s string (converts any python object using str()) -% no conversion, results in a percent (%) character -====== ============================================================================ - -Table 2-3. Conversion Types - - :: - - - >>> x = 10 - >>> y = 5.75 - >>> print 'The expression %d * %f results in %f' % (x, y, x*y) - The expression 10 * 5.750000 results in 57.500000 - -Ranges ------- +Let’s take a look at the syntax for a list comprehension. +They are basically comprised of an expression of some kind followed by a for statement and then optionally more for or if statements. +The basic functionality of a list comprehension is to iterate over the items of a list, and then apply some expression against each of the list’s members. +Syntactically, a list comprehension reads as follows: -Ranges are not really a data type or a container; they are really a Jython built-in function (Chapter 4). For this reason, -we will only briefly touch upon the range function here, and they’ll be covered in more detail in Chapter 4. However, -because they play such an important role in the iteration of data, usually via the *for* loop, I think it is important to -discuss them in this section of the book. The range is a special function that allows one to iterate between a range of -numbers; and/or list a specific range of numbers. It is especially helpful for performing mathematical iterations, but -it can also be used for simple iterations. - -The format for using the range function includes an optional starting number, an ending number, and an optional stepping number. -If specified, the starting number tells the range where to begin, whereas the ending number specifies where the range should end. -The optional step number tells the range how many numbers should be placed between each number contained within the range output. - - -Range Format -~~~~~~~~~~~~ - - range([start], stop, [step]) +Iterate through a list and optionally perform an expression on each element, then either return a new list containing the resulting elements or evaluate each element given an optional clause. :: - >>>range(0,10) - - >>>range(10) - - >>>range(0,10,2) - >>> range(100,0,-10) - [100, 90, 80, 70, 60, 50, 40, 30, 20, 10] - -As stated previously, this function can be quite useful when used within a *for* loop as the Jython *for* loop syntax works -very well with it. The following example displays a couple examples of using the range function within a *for* loop context. :: - - >>> for i in range(10): - ... print i - ... - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - - # Multiplication Example - >>> x = 1 - >>> for i in range(2, 10, 2): - ... x = x + (i * x) - ... print x - ... - 3 - 15 - 105 - 945 - - -As you can see, a range can be used to iterate through just about any number set...be it positive or negative in range. - -Lists, Dictionaries, Sets, and Tuples -------------------------------------- - -Data collection containers are a useful tool for holding and passing data throughout the lifetime of an application. The data -can come from any number of places, be it the keyboard, a file on the system, or a database…it can be stored in a collection -container and used at a later time. Lists, dictionaries, sets, and tuples all offer similar functionality and usability, but -they each have their own niche in the language. We’ll go through several examples of each since they all play an important role -under certain circumstances. + [list-element (optional expression) for list-element in list (optional clause)] -Since these containers are so important, we’ll go through an exercise at the end of this chapter, which will give you a chance -to try them out for yourself. +*Listing 2-15. Using an If Clause in a List Comprehension*:: -Lists -~~~~~ - -Perhaps one of the most used constructs within the Python programming language is the list. Most other programming languages -provide similar containers for storing and manipulating data within an application. The Python list provides an advantage to -those similar constructs which are available in statically typed languages. The dynamic tendencies of the Python language help -the list construct to harness the great feature of having the ability to contain values of different types. This means that a -list can be used to store any Python data type, and these types can be mixed within a single list. In other languages, this type -of construct is defined as a typed object, which locks the construct to using only one data type. - -The creation and usage of Jython lists is just the same as the rest of the language…very simple and easy to use. Simply assigning -a set of empty square brackets to a variable creates an empty list. We can also use the built-in list() type to create a list. -The list can be constructed and modified as the application runs, they are not declared with a static length. They are easy to -traverse through the usage of loops, and indexes can also be used for positional placement or removal of particular items in the list. -We’ll start out by showing some examples of defining lists, and then go through each of the different avenues which the Jython -language provides us for working with lists. :: - - # Define an empty list - myList = [] - myList = list() - - # Define a list of string values - myStringList = [‘Hello’,’Jython’,’Lists’] - - # Define a list containing mulitple data types - multiList = [1,2,’three’,4,’five’,’six’] - - # Define a list containing a list - comboList = [1,myStringList,multiList] - -As stated previously, in order to obtain the values from a list we can make use of indexes. Much like the Array in the Java language, -using the *list[index]* notation will allow us to access an item. If we wish to obtain a range or set of values from a list, we can -provide a *starting* index, and/or an *ending* index. This technique is also known as *slicing*. What’s more, we can also return -a set of values from the list along with a stepping pattern by providing a *step* index as well. One key to remember is that while -accessing a list via indexing, the first element in the list is contained within the 0 index. :: - - # Obtain elements in the list - >>> myStringList[0] - ‘Hello’ - - >>> myStringList[2] - ‘Lists’ - - >>> myStringList[-1] - 'Lists' - - # Using the slice method - >>> myStringList[0:2] - ['Hello', 'Jython'] - - # Return every other element in a list - >>> newList=[2,4,6,8,10,12,14,16,18,20] - >>> newList[0:10:2] - [2, 6, 10, 14, 18] - - # Leaving a positional index blank will also work - >>> newList[::2] - [2, 6, 10, 14, 18] - -Modifying a list is much the same, you can either use the index in order to insert or remove items from a particular position. -There are also many other ways that you can insert or remove elements from the list. Jython provides each of these different -options as they provide different functionality for your operations. - -In order to add an item to a list, you can make use of the *append()* method in order to add an item to the end of a list. -The *extend()* method allows you to add an entire list or sequence to the end of a list. Lastly, the *insert()* method -allows you to place an item or list into a particular area of an existing list by utilizing positional indexes. -You will examples of each method below. - -Similarly, we have plenty of options for removing items from a list. The *del* statement, as explained in Chapter 1, -can be used to remove or delete an entire list or values from a list using the index notation. You can also use the -*pop() *or *remove()* method to remove single values from a list. The *pop()* method will remove a single value from -the end of the list, and it will also return that value at the same time. If an index is provided to the *pop()* function, -then it will remove and return the value at that index. The *remove()* method can be used to find and remove a particular -value in the list. If more than one value in the list matches the value passed into the *remove()* function, the first one -will be removed. Another note about the *remove()* function is that the value removed is not returned. Let’s take a look -at these examples of modifying a list. :: - - # Adding values to a list - >>> newList=['a','b','c','d','e','f','g'] - >>> newList.append('h') - >>> print newList - ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] - - # Add another list to the existing list - >>> newList2=['h','i','j','k','l','m','n','o','p'] - >>> newList.extend(newList2) - >>> print newList - ['a', 'b', 'c', 'd', 'e', 'f', 'g', ‘h’,'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] - - # Insert a value into a particular location via the index - >>> newList.insert(2,'c') - >>> print newList - ['a', 'b', 'c', 'c', 'd', 'e', 'f', 'g', 'h', ‘h’,'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] - - # Use the slice notation to insert another list or sequence - >>> newListA=[100,200,300,400] - >>> newListB=[500,600,700,800] - >>> newListA[0:2]=newListB - >>> print newListA - [500, 600, 700, 800, 300, 400] - - # Use the del statement to delete a list - >>> newList3=[1,2,3,4,5] - >>> print newList3 - [1, 2, 3, 4, 5] - >>> del newList3 - >>> print newList3 - Traceback (most recent call last): - File "", line 1, in - NameError: name 'newList3' is not defined - - # Use the del statement to remove a value or range of values from a list - >>> newList3=['a','b','c','d','e','f'] - >>> del newList3[2] - >>> newList3 - ['a', 'b', 'd', 'e', 'f'] - >>> del newList3[1:3] - >>> newList3 - ['a', 'e', 'f'] - - # Remove values from a list using pop and remove functions - >>> print newList - ['a', 'b', 'c', 'c', 'd', 'e', 'f', 'g', 'h',’h’, 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] - >>> newList.pop(2) - 'c' - >>> print newList - ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',’h’, 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] - >>> newList.remove('h') - >>> print newList - ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] - - # Useful example of using pop() function - >>> x = 5 - >>> timesList = [1,2,3,4,5] - >>> while timesList: - ... print x * timesList.pop(0) - ... - 5 - 10 - 15 - 20 - 25 + # The following example returns each element + # in the list that is greater than the number 4 + >>> nums = [2, 4, 6, 8] + >>> [num for num in nums if num > 4] + [6, 8] -Now that we know how to add and remove items from a list, it is time to learn how to manipulate the data within them. -Python provides a number of different methods that can be used to help us manage our lists. See the table below for a -list of these functions and what they can do. - - - -========= =============================================================================== -Method Tasks Performed -========= =============================================================================== -index Returns the index of the first value in the list which matches a given value. -count Returns the number of items in the list which match a given value. -sort Sorts the items contained within the list. -reverse Reverses the order of the items contained within the list -========= =============================================================================== - -Table 2-4. Python List Methods - -Let’s take a look at some examples of how these functions can be used on lists. :: - - # Returning the index for any given value - >>> newList=[1,2,3,4,5,6,7,8,9,10] - >>> newList.index(4) - 3 - - # Add a duplicate into the list and then return the index - >>> newList.append(6) - >>> newList - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 6] - >>> newList.index(6) - 5 - - # Using count() function to return the number of items which match a given value - >>> newList.count(2) - 1 - >>> newList.count(6) - 2 - - # Sort the values in the list - >>> newList.sort() - >>> newList - [1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 10] - - # Reverse the order of the value in the list - >>> newList.reverse() - >>> newList - [10, 9, 8, 7, 6, 6, 5, 4, 3, 2, 1] - -Lists -~~~~~ - -Moving around within a list is quite simple. Once a list is populated, often times we wish to traverse through it -and perform some action against each element contained within it. You can use any of the Python looping constructs -to traverse through each element within a list. While there are plenty of options available, the *for* loop works -especially well. The reason is because of the simple syntax that the Python *for* loop uses. This section will show -you how to traverse a list using each of the different Python looping constructs. You will see that each of them has -advantages and disadvantages. - -Let’s first take a look at the syntax that is used to traverse a list using a *for* loop. This is by far one of the -easiest modes of going through each of the values contained within a list. The *for* loop traverses the list one -element at a time, allowing the developer to perform some action on each element if so desired. :: - - >>> ourList=[1,2,3,4,5,6,7,8,9,10] - >>> for elem in ourList: - ... print elem - ... - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - - -As you can see from this simple example, it is quite easy to go through a list and work with each item individually. The -*for* loop syntax requires a variable to which each element in the list will be assigned for each pass of the loop. -Additionally, we can still make use of the current index while traversing a loop this way if needed. The only requirement -is to make use of the *index()* method on the list and pass the current element. :: - - >>>ourList=[1,2,3,4,5,6,7,8,9,10] - >>> for elem in ourList: - ... print 'The current index is: %d' % (ourList.index(elem)) - ... - The current index is: 0 - The current index is: 1 - The current index is: 2 - The current index is: 3 - The current index is: 4 - The current index is: 5 - The current index is: 6 - The current index is: 7 - The current index is: 8 - The current index is: 9 - -If we do not wish to go through each element within the list then that is also possible via the use of the *for* loop. -In this case, we’ll simply use a list slice to retrieve the exact elements we want to see. For instance, take a look -a the following code which traverses through the first 5 elements in our list. :: - - - >>> for elem in ourList[0:5]: - ... print elem - ... - 1 - 2 - 3 - 4 - 5 - -To illustrate a more detailed example, lets say that you wished to retrieve every other element within the list. :: - - >>> for elem in ourList[0::2]: - ... print elem - ... - 1 - 3 - 5 - 7 - 9 +Let’s take a look at some more examples. +Once you’ve seen list comprehensions in action you are sure to understand them and see how useful they can be. -As you can see, doing so is quite easy by simply making use of the built-in features that Python offers. +*Listing 2-16. Python List Comprehensions*:: + # Create a list of ages and add one to each of those ages using a list comprehension + >>> ages=[20,25,28,30] + >>> [age+1 for age in ages] + [21, 26, 29, 31] -List Comprehensions -~~~~~~~~~~~~~~~~~~~ - -There are some advanced features for lists that can help to make a developer’s life easier. Once such feature is known -as a *list comprehension*. While this concept may be daunting at first, it offers a good alternative to creating many separate -lists manually or using map(). List comprehensions take a given list, and then iterate through it and apply a given expression -against each of the objects in the list. This allows one to quickly take a list and alter it via the use of the provided expression. -Of course, as with many other Python methods the list comprehension returns an altered copy of the list. The original list is left untouched. + # Create a list of names and convert the first letter of each name to uppercase as it should be + >>> names=['jim','frank','vic','leo','josh'] + >>> [name.title() for name in names] + ['Jim', 'Frank', 'Vic', 'Leo', 'Josh'] + # Create a list of numbers and return the square of each EVEN number + >>> numList=[1,2,3,4,5,6,7,8,9,10,11,12] + >>> [num*num for num in numList if num % 2 == 0] + [4, 16, 36, 64, 100, 144] -Let’s take a look at the syntax for a list comprehension. They are basically comprised of an expression of some kind followed by a -*for* statement and then optionally more *for* or *if* statements. As they are a difficult technique to describe, let’s take a look -at some examples. Once you’ve seen list comprehensions in action you are sure to understand them and see how useful they can be. :: + # Use a list comprehension with a range + >>> [x*5 for x in range(1,20)] + [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95] - # Create a list of ages and add one to each of those ages using a list comprehension - >>> ages=[20,25,28,30] - >>> [age+1 for age in ages] - [21, 26, 29, 31] + # Use a for clause to perform calculations against elements of two different lists + >>> list1 = [5, 10, 15] + >>> list2 = [2, 4, 6] + >>> [e1 + e2 for e1 in list1 for e2 in list2] + [7, 9, 11, 12, 14, 16, 17, 19, 21] - # Create a list of names and convert the first letter of each name to uppercase as it should be - >>> names=['jim','frank','vic','leo','josh'] - >>> [name.title() for name in names] - ['Jim', 'Frank', 'Vic', 'Leo', 'Josh'] +List comprehensions can make code much more concise and allows one to apply expressions or functions to list elements quite easily. +Let’s take a quick look at an example written in Java for performing the same type of work as an list comprehension. +It is plain to see that list comprehensions are much more concise. - # Create a list of numbers and return the square of each EVEN number - >>> numList=[1,2,3,4,5,6,7,8,9,10,11,12] - >>> [num*num for num in numList if num % 2 == 0] - [4, 16, 36, 64, 100, 144] +*Listing 2-17. Java Code to Take a List of Ages and Add One Year to Each Age*: - # Use a list comprehension with a range - >>> [x*5 for x in range(1,20)] - [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95] +.. code-block:: java + int[] ages = {20, 25, 28, 30}; + int[] ages2 = new int[ages.length]; -List comprehensions can make code much more concise and allows one to apply expressions or functions to list elements quite easily. -Let’s take a quick look at an example written in Java for performing the same type of work as an easy list comprehension. It is plain -to see that list comprehensions are much more concise. + // Use a  Java for loop to go through each element in the array + for (int x = 0; x <= ages.length; x++) { + ages2[x] = ages[x] + 1; + } -Java Code :: - // Define original integer array - int[] ages = {20, 25, 28, 30}; +Tuples +------ +Tuples are much like lists; however, they are immutable. +Once a tuple has been defined, it cannot be changed. +They contain indexes just like lists, but again, they cannot be altered once defined. +Therefore, the index in a tuple may be used to retrieve a particular value and not to assign or modify. +While tuples may appear similar to lists, they are quite different in that tuples usually contain heterogeneous elements, whereas lists oftentimes contain elements that are related in some way. +For instance, a common use case for tuples is to pass parameters to a function, method, and so on. - // Print original int array - System.out.println("Starting List:"); +Since tuples are a member of the sequence type, they can use the same set of methods an operations available to all sequence types. - for (int age : ages) { - System.out.println(age); - } +*Listing 2-18. Examples of Tuples*:: - // Create new int array by adding one to each element of first array - int x = 0; - int[] newages = new int[4]; - for (int age : ages) { - newages[x] = age+1; - x++; - } + # Creating an empty tuple + >>> myTuple = () + # Creating tuples and using them + >>> myTuple2 = (1, 'two',3, 'four') + >>> myTuple2 + (1, 'two', 3, 'four') - // Print ending list - System.out.println("Ending List:"); - for (int age : newages) { - System.out.println(age); + # To create a single-item tuple, include a trailing comma + >>> myteam = 'Bears', + >>> myteam + ('Bears',) - } +As mentioned previously, tuples can be quite useful for passing to functions, methods, classes, and so on. +Oftentimes, it is nice to have an immutable object for passing multiple values. +One such case would be using a tuple to pass coordinates in a geographical information system or another application of the kind. +They are also nice to use in situations where an immutable object is warranted. +Because they are immutable, their size does not grow once they have been defined, so tuples can also play an important role when memory allocation is a concern. Dictionaries -~~~~~~~~~~~~ - -A dictionary is quite different than a typical list in Python as there is no automatically populated index for any given element -within the dictionary. When you use a list, you need not worry about assigning an index to any value that is placed within it. -However, a dictionary forces the developer to assign an index or “key” for every element that is placed into the construct. Therefore, -each entry into a dictionary requires two values, the *key* and the *element*. - -The beauty of the dictionary is that it allows the developer to choose the data type of the key value. Therefore, if one wishes -to use a string value as a key then it is entirely possible. Dictionary types also have a multitude of methods and operations that -can be applied to them to make them easier to work with. - -===================================================================================================================================== ============================================================================================================ -Method or Operation Description -===================================================================================================================================== ============================================================================================================ -len(dictionary) Returns number of items within the given dictionary. -dictionary[key] Returns the item from the list that is associated with the given key. -dictionary[key] = value Sets the associated item in the list to the given value. -del dictionary[key] Deletes the given key/value pair from the list. -dictionary.clear() Removes all items from the dictionary. -dictionary.copy() Creates a shallow copy of the dictionary. -has_key(key) Returns a boolean stating whether the dictionary contains the given key. -items() Returns a copy of the key/value pairs within the dictionary. -keys() Returns the keys within the dictionary. -update([dictionary2]) Updates dictionary with the key/value pairs from the given dictionary. Existing keys will be overwritten. -fromkeys(sequence[,value]) Creates a new dictionary with keys from the given sequence. The values will be set to the values given. -values() Returns the values within the dictionary. -get(key[, b]) Returns the value associated with the given key. If the key does not exist, then returns b. -setdefault(key[, b]) Returns the value associated with the given key. If the key does not exist, then returns and sets b. -pop(key[, b]) Returns and removes the value associated with the given key. If the key does not exist then returns b. -popItem() Removes and returns the first key/value pair in the dictionary. -iteritems() Returns an iterator over the key/value pairs in the dictionary. -iterkeys() Returns an iterator over the keys in the dictionary. -itervalues() Returns an iterator over the values in the dictionary. -===================================================================================================================================== ============================================================================================================ - -Table 2-5. Mapping type methods and operations. - -Now we will take a look at some dictionary examples. This reference will not show you an example of using each of the mapping operations, -but it should provide you with a good enough base understanding of how they work. :: - - # Create an empty dictionary and a populated dictionary - >>> myDict={} - >>> myDict.values() - [] - >>> myDict.has_key(1) - False - >>> myDict[1] = 'test' - >>> myDict.values() - ['test'] - >>> len(myDict) - 1 - - # Replace the original dictionary with a dictionary containing string-based keys - # The following dictionary represents a hockey team line - >>> myDict = {'r_wing':'Josh','l_wing':'Frank','center':'Jim','l_defense':'Leo','r_defense':'Vic'} - >>> myDict.values() - ['Josh', 'Vic', 'Jim', 'Frank', 'Leo'] - >>> myDict.get('r_wing') - 'Josh' - - # Iterate over the items in the dictionary - >>> hockeyTeam = myDict.iteritems() - >>> for player in hockeyTeam: - ... print player - ... - ('r_wing', 'Josh') - ('r_defense', 'Vic') - ('center', 'Jim') - ('l_wing', 'Frank') - ('l_defense', 'Leo') - - >>> for key,value in myDict.iteritems(): - ... print key, value - ... - r_wing Josh - r_defense Vic - center Jim - l_wing Frank - l_defense Leo - -Sets -~~~~ +------------ + +A Python dictionary is a key-value store container. +A dictionary is quite different than a typical list in Python as there is no automatically populated index for any given element within the dictionary. +When you use a list, you need not worry about assigning an index to any value that is placed within it. +A dictionary allows the developer to assign an index or “key” for every element that is placed into the construct. +Therefore, each entry into a dictionary requires two values, the key and the element. + +The beauty of the dictionary is that it allows the developer to choose the data type of the key value. +Therefore, if one wishes to use a string or any other hashable object such as an int or float value as a key then it is entirely possible. +Dictionaries also have a multitude of methods and operations that can be applied to them to make them easier to work with. +Table 2-5 lists dictionary methods and functions. + +*Listing 2-19. Basic Dictionary Examples*:: + + # Create an empty dictionary and a populated dictionary + >>> myDict={} + >>> myDict.values() + [] + + # Assign key-value pairs to dictionary + >>> myDict['one'] = 'first' + >>> myDict['two'] = 'second' + >>> myDict + {'two': 'second', 'one': 'first'} + +*Table 2-5. Dictionary Methods and Functions* + ++----------------------------+----------------------------------------------------------+ +| Method or Function | Description | ++============================+==========================================================+ +| len(dictionary) | Function that returns number of items within the given | +| | dictionary. | ++----------------------------+----------------------------------------------------------+ +| dictionary [key] | Returns the item from the dictionary that is associated | +| | with the given key. | ++----------------------------+----------------------------------------------------------+ +| dictionary[key] = value | Sets the associated item in the dictionary to the given | +| | value. | ++----------------------------+----------------------------------------------------------+ +| del dictionary[key] | Deletes the given key/value pair from the dictionary. | ++----------------------------+----------------------------------------------------------+ +| dictionary.clear() | Method that removes all items from the dictionary. | ++----------------------------+----------------------------------------------------------+ +| dictionary.copy() | Method that creates a shallow copy of the dictionary. | ++----------------------------+----------------------------------------------------------+ +| has_key(key) | Function that returns a boolean stating whether the | +| | dictionary contains the given key. (Deprecated in favor | +| | of using in') | ++----------------------------+----------------------------------------------------------+ +| key in d | Returns a boolean stating whether the given key is found | +| | in the dictionary | ++----------------------------+----------------------------------------------------------+ +| key not in d | Returns a boolean stating whether the given key is not | +| | found in the dictionary | ++----------------------------+----------------------------------------------------------+ +| items() | Returns a list of tuples including a copy of the | +| | key/value pairs within the dictionary. | ++----------------------------+----------------------------------------------------------+ +| keys() | Returns the a list of keys within the dictionary. | ++----------------------------+----------------------------------------------------------+ +| update([dictionary2]) | Updates dictionary with the key/value pairs from the | +| | given dictionary. Existing keys will be overwritten. | ++----------------------------+----------------------------------------------------------+ +| fromkeys(sequence[,value]) | Creates a new dictionary with keys from the given | +| | sequence. The values will be set to the value given. | ++----------------------------+----------------------------------------------------------+ +| values() | Returns the values within the dictionary as a list. | ++----------------------------+----------------------------------------------------------+ +| get(key[, b]) | Returns the value associated with the given key. If the | +| | key does not exist, then returns b. | ++----------------------------+----------------------------------------------------------+ +| setdefault(key[, b]) | Returns the value associated with the given key. If the | +| | key does not exist, then  the key value is set to b | +| | (mydict[key] = b) | ++----------------------------+----------------------------------------------------------+ +| pop(key[, b]) | Returns and removes the key/value pair associated with | +| | the given key. If the key does not exist then returns b. | ++----------------------------+----------------------------------------------------------+ +| popItem() | An arbitrary key/value pair is popped from the | +| | dictionary | ++----------------------------+----------------------------------------------------------+ +| iteritems() | Returns an iterator over the key/value pairs in the | +| | dictionary. | ++----------------------------+----------------------------------------------------------+ +| iterkeys() | Returns an iterator over the keys in the dictionary. | ++----------------------------+----------------------------------------------------------+ +| itervalues() | Returns an iterator over the values in the dictionary. | ++----------------------------+----------------------------------------------------------+ + + +Now we will take a look at some dictionary examples. +This reference will not show you an example of using each of the dictionary methods and functions, but it should provide you with a good enough base understanding of how they work. + +*Listing 2-20. Working with Python Dictionaries*:: + + # Create an empty dictionary and a populated dictionary + >>> mydict = {} + # Try to find a key in the dictionary + >>> 'firstkey' in mydict + False + + # Add key/value pair to dictionary + >>> mydict['firstkey'] = 'firstval' + >>> 'firstkey' in mydict + True + + # List the values in the dictionary + >>> mydict.values() + ['firstval'] + + # List the keys in the dictionary + >>> mydict.keys() + ['firstkey'] + + # Display the length of the dictionary (how many  key/value pairs are in it) + >>> len(mydict) + 1 + + # Print the contents of the dictionary + >>> mydict + {'firstkey': 'firstval'} + >>> + # Replace the original dictionary with a dictionary containing string-based keys + + # The following dictionary represents a hockey team line + >>> myDict = + {'r_wing':'Josh','l_wing':'Frank','center':'Jim','l_defense':'Leo','r_defense':'Vic'} + >>> myDict.values() + ['Josh', 'Vic', 'Jim', 'Frank', 'Leo'] + >>> myDict.get('r_wing') + 'Josh' + >>> myDict['r_wing'] + 'Josh' + + # Try to obtain the value for a key that does not exist + >>> myDict['goalie'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'goalie' + + # Try to obtain a value for a key that does not exist using get() + >>> myDict.get('goalie') + # Now use a default message that will be displayed if the key does not exist + >>> myDict.get('goalie','Invalid Position') + 'Invalid Position' + + # Iterate over the items in the dictionary + >>> for player in myDict.iterItems(): + ...     print player + ... + ('r_wing', 'Josh') + ('r_defense', 'Vic') + ('center', 'Jim') + ('l_wing', 'Frank') + ('l_defense', 'Leo') + + # Assign keys and values to separate objects and then print + >>> for key,value in myDict.iteritems(): + ...     print key, value + ... + r_wing Josh + r_defense Vic + center Jim + l_wing Frank + l_defense Leo -Sets are unordered collections of unique elements. What makes sets different than other sequence types is that they contain -no indexing. They are also unlike dictionaries because there are no key values associated with the elements. They are an arbitrary -collection of unique elements. Sets cannot contain mutable objects, but they can be mutable. -There are two different types of sets, namely *set* and *frozenset*. The difference between the two is quite easily conveyed -from the name itself. A regular *set* is a mutable collection object, whereas a *frozen* set is immutable. Much like sequences and -mapping types, sets have an assortment of methods and operations that can be used on them. Many of the operations and methods work -on both mutable and immutable sets. However, there are a number of them that only work on the mutable set types. In the two tables -that follow, we’ll take a look at the different methods and operations. +Sets +---- + +Sets are unordered collections of unique elements. +What makes sets different than other sequence types is that they contain no indexing or duplicates. +They are also unlike dictionaries because there are no key values associated with the elements. +They are an arbitrary collection of unique elements. +Sets cannot contain mutable objects, but sets themselves can be mutable. +Another thing to note is that sets are note available to use by default, you must import set from the Sets module before using. + +*Listing 2-21. Examples of Sets*:: + + # In order to use a Set, we must first import it + >>> from sets import Set + # To create a set use the following syntax + >>> myset = Set([1,2,3,4,5]) + >>> myset + Set([5, 3, 2, 1, 4]) + + # Add a value to the set – See Table 2-7 for more details + >>> myset.add(6) + >>> myset + Set([6, 5, 3, 2, 1, 4]) + + # Try to add a duplicate + >>> myset.add(4) + >>> myset + Set([6, 5, 3, 2, 1, 4]) + +There are two different types of sets, namely set and frozenset. +The difference between the two is quite easily conveyed from the name itself. +A regular set is a mutable collection object, whereas a frozen set is immutable. +Remember, immutable objects cannot be altered once they have been created whereas mutable objects can be altered after creation. +Much like sequences and mapping types, sets have an assortment of methods and operations that can be used on them. +Many of the operations and methods work on both mutable and immutable sets. +However, there are a number of them that only work on the mutable set types. +In Tables 2-6 and 2-7, we’ll take a look at the different methods and operations. + +*Table 2-6. Set Type Methods and Functions* + ++----------------------------+----------------------------------------------------------+ +| Method or Operation | Description | ++============================+==========================================================+ +| len(set) | Returns the number of elements in a given set | ++----------------------------+----------------------------------------------------------+ +| copy() | Returns a new shallow copy of the set | ++----------------------------+----------------------------------------------------------+ +| difference(set2) | Returns a new set that contains all elements that are in | +| | the calling set, but not in set2 | ++----------------------------+----------------------------------------------------------+ +| intersection(set2) | Returns a new set that contains all elements that the | +| | calling set and set2 have in common | ++----------------------------+----------------------------------------------------------+ +| issubbset(set2) | Returns a Boolean stating whether all elements in | +| | calling set are also in set2 | ++----------------------------+----------------------------------------------------------+ +| issuperset(set2) | Returns a Boolean stating whether all elements in set2 | +| | are contained in calling set | ++----------------------------+----------------------------------------------------------+ +| symmetric_difference(set2) | Returns a new set containing elements either from the | +| | calling set or set2 but not from both (set1 ^ set2) | ++----------------------------+----------------------------------------------------------+ +| x in set | Tests whether x is contained in the set, returns boolean | ++----------------------------+----------------------------------------------------------+ +| x not in set | Tests whether x is not contained in the set, returns | +| | boolean | ++----------------------------+----------------------------------------------------------+ +| union(set2) | Returns a new set containing elements that are contained | +| | in both the calling set and set2 | ++----------------------------+----------------------------------------------------------+ + + +*Listing 2-22. Using Set Type Methods and Functions*:: + + # Create two sets + >>> s1 = Set(['jython','cpython','ironpython']) + >>> s2 = Set(['jython','ironpython','pypy']) + # Make a copy of a set + >>> s3 = s1.copy() + >>> s3 + Set(['cpython', 'jython', 'ironpython']) + + # Obtain a new set containing all elements that are in s1 but not s2 + >>> s1.difference(s2) + Set(['cpython']) + + # Obtain a new set containing all elements from each set + >>> s1.union(s2) + Set(['cpython', 'pypy', 'jython', 'ironpython']) + + # Obtain a new set containing elements from either set that are not contained in both + >>> s1.symmetric_difference(s2) + Set(['cpython', 'pypy']) + + +*Table 2-7. Mutable Set Type Methods* + ++-----------------------------------+-----------------------------------------------------------+ +| Method or Operation | Description | ++===================================+===========================================================+ +| add(item) | Adds an item to a set if it is not already in the set | ++-----------------------------------+-----------------------------------------------------------+ +| clear() | Removes all items in a set | ++-----------------------------------+-----------------------------------------------------------+ +| difference_update(set2) | Returns the set with all elements contained in set2 | +| | removed | ++-----------------------------------+-----------------------------------------------------------+ +| discard(element) | Removes designated element from set if present | ++-----------------------------------+-----------------------------------------------------------+ +| intersection_update(set2) | Returns the set keeping only those elements that are also | +| | in set2 | ++-----------------------------------+-----------------------------------------------------------+ +| pop() | Return an arbitrary element from the set | ++-----------------------------------+-----------------------------------------------------------+ +| remove(element) | Remove element from set if present, if not then KeyError | +| | is raised | ++-----------------------------------+-----------------------------------------------------------+ +| symmetric_difference_update(set2) | Replace the calling set with a set containing | +| | elements from either the calling set or set2 but | +| | not both, and return it | ++-----------------------------------+-----------------------------------------------------------+ +| update(set2) | Returns set including all elements from set2 | ++-----------------------------------+-----------------------------------------------------------+ + + + +*Listing 2-23. More Using Sets*:: + + # Create three sets + >>> s1 = Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + >>> s2 = Set([5, 10, 15, 20]) + >>> s3 = Set([2, 4, 6, 8, 10]) + # Remove arbitrary element from s2 + >>> s2.pop() + 20 + >>> s2 + Set([5, 15, 10]) + + # Discard the element that equals 3 from s1 (if exists) + >>> s1.discard(3) + >>> s1 + Set([6, 5, 7, 8, 2, 9, 10, 1, 4]) + + # Update s1 to include only those elements contained in both s1 and s2 + >>> s1.intersection_update(s2) + >>> s1 + Set([5, 10]) + >>> s2 + Set([5, 15, 10]) + + # Remove all elements in s2 + >>> s2.clear() + >>> s2 + Set([]) + + # Updates set s1 to include all elements in s3 + >>> s1.update(s3) + >>> s1 + Set([6, 5, 8, 2, 10, 4]) +Ranges +------ -============================ ============================================================== -Method or Operation Description -============================ ============================================================== -len(set) Returns the number of elements in a given set. -copy() -difference(set2) -intersection(set2) -issubbset(set2) -issuperset(set2) -symmetric_difference(set2) -union(set2) -============================ ============================================================== +The range is a special function that allows one to iterate between a range of numbers or list a specific range of numbers. +It is especially helpful for performing mathematical iterations, but it can also be used for simple iterations. -Table 2-6. Set Type Methods and Operations +The format for using the range function includes an optional starting number, an ending number, and an optional stepping number. +If specified, the starting number tells the range where to begin, whereas the ending number specifies where the range should end. +The starting index is inclusive whereas the ending index is not. +The optional step number tells the range how many numbers should be placed between each number contained within the range output. +The step number is added to the previous number and if that number exceeds the end point then the range stops. +Range Format +~~~~~~~~~~~~ -=================================== ===================================================================== -Method or Operation Description -=================================== ===================================================================== -add(item) Adds an item to a set if it is not already in the set. -clear() Removes all items in a set. -difference_update(set2) -discard(item) -intersection_update(set2) -pop() -remove() -symmetric_difference_update(set2) -update(set2) -=================================== ===================================================================== +:: -Table 2-7. Mutable Set Type Methods and Operations + range([start], stop, [step]) + +*Listing 2-24. Using the Range Function*:: + + #Simple range starting with zero, note that the end point is not included in the + range + >>>range(0,10) + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + >>> range(50, 65) + [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64] + >>>range(10) + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + + # Include a step of two in the range + >>>range(0,10,2) + [0, 2, 4, 6, 8] + + # Including a negative step performs the same functionality...the step is added to + the previously + + # number in the range + >>> range(100,0,-10) + [100, 90, 80, 70, 60, 50, 40, 30, 20, 10] + +One of the most common uses for this function is in a for loop. +The following example displays a couple ways of using the range function within a for loop context. + +*Listing 2-25. Using the Range Function Within a For Loop*:: + + >>> for i in range(10): + ...     print i + ... + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + # Multiplication Example + >>> x = 1 + >>> for i in range(2, 10, 2): + ...     x = x + (i * x) + ...     print x + ... + 3 + 15 + 105 + 945 + +As you can see, a range can be used to iterate through just about any number set, be it going up or down, positive or negative in step. +Ranges are also a good way to create a list of numbers. +In order to do so, simply pass a range to list() as shown in the following example. + +*Listing 2-26. Create a List from a Range*:: + + >>> my_number_list = list(range(10)) + >>> my_number_list + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +As you can see, not only are ranges useful for iterative purposes but they are also a good way to create numeric lists. + +Jython-specific Collections +=========================== + +There are a number of Jython-specific collection objects that are available for use. +Most of these collection objects are used to pass data into Java classes and so forth, but they add additional functionality into the Jython implementation that will assist Python newcomers that are coming from the Java world. +Nonetheless, many of these additional collection objects can be quite useful under certain situations. + +In the Jython 2.2 release, Java collection integration was introduced. +This enables a bidirectional interaction between Jython and Java collection types. +For instance, a Java ArrayList can be imported in Jython and then used as if it were part of the language. +Prior to 2.2, Java collection objects could act as a Jython object, but Jython objects could not act as Java objects. +For instance, it is possible to use a Java ArrayList in Jython and use methods such as add(), remove(), and get(). +You will see in the example below that using the add() method of an ArrayList will add an element to the list and return a boolean to signify the success or failure of the addition. +The remove() method acts similarly, except that it removes an element rather than adding it. + +*Listing 2-27. Example of Using Java Oriented Collection in Jython*:: + + # Import and use a Java ArrayList + >>> import java.util.ArrayList as ArrayList + >>> arr = ArrayList() + #  Add method will add an element to the list and return a boolean to signify + successsful addition + >>> arr.add(1) + True + >>> arr.add(2) + True + >>> print arr + [1, 2] + +Ahead of the integration of Java collections, Jython also had implemented the jarray object which basically allows for the construction of a Java array in Jython. +In order to work with a jarray, simply define a sequence type in Jython and pass it to the jarray object along with the type of object contained within the sequence. +The jarray is definitely useful for creating Java arrays and then passing them into java objects, but it is not very useful for working in Jython objects. +Moreover, all values within a jarray must be the same type. +If you try to pass a sequence containing multiple types to a jarray then you’ll be given a TypeError of one kind or another. +See Table 2-8 for a listing of character typecodes used with jarray. + +*Table 2-8. Character Typecodes for Use With Jarray* + ++-----------+-----------------+ +| Character | Java Equivalent | ++===========+=================+ +| z | boolean | ++-----------+-----------------+ +| b | byte | ++-----------+-----------------+ +| c | char | ++-----------+-----------------+ +| d | Double | ++-----------+-----------------+ +| f | Float | ++-----------+-----------------+ +| h | Short | ++-----------+-----------------+ +| i | Int | ++-----------+-----------------+ +| l | Long | ++-----------+-----------------+ + + +*Listing 2-28. Jarray Usage*:: + + >>> my_seq = (1,2,3,4,5) + >>> from jarray import array + >>> array(my_seq,'i') + array('i', [1, 2, 3, 4, 5]) + >>> myStr = "Hello Jython" + >>> array(myStr,'c') + array('c', 'Hello Jython') + +Another useful feature of the jarray is that we can create empty arrays if we wish by using the zeros() method. +The zeros() method works in a similar fashion to the array() method which we’ve already demonstrated. +In order to create an array that is empty, simply pass the length of the array along with the type to the zeros() method. +Let’s take a quick look at an example. + +*Listing 2-29. Create an Empty Boolean Array*:: + + >>> arr = zeros(10,'z') + >>> arr + array('z', [False, False, False, False, False, False, False, False, False, False]) + +*Listing 2-30. Create an Empty Integer Array*:: + + >>> arr2 = zeros(6, 'i') + >>> arr2 + array('i', [0, 0, 0, 0, 0, 0]) + +In some circumstances when working with Java objects, you will need to call a Java method that requires a Java array as an argument. +Using the jarray object allows for a simple way of creating Java arrays when needed. -Tuples -~~~~~~ - -Tuples are much like lists, however they are immutable. Once a tuple has been defined, it cannot be changed. -They contain indexes just like lists, but again, they cannot be altered once defined. Therefore, the index in -a tuple may be used to retrieve a particular value and not to assign or modify. - -Since tuples are a member of the sequence type, they can use the same set of methods an operations available -to all sequence types. :: - - # Creating an empty tuple - >>> myTuple = () - - # Creating tuples and using them - >>> myTuple2 = (1, 'two',3, 'four') - >>> myTuple2 - (1, 'two', 3, 'four') - - -Jython Specific Collections ---------------------------- - -There are a number of Jython specific collection objects that are available for use. Most of these collection -objects are used to pass data into Java classes and so forth, but they add additional functionality into the Jython -implementation that will assist Python newcomers that are coming from the Java world. Nonetheless, many of these -additional collection objects can be quite useful under certain situations. - -In the Jython 2.2 release, Java collection integration was introduced. This enables a bidirectional interaction -between Jython and Java collection types. For instance, a Java ArrayList can be imported in Jython and then used -as if it were part of the language. Prior to 2.2, Java collection objects could act as a Jython object, but Jython -objects could not act as Java objects. :: - - # Import and use a Java ArrayList - >>> import java.util.ArrayList as ArrayList - >>> arr = ArrayList() - >>> arr.add(1) - True - >>> arr.add(2) - True - >>> print arr - [1, 2] - - -Ahead of the integration of Java collections, Jython also had implemented the *jarray* object which basically allows -for the construction of a Java array in Jython. In order to work with a *jarray*, simply define a sequence type in -Jython and pass it to the *jarray* object along with the type of object contained within the sequence. The *jarray* -is definitely useful for creating Java arrays and then passing them into java objects, but it is not very useful for -working in Jython objects. Moreover, all values within a jarray must be the same type. If you try to pass a sequence -containing multiple types to a jarray then you’ll be given a *TypeError* of one kind or another. - -=========== === ================= ========= -Character Java Equivalent -=========== === ================= ========= -z boolean -b byte -c char -d double -f float -h short -i int -l long -=========== === ================= ========= - -Table 2-8. Character Typecodes for use with Jarray :: - - >>> mySeq = (1,2,3,4,5) - >>> from jarray import array - >>> array(mySeq,int) - array(org.python.core.PyInteger, [1, 2, 3, 4, 5]) - - >>> myStr = "Hello Jython" - >>> array(myStr,'c') - array('c', 'Hello Jython') Java arrays can be constructed of arbitrary Java classes using jarray, if needed. @@ -862,230 +1413,329 @@ The names for primitive arrays can be found in the Java documentation for the *C Files ------ - -File objects are used to read and write data to a file on disk. The file object is used to obtain a reference -to the file on disk and open it for reading, writing, appending, or a number of different tasks. If we simply -use the *open(filename[, mode])* function, we can return a file type and assign it to a variable for processing. -If the file does not yet exist on disk, then it will automatically be created. The *mode* argument is used to -tell what type of processing we wish to perform on the file. This argument is optional and if omitted then the -file is opened in read-only mode. - -======= === ==================================== -Mode Description -======= === ==================================== -‘r’ read only -‘w’ write -‘a’ append -‘r+’ read and write -‘rb’ Windows binary file read -‘wb’ Windows binary file write -‘r+b’ Windows binary file read and write -======= === ==================================== - -Table 2-9. Modes of Operations for File Types - - # Open a file and assign it to variable f - - -There are plenty of methods that can be used on file objects for manipulation of the file content. We can call -*read([size])* on a file in order to read it’s content. Size is an optional argument here and it is used to tell -how much content to read from the file. If it is omitted then the entire file content is read. The *readline()* -method can be used to read a single line from a file. *readlines([size])* is used to return a list containing -all of the lines of data that are contained within a file. Again, there is an optional *size* parameter that -can be used to tell how many bytes from the file to read. If we wish to place content into the file, the *write(string)* -method does just that. The *write()* method writes a string to the file. +===== + +File objects are used to read and write data to a file on disk. +The file object is used to obtain a reference to the file on disk and open it for reading, writing, appending, or a number of different tasks. +If we simply use the open(filename[, mode]) function, we can return a file object and assign it to a variable for processing. +If the file does not yet exist on disk, then it will automatically be created. +The mode argument is used to tell what type of processing we wish to perform on the file. +This argument is optional and if omitted then the file is opened in read-only mode. +See Table 2-9. + +*Table 2-9. Modes of Operations for File Types* + ++-------+-------------------------------------------------------------------------------+ +| Mode | Description | ++=======+===============================================================================+ +| 'r' | read only | ++-------+-------------------------------------------------------------------------------+ +| 'w' | write (Note:  This overwrites anything else in the file, so use with caution) | ++-------+-------------------------------------------------------------------------------+ +| 'a' | append | ++-------+-------------------------------------------------------------------------------+ +| 'r+' | read and write | ++-------+-------------------------------------------------------------------------------+ +| 'rb' | binary file read | ++-------+-------------------------------------------------------------------------------+ +| 'wb' | binary file write | ++-------+-------------------------------------------------------------------------------+ +| 'r+b' | binary file read and write | ++-------+-------------------------------------------------------------------------------+ + + +*Listing 2-31.*:: + + # Open a file and assign it to variable f + >>> f = open('newfile.txt','w') + +There are plenty of methods that can be used on file objects for manipulation of the file content. +We can call read([size]) on a file in order to read its content. +Size is an optional argument here and it is used to tell how much content to read from the file. +If it is omitted then the entire file content is read. +The readline() method can be used to read a single line from a file. +readlines([size]) is used to return a list containing all of the lines of data that are contained within a file. +Again, there is an optional size parameter that can be used to tell how many bytes from the file to read. +If we wish to place content into the file, the write(string) method does just that. +The write() method writes a string to the file. When writing to a file it is oftentimes important to know exactly what position in the file you are going to write to. There are a group of methods to help us out with positioning within a file using integers to represent bytes in the file. -The *tell()* method can be called on a file to give the file object’s current position. The integer returned is in bytes -and is an offset from the beginning of the file. The *seek(offset, from)* method can be used to change position in a -file. The *offset* is the number in bytes of the position you’d like to go, and *from* represents the place in the file -where you’d like to calculate the *offset* from. If *from* equals 0, then the offset will be calculated from the beginning -of the file. Likewise, if it equals 1 then it is calculated from the current file position, and 2 will be from the end of -the file. The default is 0 if *from* is omitted. - -Lastly, it is important to allocate and de-allocate resources efficiently in our programs or we will incur a memory overhead -and leaks. The *close()* method should be called on a file when we are through working with it. The proper methodology -to use when working with a file is to open, process, and then close each time. However, there are more efficient ways -of performing such tasks. In Chapter 5 we will discuss the use of context managers to perform the same functionality in -a more efficient manner. :: - - File Manipulation in Python - # Create a file, write to it, and then read it’s content - - >>> f = open('newfile.txt','r+') - >>> f.write('This is some new text for our file\n') - >>> f.write('This should be another line in our file\n') - # No lines will be read because we are at the end of the written content - >>> f.read() - '' - >>> f.readlines() - [] - >>> f.tell() - 75L - # Move our position back to the beginning of the file - >>> f.seek(0) - >>> f.read() - 'This is some new text for our file\nThis should be another line in our file\n' - >>> f.seek(0) - >>> f.readlines() - ['This is some new text for our file\n', 'This should be another line in our file\n'] - >>> f.close() +The tell() method can be called on a file to give the file object’s current position. +The integer returned is in a number of bytes and is an offset from the beginning of the file. +The seek(offset, from) method can be used to change position in a file. +The offset is the number in bytes of the position you’d like to go, and from represents the place in the file where you’d like to calculate the offset from. +If from equals 0, then the offset will be calculated from the beginning of the file. +Likewise, if it equals 1 then it is calculated from the current file position, and 2 will be from the end of the file. +The default is 0 if from is omitted. + +Lastly, it is important to allocate and de-allocate resources efficiently in our programs or we will incur a memory overhead and leaks. +Resources are usually handled a bit differently between CPython and Jython because garbage collection acts differently. +In CPython, it is not as important to worry about de-allocating resources as they are automatically de-allocated when they go out of scope. +The JVM does note immediately garbage collect, so proper de-allocation of resources is more important. +The close() method should be called on a file when we are through working with it. +The proper methodology to use when working with a file is to open, process, and then close each time. +However, there are more efficient ways of performing such tasks. +In Chapter 7 we will discuss the use of context managers to perform the same functionality in a more efficient manner. + +*Listing 2-32. File Manipulation in Python*:: + + # Create a file, write to it, and then read its content + >>> f = open('newfile.txt','r+') + >>> f.write('This is some new text for our file\n') + >>> f.write('This should be another line in our file\n') + #  No lines will be read because we are at the end of the written content + >>> f.read() + '' + >>> f.readlines() + [] + >>> f.tell() + 75L + + # Move our position back to the beginning of the file + >>> f.seek(0) + >>> f.read() + 'This is some new text for our file\nThis should be another line in our file\n' + >>> f.seek(0) + >>> f.readlines() + ['This is some new text for our file\n', 'This should be another line in our file\n'] + + # Closing the file to de-allocate + >>> f.close() Iterators ---------- - -The iterator type was introduced into Python back in version 2.2. It allows for iteration over Python containers. -All iterable containers have built-in support for the iterator type. For instance, sequence objects are iterable -as they allow for iteration over each element within the sequence. If you try to return an iterator on an object -that does not support iteration, you will most likely receive an *AttributeError* which tells you that __iter__ -has not been defined as an attribute for that object. - -Iterators allow for easy access to sequences and other iterable containers. Some containers such as dictionaries -have specialized iteration methods built into them as you have seen in previous sections. Iterator objects are -required to support two main methods that form the iterator protocol. Those methods are defined below. - - - -===================== =================================================================================================== ========================================= -Method Description -===================== =================================================================================================== ========================================= -iterator.__iter__() Returns the iterator object on a container. Required to allow use with *for* and *in* statements -iterator.next() Returns the next item from a container. -===================== =================================================================================================== ========================================= - -Table 2-10: Iterator Protocol - -To return an iterator on a container, just assign *container.__iter__()* to some variable. That variable will become -the iterator for the object. If using the *next()* call, it will continue to return the next item within the list -until all items have been retrieved. Once this occurs, a *StopIteration* error is issued. The important thing to note -here is that we are actually creating a copy of the list when we return the iterator and assign it to a variable. That -variable returns and removes an item from that copy each time the *next()* method is called on it. If we continue to -call *next()* on the iterator variable until the *StopIteration* error is issued, the variable will no longer contain -any items and is empty. +========= + +The iterator  was introduced into Python back in version 2.2. +It allows for iteration over Python containers. +All iterable containers have built-in support for the iterator type. +For instance, sequence objects are iterable as they allow for iteration over each element within the sequence. +If you try to return an iterator on an object that does not support iteration, you will most likely receive an AttributeError which tells you that __iter__ has not been defined as an attribute for that object. +It is important to note that Python method names using double-underscores are special  methods. +For instance, in Python a class can be initialized using the __init__() method. . .much like a Java constructor. +For more details on classes and special class methods, please refer to Chapter 7. + +Iterators allow for easy access to sequences and other iterable containers. +Some containers such as dictionaries have specialized iteration methods built into them as you have seen in previous sections. +Iterator objects are required to support two main methods that form the iterator protocol. +Those methods are defined below in Table 2-10.To return an iterator on a container, just assign container.__iter__()  to some variable. +That variable will become the iterator for the object. +This affords one the ability to pass iterators around, into functions and the like. +The iterator is then itself like a changing variable that maintains its state. +We can use work with the iterator without affecting the original object. +If using the next() call, it will continue to return the next item within the list until all items have been retrieved. +Once this occurs, a StopIteration  exception is issued. +The important thing to note here is that we are actually creating a copy of the list when we return the iterator and assign it to a variable. +That variable returns and removes an item from that copy each time the next() method is called on it. +If we continue to call next() on the iterator variable until the StopIteration error is issued, the variable will no longer contain any items and is empty. +For instance, if we created an iterator from a list then called the next() method on it until it had retrieved all values then the iterator would be empty and the original list would be left untouched. + +*Listing 2-33. Create an Iterator from a List and Use It*:: + + >>> hockey_roster = ['Josh', 'Leo', 'Frank', 'Jim', 'Vic'] + >>> hockey_itr = hockey_roster.__iter__() + >>> hockey_itr = hockey_roster.__iter__() + >>> hockey_itr.next() + 'Josh' + >>> for x in hockey_itr: + ...     print x + ... + Leo + Frank + Jim + Vic + + # Try to call next() on iterator after it has already used all of its elements + >>> hockey_itr.next() + Traceback (most recent call last): + File "", line 1, in + StopIteration + +*Listing 2-34. Iteration Over Sequence and List*:: + + # Iterate over a string and a list + >>> str_a = 'Hello' + >>> list_b = ['Hello','World'] + >>> for x in str_a: + ...     print x + ... + H + e + l + l + o + >>> for y in list_b: + ...     print y + '!' + ... + Hello! + World! Referencing and Copies ====================== -Creating copies and referencing items in the Python language is fairly straightforward. The only thing you’ll need to -keep in mind is that the techniques used to copy mutable and immutable objects differ a bit. - -In order to create a copy of an immutable object, you simply assign it to a different variable. The new variable is an -exact copy of the object. If you attempt to do the same with a mutable object, you will actually just create a reference -to the original object. Therefore, if you perform operations on the “copy” of the original then the same operation will -actually be performed on the original. This occurs because the new assignment references the same mutable object in memory -as the original. It is kind of like someone calling you by a different name. One person may call you by your birth name -and another may call you by your nickname, but both names will reference you of course. - -To effectively create a copy of a mutable object, you have two choices. You can either create what is known as a *shallow* -copy or a *deep* copy of the original object. The difference is that a shallow copy of an object will create a new object -and then populate it with references to the items that are contained in the original object. Hence, if you modify any of -those items then each object will be affected since they both reference the same items. A deep copy creates a new object -and then recursively copies the contents of the original object into the new copy. Once you perform a deep copy of an object -then you can perform operations on the copied object without affecting the original. You can use the *deepcopy* function in -the Python standard library to create such a copy. Let’s look at some examples of creating copies in order to give you a -better idea of how this works. :: - - - # Create an integer variable, copy it, and modify the copy - >>> a = 5 - >>> b = a - >>> print b - 5 - >>> b = a * 5 - >>> b - 25 - >>> a - 5 - - # Create a list, assign it to a different variable and then modify - >>> listA = [1,2,3,4,5,6] - >>> print listA - [1, 2, 3, 4, 5, 6] - >>> listB = listA - >>> print listB - [1, 2, 3, 4, 5, 6] - >>> del listB[2] - # Oops, we’ve altered the original list! - >>> print listA - [1, 2, 4, 5, 6] - - # Create a deep copy of the list and modify it - >>> import copy - >>> listA = [1,2,3,4,5,6] - >>> listB = copy.deepcopy(listA) - >>> print listA - [1, 2, 3, 4, 5, 6] - >>> del listB[2] - >>> print listB - [1, 2, 4, 5, 6] - >>> print listA - [1, 2, 3, 4, 5, 6] +Creating copies and referencing items in the Python language is fairly straightforward. +The only thing you’ll need to keep in mind is that the techniques used to copy mutable and immutable objects differ a bit. + +In order to create a copy of an immutable object, you simply assign it to a different variable. +The new variable is an exact copy of the object. +If you attempt to do the same with a mutable object, you will actually just create a reference to the original object. +Therefore, if you perform operations on the “copy” of the original then the same operation will actually be performed on the original. +This occurs because the new assignment references the same mutable object in memory as the original. +It is kind of like someone calling you by a different name. +One person may call you by your birth name and another may call you by your nickname, but both names will reference you of course. + +*Listing 2-35. Working with Copies*:: + + # Strings are immutable, so when you assign a string to another variable, it creates + a real copy + >>> mystring = "I am a string, and I am an immutable object" + >>> my_copy = mystring + >>> my_copy + 'I am a string, and I am an immutable object' + >>> mystring + 'I am a string, and I am an immutable object' + >>> my_copy = "Changing the copy of mystring" + >>> my_copy + 'Changing the copy of mystring' + >>> mystring + 'I am a string, and I am an immutable object' + + # Lists are mutable objects, so assigning a list to a variable + + # creates a reference to that list. Changing one of these variables will also + + # change the other one – they are just references to the same object. + >>> listA = [1,2,3,4,5,6] + >>> print listA + [1, 2, 3, 4, 5, 6] + >>> listB = listA + >>> print listB + [1, 2, 3, 4, 5, 6] + >>> del listB[2] + # Oops, we've altered the original list! + >>> print listA + [1, 2, 4, 5, 6] + + # If you want a new list which contains the same things, but isn't just a reference + + # to your original list, you need the copy module + >>> import copy + >>> a = [[]] + >>> b = copy.copy(a) + >>> b + [[]] + + # b is not the same list as a, just a copy + >>> b is a + False + + # But the list b[0] is the same the same list as the list a[0], and changing one will + + # also change the other. This is what is known as a shallow copy – a and b are + + # different at the top level, but if you go one level down, you have references to + + # to the same things – if you go deep enough, it's not a copy, + + # it's the same object. + >>> b[0].append('test') + >>> a + [['test']] + >>> b + [['test']] + +To effectively create a copy of a mutable object, you have two choices. +You can either create what is known as a shallow copy or a deep copy of the original object. +The difference is that a shallow copy of an object will create a new object and then populate it with references to the items that are contained in the original object. +Hence, if you modify any of those items then each object will be affected since they both reference the same items. + +A deep copy creates a new object and then recursively copies the contents of the original object into the new copy. +Once you perform a deep copy of an object then you can perform operations on any object contained in the copy without affecting the original. +You can use the deepcopy function in the copy module of the Python standard library to create such a copy. +Let’s look at some more examples of creating copies in order to give you a better idea of how this works. + +*Listing 2-36.*:: + + # Create an integer variable, copy it, and modify the copy + >>> a = 5 + >>> b = a + >>> print b + 5 + >>> b = a * 5 + >>> b + 25 + >>> a + 5 + + # Create a deep copy of the list and modify it + >>> import copy + >>> listA = [1,2,3,4,5,6] + >>> listB = copy.deepcopy(listA) + >>> print listB + [1, 2, 3, 4, 5, 6] + >>> del listB[2] + >>> print listB + [1, 2, 4, 5, 6] + >>> print listA + [1, 2, 3, 4, 5, 6] Garbage Collection ================== -This is one of those major differences between CPython and Jython. Unline CPython, Jython does not implement a -reference counting technique for aging out or garbage collection unused objects. Instead, Jython makes use of the -garbage collection mechanisms that the Java platform provides. When a Jython object becomes stale or unreachable, -the JVM may or may not reclaim it. One of the main aspects of the JVM that made developers so happy in the early -days is that there was no longer a need to worry about cleaning up after your code. In the C programming language, -one must maintain an awareness of which objects are currently being used so that when they are no longer needed the -program would perform some clean up. Not in the Java world, the gc thread on the JVM takes care of all garbage -collection and cleanup for you. This is a benefit of using the Jython implementation; unlike Python there is no need -to worry about reference counting. - -Even though we haven’t spoken about classes yet, it is a good time to mention that Jython provides a mechanism for -object cleanup. A finalizer method can be defined in any class in order to ensure that the garbage collector performs -specific tasks. Any cleanup code that needs to be performed when an object goes out of scope can be placed within -this finalizer method. It is important to note that the finalizer method cannot be counted on as a method which will -always be invoked when an object is stale. This is the case because the finalizer method is invoked by the Java garbage -collection thread, and there is no way to be sure when and if the garbage collector will be called on an object. Another -issue of note with the finalizer is that they incur a performance penalty. If you’re coding an application that already -performs poorly then it may not be a good idea to throw lots of finalizers into it. - - -Below is an example of a Jython finalizer. It is an instance method that must be named __del__. :: - - class MyClass: - def __del__(self): - pass # Perform some cleanup here +This is one of those major differences between CPython and Jython. +In CPython, an object is garbage collected when it goes out of scope or is no longer needed. +This occurs automatically and rarely needs to be tracked by the developer. +Behind the scenes, CPython uses a reference counting technique to maintain a count on each object which effectively determines if the object is still in use. +Unlike CPython, Jython does not implement a reference counting technique for aging out or garbage collection unused objects. +Instead, Jython makes use of the garbage collection mechanisms that the Java platform provides. +When a Jython object becomes stale or unreachable, the JVM may or may not reclaim it. +One of the main aspects of the JVM that made developers so happy in the early days is that there was no longer a need to worry about cleaning up after your code. +In the C programming language, one must maintain an awareness of which objects are currently being used so that when they are no longer needed the program would perform some clean up. +Not in the Java world, the gc thread on the JVM takes care of all garbage collection and cleanup for you. + +Even though we haven’t spoken about classes in detail yet, you saw a short example of how them in Chapter 1. +It is a good time to mention that Python provides a mechanism for object cleanup. +A finalizer method can be defined in any class in order to ensure that the garbage collector performs specific tasks. +Any cleanup code that needs to be performed when an object goes out of scope can be placed within this finalizer method. +It is important to note that the finalizer method cannot be counted on as a method which will always be invoked when an object is stale. +This is the case because the finalizer method is invoked by the Java garbage collection thread, and there is no way to be sure when and if the garbage collector will be called on an object. +Another issue of note with the finalizer is that they incur a performance penalty. +If you’re coding an application that already performs poorly then it may not be a good idea to throw lots of finalizers into it. + +The following is an example of a Python finalizer. +It is an instance method that must be named __del__. + +*Listing 2-37. Python Finalizer Example*:: + + class MyClass: + def __del__(self): + pass    # Perform some cleanup here + +The downside to using the JVM garbage collection mechanisms is that there is really no guarantee as to when and if an object will be reclaimed. +Therefore, when working with performance intensive objects it is best to not rely on a finalizer to be called. +It is always important to ensure that proper coding techniques are used in such cases when working with objects like files and databases. +Never code the close() +method for a file into a finalizer because it may cause an issue if the finalizer is not invoked. +Best practice is to ensure that all mandatory cleanup activities are performed before a finalizer would be invoked. -The downside to using the JVM garbage collection mechanisms is that there is really no guarantee as to when and if an -object will be reclaimed. Therefore, when working with performance intensive objects it is best to not rely on a finalizer -to be called. It is always important to ensure that proper coding techniques are used in such cases when working with objects -like files and databases. Never code the close() method for a file into a finalizer because it may cause an issue if the -finalizer is not invoked. Best practice is to ensure that all mandatory cleanup activities are performed before a finalizer -would be invoked. - Summary ======= -A lot of material was covered in this chapter. You should be feeling better acquainted with Python after reading through -this material. We began the chapter by covering the basics of assignment an assigning data to particular objects or data types. -We learned that working with each type of data object opens different doors as the way we work with each type of data object -differs. Our journey into data objects began with numbers and strings, and we discussed the many functions available to the -string object. We learned that strings are part of the sequence family of Python collection objects along with lists and tuples. -We covered how to create and work with lists, and the variety of options available to us when using lists. We discovered that -list comprehensions can help us create copies of a given list and manipulate their elements according to an expression or function. -After discussing lists, we went on to discuss dictionaries, sets and tuples. These objects give us different alternatives to -the list object. - -After discussing the collection types, we learned that Jython has it’s own set of collection objects that differ from those in -Python. We can leverage the advantage of having the Java platform at our fingertips and use Java collection types from within -Jython. Likewise, we can pass a Jython collection to Java as a *jarray* object. We followed that topic with a discussion of file -objects and how they are used in Python. The topic of iteration and creating iterables followed. We finished up by discussing -referencing, copies, and garbage collection. We saw how creating different copies of objects does not always give you what you’d -expect, and that Jython garbage collection differs quite a bit from that of Python. - -The next chapter will help you to combine some of the topics you’ve learned about in this chapter as you will learn how to define -expressions and work with control flow. - - - - - - +A lot of material was covered in this chapter. +You should be feeling better acquainted with Python after reading through this material. +We began the chapter by covering the basics of assignment an assigning data to particular objects or data types. +You learned that working with each type of data object opens different doors as the way we work with each type of data object differs. +Our journey into data objects began with numbers and strings, and we discussed the many methods available to the string object. +We learned that strings are part of the sequence family of Python collection objects along with lists and tuples. +We covered how to create and work with lists, and the variety of options available to us when using lists. +You discovered that list comprehensions can help create copies of a given list and manipulate their elements according to an expression or function. +After discussing lists, we went on to discuss dictionaries, sets and tuples. + +After discussing the collection types, we learned that Jython has its own set of collection objects that differ from those in Python. +We can leverage the advantage of having the Java platform at our fingertips and use Java collection types from within Jython. +We finished up by discussing referencing, copies, and garbage collection. +Creating different copies of objects does not always give you what you’d expect, and that Jython garbage collection differs quite a bit from that of Python. + +The next chapter will help you to combine some of the topics you’ve learned about in this chapter as you will learn how to define expressions and work with control flow. diff --git a/DefiningFunctionsandUsingBuilt-Ins.rst b/DefiningFunctionsandUsingBuilt-Ins.rst index 5003b05..147c812 100644 --- a/DefiningFunctionsandUsingBuilt-Ins.rst +++ b/DefiningFunctionsandUsingBuilt-Ins.rst @@ -1,54 +1,47 @@ -Chapter 4: Defining Functions and Using Built-Ins -================================================== - - -Functions are the fundamental unit of work in Python. A function in Python -performs a task and returns a result. In this chapter, -we will start with the basics of functions. Then we look at using the -builtin functions. These are the core functions that are always -available, meaning they don't require an explicit import into your -namespace. Next we will look at some alternative ways of defining functions, such as -lambdas and classes. We will also look at more advanced types of -functions, namely closures and generator functions. - -As you will see, functions are very easy to define and use. Python -encourages an incremental style of development that you can leverage -when writing functions. So how does this work out in practice? Often when writing a function -it may make sense to start with a sequence of statements and just try -it out in a console. Or maybe just write a short script in an -editor. The idea is to just to prove a path and answer such questions -as, "Does this API work in the way I expect?" Because top-level code in -a console or script works just like it does in a function, it's easy -to later isolate this code in a function body and then package it as a -function, maybe in a libary, or as a method as part of a class. The -ease of doing this style of development is one aspect that makes -Python such a joy to program in. And of course in the Jython -implementation, it's easy to use this technique within the context of any Java -library. - -An important thing to keep in mind is that functions are first-class objects in -Python. They can be passed around just like any other variable, resulting in -some very powerful solutions. We'll see some examples of using functions in such -a way later in this chapter. +Chapter 4: Defining Functions and Using Built-ins +++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functions are the fundamental unit of work in Python. +A function in Python performs a task and returns a result. +In this chapter, we will start with the basics of functions. +Then we look at using the built-in functions. +These are the core functions that are always available, meaning they don’t require an explicit import into your namespace. +Next we will look at some alternative ways of defining functions, such as lambdas and classes. +We will also look at more advanced types of function, namely closures and generator functions. + +As you will see, functions are very easy to define and use. +Python encourages an incremental style of development that you can leverage when writing functions. +So how does this work out in practice? +Often when writing a function it may make sense to start with a sequence of statements and just try it out in a console. +Or maybe just write a short script in an editor. +The idea is to just to prove a path and answer such questions as, “Does this API work in the way I expect?” +Because top-level code in a console or script works just like it does in a function, it’s easy to later isolate this code in a function body and then package it as a function, maybe in a library, or as a method as part of a class. +The ease of doing this style of development is one aspect that makes Python such a joy use. +And of course in the Jython implementation, it’s easy to use this technique within the context of any Java library. + +An important thing to keep in mind is that functions are first-class objects in Python. +They can be passed around just like any other variable, resulting in some very powerful solutions. +We’ll see some examples of using functions in such a way later in this chapter. Function Syntax and Basics --------------------------- +========================== -Functions are usually defined by using the *`def`* keyword, the name -of the function, its parameters (if any), and the body of code. We -will start by looking at this example function:: +Functions are usually defined by using the ``def`` keyword, the name of the function, its parameters (if any), and the body of code. +We will start by looking at this example function: + +*Listing 4-1.* +:: def times2(n): return n * 2 +In this example, the function name is ``times2`` and it accepts a parameter n. +The body of the function is only one line, but the work being done is the multiplication of the parameter by the number 2. +Instead of storing the result in a variable, this function simply returns it to the calling code. +An example of using this function would be as follows. -In this example, the function name is *times2* and it accepts a parameter *n*. -The body of the function is only one line, but the work being done is the multiplication -of the parameter by the number 2. Instead of storing the result in a variable, -this function simply returns it to the calling code. An example of using this function -would be as follows. - +*Listing 4-2.* :: >>> times2(8) @@ -57,69 +50,67 @@ would be as follows. >>> x 10 -Normal usage can treat function definitions as being very simple. But -there's subtle power in every piece of the function definition, due to -the fact that Python is a dynamic language. We look at these pieces -from both a simple (the more typical case) and a more advanced -perspective. We will also look at some alternative ways of creating functions in a -later section. +Normal usage can treat function definitions as being very simple. +But there’s subtle power in every piece of the function definition, due to the fact that Python is a dynamic language. +We look at these pieces from both a simple (the more typical case) and a more advanced perspective. +We will also look at some alternative ways of creating functions in a later section. -The `def` Keyword -~~~~~~~~~~~~~~~~~ +The ``def`` Keyword +------------------- -Using *`def`* for *define* seems simple enough, and this keyword -certainly can be used to declare a function just like you would in a -static language. You should write most code that way in fact. +Using ``def`` for *define* seems simple enough, and this keyword certainly can be used to declare a function just like you would in a static language. +You should write most code that way in fact. -However, the more advanced usage is that a function definition can -occur at any level in your code and be introduced at any time. Unlike -the case in a language like C or Java, function definitions are not -declarations. Instead they are *executable statements*. You can nest -functions, and we'll describe that more when we talk about nested -scopes. And you can do things like conditionally define them. +However, a function definition can occur at any level in your code and be introduced at any time. +Unlike the case in a language like C or Java, function definitions are not declarations. +Instead they are *executable statements*. +You can nest functions, and we'll describe that more when we talk about nested scopes. +And you can do things like conditionally define them. -This means it's perfectly valid to write code like the following: +This means it’s perfectly valid to write code like the following: +*Listing 4-3.* :: if variant: def f(): print "One way" - else: + else: def f(): print "or another" -Please note, regardless of when and where the definition occurs, -including its variants as above, the function definition will be -compiled into a function object at the same time as the rest of the -module or script that the function is defined in. +Please note, regardless of when and where the definition occurs, including its variants as above, the function definition will be compiled into a function object at the same time as the rest of the module or script that the function is defined in. Naming the Function -~~~~~~~~~~~~~~~~~~~ +------------------- + +We will describe this more in a later section, but the ``dir`` built-in function will tell us about the names defined in a given namespace, defaulting to the module, script, or console environment we are working in. +With this new ``times2`` function defined above, we now see the following (at least) in the console namespace: -We will describe this more in a later section, but the ``dir`` builtin -function will tell us about the names defined in a given namespace, -defaulting to the module, script, or console environment we are -working in. With this new ``times2`` function defined above, we now -see the following (at least) in the console namespace:: +*Listing 4-4.* +:: - >>> dir() - ['__doc__', '__name__', 'times2'] + >>> dir() + ['__doc__', '__name__', 'times2'] We can also just look at what is bound to that name: +*Listing 4-5.* :: >>> times2 -(This object is further introspectable. Try ``dir(times2)`` and go -from there.) +(This object is further introspectable. +Try ``dir(times2)`` and go from there.) +We can reference the function by supplying the function name such as we did in the example above. +However, in order to call the function and make it perform some work, we need to supply the ``()`` to the end of the name. We can also redefine a function at any time: +*Listing 4-6.* :: >>> def f(): print "Hello, world" @@ -129,81 +120,92 @@ We can also redefine a function at any time: >>> f() Hi, world -This is true not just of running it from the console, but any module -or script. The original version of the function object will persist -until it's no longer referenced, at which point it will be ultimately -be garbage collected. In this case, the only reference was the name -``f``, so it became available for GC immediately upon rebind. +This is true not just of running it from the console, but any module or script. +The original version of the function object will persist until it’s no longer referenced, at which point it will be ultimately be garbage collected. +In this case, the only reference was the name ``f``, so it became available for GC immediately upon rebind. -What's important here is that we simply rebound the name. First it -pointed to one function object, then another. We can see that in -action by simply setting another name (equivalently, a variable) to -``times2``. +What’s important here is that we simply rebound the name. +First it pointed to one function object, then another. +We can see that in action by simply setting another name (equivalently, a variable) to ``times2``. +*Listing 4-7.* :: >>> t2 = times2 >>> t2(5) 10 -This makes passing a function as a parameter very easy, for a callback -for example. But first, we need to look at function parameters in more -detail. +This makes passing a function as a parameter very easy, for a callback for example. +A callback is a function that can be invoked by a function to perform a task and then turn around and invoke the calling function, thus the callback. +Let’s take a look at function parameters in more detail. + .. sidebar:: Function Metaprogramming - A given name can only be associated with one function at a time, so - can't overload a function with multiple definitions. If you were to - define two or more functions with the same name, the last one - defined is used, as we saw. + A given name can only be associated with one function at a time, so can’t overload a function with multiple definitions. + If you were to define two or more functions with the same name, the last one defined is used, as we saw. - However, it is possible to overload a function, or otherwise - genericize it. You simply need to create a dispatcher function that - then dispatches to your set of corresponding functions. + However, it is possible to overload a function, or otherwise genericize it. + You simply need to create a dispatcher function that then dispatches to your set of corresponding functions. + Another way to genericize a function is to make use of the simplegeneric module which lets you define simple single-dispatch generic functions. + For more information, please see the simplegeneric package in the Python Package Index. Function Parameters and Calling Functions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +----------------------------------------- -When defining a function, you specify the parameters it -takes. Typically you will see something like the following. The syntax -is familar: +When defining a function, you specify the parameters it takes. +Typically you will see something like the following. +The syntax is familiar: :: def tip_calc(amt, pct) +As mentioned previously, calling functions is also done by placing parentheses after the function name. +For example, for the function ``x`` with parameters ``a,b,c`` that would be ``x(a,b,c)``. +Unlike some other dynamic languages like Ruby and Perl, the use of parentheses is required syntax (due the function name being just like any other name). -Calling a function is symmetric. -You can call a function. The parentheses are mandatory. Calling functions is also done by with a familiar syntax. For example, -for the function x with parameters ``a,b,c`` that would be -x(a,b,c). Unlike some other dynamic languages like Ruby and Perl, the -use of parentheses is required syntax (due the function name being -just like any other name). - -Objects are strongly typed, as we have seen. But function parameters, -like names in general in Python, are not typed. This means that -any parameter can refer to any type of object. +Objects are strongly typed, as we have seen. +But function parameters, like names in general in Python, are not typed. +This means that any parameter can refer to any type of object. -We see this play out in the ``times2`` function. The ``*`` operator -not only means multiply for numbers, it also means repeat for -sequences (like strings and lists). So you can use the ``times2`` -function as follows:: +We see this play out in the ``times2`` function. +The ``*`` operator not only means multiply for numbers, it also means repeat for sequences (like strings and lists). +So you can use the ``times2`` function as follows:: - >>> times2(4) - 8 - >>> times2('abc') - 'abcabc' - >>> times2([1,2,3]) - [1, 2, 3, 1, 2, 3] + >>> times2(4) + 8 + >>> times2('abc') + 'abcabc' + >>> times2([1,2,3]) + [1, 2, 3, 1, 2, 3] + +All parameters in Python are passed by reference. +This is identical to how Java does it with object parameters. +However, while Java does support passing unboxed primitive types by value, there are no such entities in Python. +Everything is an object in Python. +It is important to remember that immutable objects cannot be changed, and therefore, if we pass a string to a function and alter it, a copy of the string is made and the changes are applied to the copy. + +*Listing 4-9.* +:: -All parameters in Python are passed by reference. This is identical to -how Java does it with object parameters. However, while Java does -support passing unboxed primitive types by value, there are no such -entities in Python. Everything is an object in Python. + # The following function changes the text of a string by making a copy + # of the string and then altering it. The original string is left + # untouched as it is immutable. + >>> def changestr(mystr): + ...     mystr = mystr + '_changed' + ...     print 'The string inside the function: ', mystr + ...     return + >>> mystr = 'hello' + >>> changestr(mystr) + The string inside the function:  hello_changed + >>> mystr + 'hello' Functions are objects too, and they can be passed as parameters: +*Listing 4-10.* :: # Define a function that takes two values and a mathematical function @@ -223,49 +225,42 @@ Functions are objects too, and they can be passed as parameters: ... >>> perform_calc(2, 4, add_values) 6 - >>> - -If you have more than two or so arguments, it often makes more sense -to call a function by parameter, rather than by the defined -order. This tends to create more robust code. So if you have a -function ``draw_point(x,y)``, you might want to call it as -``draw_point(x=10,y=20)``. +If you have more than two or so arguments, it often makes more sense to call a function by named values, rather than by the positional parameters. +This tends to create more robust code. +So if you have a function ``draw_point(x,y)``, you might want to call it as ``draw_point(x=10,y=20)``. -Defaults further simplify calling a function. You use the form of -``param=default_value`` when defining the function. For instance, you -might take our ``times2`` function and generalize it. +Defaults further simplify calling a function. +You use the form of ``param=default_value`` when defining the function. +For instance, you might take our ``times2`` function and generalize it. +*Listing 4-11.* :: def times_by(n, by=2): return n * by -This function is equivalent to ``times2`` when called using that -default value. - -There's one point to remember that oftens trips up developers. The -default value is initialized exactly once, when the function is -defined. That's certainly fine for immutable values like numbers, -strings, tuples, frozensets, and similar objects. But you need to -ensure that if the default value is mutable, that it's being used in -this fashion correctly. So a dictionary for a shared cache makes -sense. But this mechanism won't work for but a list where we expect it -is initialized to an empty list upon invocation. If you're doing that, -you need to write that explicitly in your code. - -Lastly, a function can take an unspecified number of ordered -arguments, through ``*args``, and keyword args, through -``**kwargs``. These parameter names (``args`` and ``kwargs``) are conventional, -so you can use whatever name makes sense for your function. +This function is equivalent to ``times2`` when called using that default value. + +There’s one point to remember that often trips up developers. +The default value is initialized exactly once, when the function is defined. +That’s certainly fine for immutable values like numbers, strings, tuples, frozensets, and similar objects. +But you need to ensure that if the default value is mutable, that it’s being used correctly. +So a dictionary for a shared cache makes sense. +But this mechanism won’t work for a list where we expect it is initialized to an empty list upon invocation. +If you’re doing that, you need to write that explicitly in your code. +As a best practice, use None as the default value rather than a mutable object, and check at the start of the body of your function for the case ``value = None`` and set the variable to your mutable object there. + +Lastly, a function can take an unspecified number of ordered arguments, through ``*args``, and keyword args, through ``**kwargs``. +These parameter names (``args`` and ``kwargs``) are conventional, so you can use whatever name makes sense for your function. The markers ``*`` and ``**`` are used to to determine that this functionality should be used. -The single ``*`` argument allows for passing a sequence of values, and a double ``**`` argument -allows for passing a dictionary of names and values. If either of these types -of arguments are specified, they must follow any single arguments in the function -declaration. Furthermore, the double ``**`` must follow the single ``*``. +The single ``*`` argument allows for passing a sequence of values, and a double ``**`` argument allows for passing a dictionary of names and values. +If either of these types of argument is specified, they must follow any single arguments in the function declaration. +Furthermore, the double ``**`` must follow the single ``*``. Definition of a function that takes a sequence of numbers: +*Listing 4-12.* :: def sum_args(*nums): @@ -279,22 +274,16 @@ Calling the function using a sequence of numbers: >>> sum_args(*seq) 18 -.. note:: - - This is not exhaustive. You can also use tuple parameters, but in - practice, they are not typically used, and were removed in Python - 3. We recommend you don't use them. For one thing, they cannot be - properly introspected from Jython. Recursive Function Calls -^^^^^^^^^^^^^^^^^^^^^^^^ +======================== -It is also quite common to see cases in which a function calls itself -from inside the function body. This type of function call is known as a recursive -function call. Let's take a look at a function that computes the factorial of -a given argument. This function calls itself passing in the provided argument -decremented by 1 until the argument reaches the value of 0 or 1. +It is also quite common to see cases in which a function calls itself from inside the function body. +This type of function call is known as a recursive function call. +Let’s take a look at a function that computes the factorial of a given argument. +This function calls itself passing in the provided argument decremented by 1 until the argument reaches the value of 0 or 1. +*Listing 4-13.* :: def fact(n): @@ -303,38 +292,38 @@ decremented by 1 until the argument reaches the value of 0 or 1. else: return n * fact(n - 1) -It is important to note that Jython is not unlike CPython in that -it is ultimately stack based. Stacks are regions of memory where data is added -and removed in a last-in first-out manner. If a recursive function calls itself too many times -then it is possible to exhaust the stack, which results in an *OutOfMemoryError*. -Therefore, be cautious when developing software using recursion. - +It is important to note that Jython is like CPython in that it is ultimately stack based. +Stacks are regions of memory where data is added and removed in a last-in first-out manner. +If a recursive function calls itself too many times then it is possible to exhaust the stack, which results in an ``OutOfMemoryError``. +Therefore, be cautious when developing software using deep recursion. Function Body -~~~~~~~~~~~~~ +------------- + +This section will break down the different components that comprise the body of a function. +The body of a function is the part that performs the work. +Throughout the next couple of sub-sections, you will see that a function body can be comprised of many different parts. -This section will break down the different components that comprise the body of -a function. The body of a function is the part that performs the work. Throughout -the next couple of sub-sections, you will see that a function body can be comprised -of many different parts. Documenting Functions -^^^^^^^^^^^^^^^^^^^^^ +===================== -First, you should specify a document string for the function. The -docstring, if it exists, is a string that occurs as the first value of -the function body. +First, you should specify a document string for the function. +The docstring, if it exists, is a string that occurs as the first value of the function body. +*Listing 4-14.* :: def times2(n): """Given n, returns n * 2""" return n * 2 -As mentioned in chapter 1, by convention we use triple-quoted strings, even if your docstring is -not multiline. If it is multiline, this is how we recommend you format it. +As mentioned in Chapter 1, by convention we use triple-quoted strings, even if your docstring is not multiline. +If it is multiline, this is how we recommend you format it. +For more information, please take a look at PEP 257 (www.python.org/dev/peps/pep-0257). +*Listing 4-15.* :: def fact(n): @@ -350,15 +339,12 @@ not multiline. If it is multiline, this is how we recommend you format it. else: return n * fact(n - 1) -Any such docstring, but with leading indendetation stripped, becomes -the ``__doc__`` attribute of that function object. Incidentally, -docstrings are also used for modules and classes, and they work -exactly the same way. +Any such docstring, but with leading indentation stripped, becomes the ``__doc__`` attribute of that function object. +Incidentally, docstrings are also used for modules and classes, and they work exactly the same way. -You can now use the ``help`` built-in function to get the docstring, -or see them from various IDEs like PyDev for Eclipse and nbPython for -NetBeans as part of the auto-complete. +You can now use the ``help`` built-in function to get the docstring, or see them from various IDEs like PyDev for Eclipse and nbPython for NetBeans as part of the auto-complete. +*Listing 4-16.* :: >>> help(fact) @@ -371,15 +357,15 @@ NetBeans as part of the auto-complete. Returning Values -^^^^^^^^^^^^^^^^ +================ -All functions return some value. In ``times2``, we use the ``return`` statement -to exit the function with that value. Functions can easily return multiple -values at once by returning a tuple or -other structure. The following is a simple example of a function that returns more -than one value. In this case, the tip calculator returns the result of a tip based -upon two percentage values. +All functions return some value. +In ``times2``, we use the ``return`` statement to exit the function with that value. +Functions can easily return multiple values at once by returning a tuple or other structure. +The following is a simple example of a function that returns more than one value. +In this case, the tip calculator returns the result of a tip based upon two percentage values. +*Listing 4-17.* :: >>> def calc_tips(amount): @@ -388,10 +374,10 @@ upon two percentage values. >>> calc_tips(25.25) (4.545, 5.050000000000001) +A function can return at any time, and it can also return any object as its value. +So you can have a function that looks like the following: -A function can return at any time, and it can also return any object as its value. So you can have a -functions that look like the following: - +*Listing 4-18.* :: >>> def check_pos_perform_calc(num1, num2, func): @@ -408,13 +394,11 @@ functions that look like the following: >>> check_pos_perform_calc(3, -44, mult_values) 'Only positive numbers can be used with this function!' +If a ``return`` statement is not used, the value ``None`` is returned. +There is no equivalent to a void method in Java, because every function in Python returns a value. +However, the Python console will not show the return value when it’s None, so you need to explicitly print it to see what is returned. -If a return statement is not used, the value ``None`` is returned. There is no -equivalent to a ``void`` method in Java, because every function in Python -returns a value. However, the Python console will not show the return -value when it's ``None``, so you need to explicitly print it to see -what is returned. - +*Listing 4-19.* :: >>> do_nothing() @@ -423,18 +407,18 @@ what is returned. Introducing Variables -^^^^^^^^^^^^^^^^^^^^^ +===================== -A function introduces a scope for new names, such as variables. Any -names that are created in the function are only visible within that -scope. In the following example, the sq variable is defined within the -scope of the function definition itself. If we try to use it outside -of the function then we'll receive an error. +A function introduces a scope for new names, such as variables. +Any names that are created in the function are only visible within that scope. +In the following example, the sq variable is defined within the scope of the function definition itself. +If we try to use it outside of the function then we’ll receive an error. +*Listing 4-20.* :: >>> def square_num(num): - ... """ Return the square of a number""" + ... """ Return the square of a number""" ... sq = num * num ... return sq ... @@ -442,34 +426,26 @@ of the function then we'll receive an error. 1225 >>> sq Traceback (most recent call last): - File "", line 1, in - NameError: name 'sq' is not defined +  File "", line 1, in + NameError: name 'sq' is not defined .. sidebar:: Global Variables - global keyword - [Useful for certain circumstances, certainly not - core/essential, much like nonlocal in Py3K, so let's not put too - much focus on it.] - - The `global` keyword is used to declare that a variable name is from - the module scope (or script) containing this function. Using - `global` is rarely necessary in practice, since it is not necessary - if the name is called as a function or an attribute is accessed - (through dotted notation). + The global keyword is used to declare that a variable name is from the module scope (or script) containing this function. + Using global is rarely necessary in practice, since it is not necessary if the name is called as a function or an attribute is accessed (through dotted notation). - This is a good example of where Python is providing a complex - balancing between a complex idea - the lexical scoping of names, and - the operations on them - and the fact that in practice it is doing - the right thing. + This is a good example of where Python is providing a complex balancing between a complex idea -- the lexical scoping of names, and the operations on them—and the fact that in practice it is doing the right thing. - Here is an example of using a global variable in the same *square_num()* function. + Here is an example of using a global variable in the same ``square_num()`` + function. + *Listing 4-21.* :: - + >>> sq = 0 >>> def square_num(n): - ... global sq - ... sq = n * n + ...     global sq + ...     sq = n * n ... return sq ... >>> square_num(10) @@ -479,55 +455,41 @@ of the function then we'll receive an error. Other Statements -^^^^^^^^^^^^^^^^ +================ -What can go in a function body? Pretty much any statement, -including material that we will cover later in this book. So you can -define functions or classes or use even import, within the scope of -that function. +What can go in a function body? +Pretty much any statement, including material that we will cover later in this book. +So you can define functions or classes or use even import, within the scope of that function. -In particular, performing a potentially expensive operation like -import as last as possible, can reduce the startup time of your -app. It's even possible it will be never needed too. +In particular, performing a potentially expensive operation like import as least as possible, can reduce the startup time of your app. +It’s even possible it will be never needed too. -There are a couple of exceptions to this rule. In both cases, these -statements must go at the beginning of a module, similar to what we -see in a static language like Java: +There are a couple of exceptions to this rule. +In both cases, these statements must go at the beginning of a module, similar to what we see in a static language like Java: -* Compiler directives. Python supports a limited set of compiler - directives that have the provocative syntax of ``from __future__ - import X``; see :pep:`236`. These are features that will be - eventually be made available, generally in the next minor - revision (such as 2.5 to 2.6). In addition, it's a popular place - to put Easter eggs, such as ``from __future__ import - braces``. (Try it in the console, which also relaxes what it - means to be performed at the beginning.) +* Compiler directives. + Python supports a limited set of compiler directives that have the provocative syntax of ``from __future__ import X``; see :pep:`236`. + These are features that will be eventually be made available, generally in the next minor revision (such as 2.5 to 2.6). In addition, it’s a popular place to put Easter eggs, such as ``from __future__ import braces``. + (Try it in the console, which also relaxes what it means to be performed at the beginning.) -* Source encoding declaration. Although technically not a - statement -- it's in a specially parsed comment -- this must go - in the first or second line. +* Source encoding declaration. + Although technically not a statement -- it’s in a specially parsed comment -- this must go in the first or second line. -Empty Functions -^^^^^^^^^^^^^^^ +Empty Functions +=============== It is also possible to define an empty function. -Why have a function that does nothing? As in math, it's useful to have -an operation that stands for doing nothing, like "add zero" or -"multiply by one". These identity functions eliminate special -cases. Likewise, as see with ``empty_callback``, we may need to -specify a callback function when calling an API, but nothing actually -needs to be done. By passing in an empty function -- or having this be -the default -- we can simplify the API. An empty function still needs something -in its body. You can use the ``pass`` statement. +Why have a function that does nothing? +As in math, it’s useful to have an operation that stands for doing nothing, like “add zero” or “multiply by one.” These identity functions eliminate special cases. Likewise, as see with ``empty_callback``, we may need to specify a callback function when calling an API, but nothing actually needs to be done. By passing in an empty function—or having this be the default—we can simplify the API. An empty function still needs something in its body. You can use the pass statement. +*Listing 4-22.* :: def do_nothing(): pass # here's how to specify an empty body of code -Or you can just have a docstring for the function body as in the following -example. +Or you can just have a docstring for the function body as in the following example. :: @@ -536,157 +498,113 @@ example. but have nothing further to do. """ -Miscellaneous Information for the Curious Reader ------------------------------------------------- -As you already know, Jython is an interpreted language. That is, the Python -code that we write for a Jython application is ultimately compiled down into -Java bytecode when our program is run. So oftentimes it is useful for Jython -developers to understand what is going on when this code is interpreted into -Java bytecode. - -What do functions look like from Java? They are instances of an object named -PyObject, supporting the ``__call__`` method. - -Additional introspection is available. If a function object is just -a standard function written in Python, it will be of class -PyFunction. A builtin function will be of class -PyBuiltinFunction. But don't assume that in your code, because many -other objects support the function interface (``__call__``), and -these potentially could be proxying, perhaps several layers deep, a -given function. You can only assume it's a PyObject. - -Much more information is available by going to the Jython wiki. You can also -send questions to the jython-dev mailing list for more specifics. - - -Builtin Functions ------------------ - -Builtin functions are those functions that are always in the Python -namespace. In other words, these functions -- and builtin exceptions, -boolean values, and some other objects -- are the only truly globally -defined names. If you are familiar with Java, they are somewhat like -the classes from ``java.lang``. - -Builtins are rarely sufficient, however; even a simple command line -script generally needs to parse its arguments or read in from its -standard input. So for this case you would need to ``import sys``. And -in the context of Jython, you will need to import the relevant Java -classes you are using, perhaps with ``import java``. But the -builtin functions are really the core function that almost all Python -code uses. - -The documentation for covering all of the built-in functions that -are available is extensive. However, it has been included in this book as -Appendix C. It should be easy to use Appendix C as a reference when using -a built-in function, or for choosing which built-in function to use. +Miscellaneous Information for the Curious Reader +================================================ + +As you already know, Jython is an interpreted language. +That is, the Python code that we write for a Jython application is ultimately compiled down into Java bytecode when our program is run. +So oftentimes it is useful for Jython developers to understand what is going on when this code is interpreted into Java bytecode. +What do functions look like from Java? +They are instances of an object named PyObject, supporting the ``__call__`` method. + +Additional introspection is available. +If a function object is just a standard function written in Python, it will be of class ``PyFunction``. +A built-in function will be of class ``PyBuiltinFunction``. +But don’t assume that in your code, because many other objects support the function interface (``__call__``), and these potentially could be proxying, perhaps several layers deep, a given function. +You can only assume it’s a ``PyObject``. +Much more information is available by going to the Jython wiki. +You can also send questions to the ``jython-dev`` mailing list for more specifics. + + +Built-in Functions +================== + +Built-in functions are those functions that are always in the Python namespace. +In other words, these functions—and built-in exceptions, boolean values, and some other objects—are the only truly globally defined names. +If you are familiar with Java, they are somewhat like the classes from java.lang. +Built-ins are rarely sufficient, however; even a simple command line script generally needs to parse its arguments or read in from its standard input. +So for this case you would need to import sys. +And in the context of Jython, you will need to import the relevant Java classes you are using, perhaps with ``import java``. +But the built-in functions are really the core function that almost all Python code uses. +The documentation for covering all of the built-in functions that are available is extensive. +However, it has been included in this book as Appendix C. +It should be easy to use Appendix C as a reference when using a built-in function, or for choosing which built-in function to use. Alternative Ways to Define Functions ------------------------------------- +==================================== -The *`def`* keyword is not the only way to define a function. Here are -some alternatives: +The ``def`` keyword is not the only way to define a function. +Here are some alternatives: * Lambda Functions: - -*`lambda`* functions. The *`lambda`* keyword creates an unnamed -function. Some people like this because it requires minimal -space, especially when used in a callback. - - + The ``lambda`` keyword creates an unnamed function. + Some people like this because it requires minimal space, especially when used in a callback. * Classes: - -In addition, we can also create objects with classes -whose instance objects look like ordinary functions. Objects -supporting the __call__ protocol. This will be covered in a -later chapter. For Java developers, this is familiar. Classes -implement such single-method interfaces as Callable or Runnable. - + In addition, we can also create objects with classes whose instance objects look like ordinary functions. + Objects supporting the ``__call__`` protocol. + For Java developers, this is familiar. + Classes implement such single-method interfaces as ``Callable`` or ``Runnable``. * Bound Methods: - -Instead of calling x.a(), I can pass x.a as a -parameter or bind to another name. Then I can invoke this -name. The first parameter of the method will be passed the bound -object, which in OO terms is the receiver of the method. This is -a simple way of creating callbacks. (In Java you would have just -passed the object of course, then having the callback invoke the -appropriate method such as `call` or `run`.) - -* staticmethod, classmethod, descriptors functools, such as for - partial construction. - -* Other function constructors, including yours? + Instead of calling ``x.a()``, I can pass ``x.a`` as a parameter or bind to another name. + Then I can invoke this name. + The first parameter of the method will be passed the bound object, which in OO terms is the receiver of the method. + This is a simple way of creating callbacks. (In Java you would have just passed the object of course, then having the callback invoke the appropriate method such as call or run.) Lambda Functions -~~~~~~~~~~~~~~~~ - -As stated in the introduction, a lambda function is an anonymous function. In other -words, a lambda function is not bound to any name. This -can be useful when you are trying to create compact code or when it does not make -sense to declare a named function because it will only be used once. +---------------- -A lambda function is usually written inline with other code, and most often the body -of a lamdba function is very short in nature. A lambda function is comprised of the -following segments: +As stated in the introduction, a lambda function is an anonymous function. +In other words, a lambda function is not required to be bound to any name. +This can be useful when you are trying to create compact code or when it does not make sense to declare a named function because it will only be used once. +A lambda function is usually written inline with other code, and most often the body of a lambda function is very short in nature. +A lambda function is comprised of the following segments: :: lambda <> : <> -A lambda function accepts arguments just like any other function, and it uses -those arguments within it's function body. Also, just like other functions in -Python a value is always returned. Let's take a look at a simple lambda function -to get a better understanding of how they work. +A lambda function accepts arguments just like any other function, and it uses those arguments within it’s function body. +Also, just like other functions in Python a value is always returned. +Let’s take a look at a simple lambda function to get a better understanding of how they work. -*Example of using a lambda function to combine two strings. In this case, a first -and last name* +*Example of using a lambda function to combine two strings. In this case, a first and last name* :: - >>> name_combo = lambda first,last: first + ' ' + last + >>> name_combo = lambda first, last: first + ' ' + last >>> name_combo('Jim','Baker') 'Jim Baker' -In the example above, we assigned the function to a name. However, a lambda -function can also be defined in-line with other code. Oftentimes a lambda -function is used within the context of other functions, namely built-ins. +In the example above, we assigned the function to a name. +However, a lambda function can also be defined in-line with other code. +Oftentimes a lambda function is used within the context of other functions, namely built-ins. Generator Functions -------------------- - -Generators are functions that construct objects implementing Python's -iterator protocol. - -iter() - obj.__iter__ -Call obj.next +=================== +Generators are special functions that are an example of iterators, which will be discussed in Chapter 6. +Generators advance to the next point by calling the special method next. +Usually that’s done implicitly, typically through a loop or a consuming function that accepts iterators, including generators. +They return values by using the ``yield`` statement. +Each time a ``yield`` statement is encountered then the current iteration halts and a value is returned. +Generators have the ability to remember where they left off. +Each time ``next()`` is called, the generator resumes where it had left off. +A ``StopIteration`` exception will be raised once the generator has been terminated. +Over the next couple of sections, we will take a closer look at generators and how they work. +Along the way, you will see many examples for creating and using generators. -Generators advance to the next point by calling the special method -``next``. Usually that's done implicitly, typically through a loop or -a consuming function that accepts iterators, including generators. They return -values by using the *yield* statement. Each time a *yield* statement is -encountered then the current iteration halts and a value is returned. Generators -have the ability to remember where they left off. Each time *next()* is called, the -generator resumes where it had left off. If a generator -function is not used in the context of a loop, then a *StopIteration* error -will be raised once the generator has been terminated. - -Over the next couple of sections, we will take a closer look at generators -and how they work. Along the way, you will see many examples for creating -and using generators. Defining Generators -~~~~~~~~~~~~~~~~~~~ +------------------- -A generator function is written so that it consists of one or more -yield points, which are marked through the use of the *yield* statement. -As mentioned previously, each time the ``yield`` statement is encountered, -a value is returned. +A generator function is written so that it consists of one or more yield points, which are marked through the use of the ``yield`` statement. +As mentioned previously, each time the ``yield`` statement is encountered, a value is returned. +*Listing 4-24.* :: def g(): @@ -697,15 +615,19 @@ a value is returned. yield 2 yield 3 -In the example above, the generator function *g()* will halt and return a value -once the first *yield* statement is encountered. In this case, a 1 will be returned. -The next time *g.next()* is called, the generator will continue until it encounters -the next yield statement. At that point it will return another value, the 2 in -this case. Let's see this generator in action. +In the previous example, the generator function ``g()`` will halt and return a value once the first ``yield`` statement is encountered. +In this case, a 1 will be returned. +The next time ``g.next()`` is called, the generator will continue until it encounters the next ``yield`` statement. +At that point it will return another value, the 2 in this case. +Let’s see this generator in action. +Note that calling the generator function simply creates your generator, it does not cause any yields. In order to get the value from the first ``yield``, we must call ``next()``. +*Listing 4-25.* :: + # Call the function to create the generator >>> x = g() + # Call next() to get the value from the yield >>> x.next() before the yield point 1 1 @@ -719,13 +641,12 @@ this case. Let's see this generator in action. File "", line 1, in StopIteration +Let’s take a look at another more useful example of a generator. +In the following example, the ``step_to()`` function is a generator that increments based upon a given factor. +The generator starts at zero and increments each time ``next()`` is called. +It will stop working once it reaches the value that is provided by the ``stop`` argument. -Let' take a look at another more useful example of a generator. In the following -example, the *step_to()* function is a generator that increments based -upon a given factor. The generator starts at zero and increments each time -*next()* is called. It will stop working once it reaches the value that is -provided by the *stop* argument. - +*Listing 4-26.* :: >>> def step_to(factor, stop): @@ -760,16 +681,13 @@ provided by the *stop* argument. 10 >>> +If the ``yield`` statement is seen in the scope of a function, then that function is compiled as if it’s a generator function. +Unlike other functions, you use the ``return`` statement only to say, “I’m done,” that is, to exit the generator, and not to return any values. +You can think of ``return`` as acting like a break in a for-loop or while-loop. +Let’s change the ``step_to`` function just a bit to check and ensure that the ``factor`` is less than the stopping point. +We’ll add a ``return`` statement to exit the generator if the ``factor`` is greater or equal to the ``stop``. -If the ``yield`` statement is seen in the scope of a function, then that -function is compiled as if it's a generator function. Unlike other functions, -you use the ``return`` statement only to say, "I'm done", that is, to exit the -generator. It is not necessary to explicitly return. You can think of -``return`` as acting like a ``break`` in a for-loop or while-loop. -Let's change the step_to function just a bit to check and ensure -that the factor is less than the stopping point. We'll add a return -statement to exit the generator if the factor is greater or equal to the stop. - +*Listing 4-27* :: >>> def step_return(factor, stop): @@ -808,6 +726,7 @@ statement to exit the generator if the factor is greater or equal to the stop. If you attempt to return an argument then a syntax error will be raised. +*Listing 4-28.* :: def g(): @@ -820,51 +739,35 @@ If you attempt to return an argument then a syntax error will be raised. SyntaxError: 'return' with argument inside generator -Many useful generators actually will have an infinite loop around -their yield expression, instead of ever exiting, explicitly or not. The -generator will essentially work each time *next()* is called throughout the life -of the program. +Many useful generators actually will have an infinite loop around their ``yield`` expression, instead of ever exiting, explicitly or not. +The generator will essentially work each time ``next()`` is called throughout the life of the program. -*Pseudocode for generator using infinite loop* :: +*Listing 4-29. Pseudocode for generator using infinite loop* +:: while True: yield stuff -This works because a generator object can be garbage collected, just -like any other object implementing the iteration protocol. The fact -that it uses the machinery of function objects to implement itself -doesn't matter. - -.. sidebar:: How it actually works - - Generators are actually compiled differently from other - functions. Each yield point saves the state of unnamed local - variables (Java temporaries) into the frame object, then returns the - value to the function that had called ``next`` (or ``send`` in the - case of a coroutine). The generator is then indefinitely suspended, - just like any other iterator. Upon calling *next* again, the generator - is resumed by restoring these local variables, then executing the - next bytecode instruction following the yield point. This process - continues until the generator is either garbage collected or it - exits. +This works because a generator object can be garbage collected as soon as the last reference to the generator is used. +The fact that it uses the machinery of function objects to implement itself doesn’t matter. - You can determine if the underlying function is a generator if it's - code object has the ``CO_GENERATOR`` flag set in ``co_flags``. - - Generators can also be resumed from any thread, although some care - is necessary to ensure that underlying system state is shared (or - compatible). We will explore how to use effectively use this - capability in the chapter on concurrency. +.. sidebar::How it Actually Works + Generators are actually compiled differently from other functions. + Each yield point saves the state of unnamed local variables (Java temporaries) into the frame object, then returns the value to the function that had called next (or send in the case of a coroutine which will be discussed later in this chapter). + The generator is then indefinitely suspended, just like any other iterator. + Upon calling ``next`` again, the generator is resumed by restoring these local variables, then executing the next bytecode instruction following the yield point. + This process continues until the generator is either garbage collected or it exits. + Generators can also be resumed from any thread, although some care is necessary to ensure that underlying system state is shared (or compatible). Generator Expressions -~~~~~~~~~~~~~~~~~~~~~ - +--------------------- Generator expressions are an alternative way to create the generator object. -Please note that this is not the same as a generator function! It's the -equivalent to what a generator function yields when called. Generator expressions -basically create an unnamed generator. +Please note that this is not the same as a generator function! +It’s the equivalent to what a generator function yields when called. +Generator expressions basically create an unnamed generator. +*Listing 4-30.* :: >>> x = (2 * x for x in [1,2,3,4]) @@ -875,7 +778,7 @@ basically create an unnamed generator. File "", line 1, in TypeError: 'generator' object is not callable -Let's see this generator expression in action: +Let’s see this generator expression in action: :: @@ -888,39 +791,35 @@ Let's see this generator expression in action: 8 >>> -Typically generator expressions tend to be more compact but less versatile than -generator functions. They are useful for getting things done in a consise -manner. - +Typically generator expressions tend to be more compact but less versatile than generator functions. +They are useful for getting things done in a concise manner. -Namespaces, Nested Scopes and Closures --------------------------------------- -Note that you can introduce other namespaces into your function definition. It -is possible to include import statements directly within the body of a function. -This allows such imports to be valid only within the context of the function. For -instance, in the following function definition the imports of *A* and *B* are -only valid within the context of *f()*. +Namespaces, Nested Scopes, and Closures +======================================= +Note that you can introduce other namespaces into your function definition. +It is possible to include import statements directly within the body of a function. +This allows such imports to be valid only within the context of the function. +For instance, in the following function definition the imports of A and B are only valid within the context of ``f()``. +*Listing 4-31.* :: def f(): from NS import A, B -At first glance, including import statements within your function definitions may -seem unneccessary. However, if you think of a function as an object then it makes -much more sense. We can pass functions around just like other objects in Python -such as variables. As mentioned previously, functions can even be passed to -other functions as arguments. Function namespaces provide the ability to -treat functions as their own separate piece of code. Oftentimes, functions that -are used in several different places throughout an application are stored in a -separate module. The module is then imported into the program where needed. - -Functions can also be nested within each other to create useful solutions. Since -functions have their own namespace, any function that is defined within another -function is only valid within the parent function. Let's take a look at a simple -example of this before we go any further. - +At first glance, including import statements within your function definitions may seem unnecessary. +However, if you think of a function as an object then it makes much more sense. +We can pass functions around just like other objects in Python such as variables. +As mentioned previously, functions can even be passed to other functions as arguments. +Function namespaces provide the ability to treat functions as their own separate piece of code. +Oftentimes, functions that are used in several different places throughout an application are stored in a separate module. +The module is then imported into the program where needed. +Functions can also be nested within each other to create useful solutions. +Since functions have their own namespace, any function that is defined within another function is only valid within the parent function. +Let’s take a look at a simple example of this before we go any further. + +*Listing 4-32.* :: >>> def parent_function(): @@ -939,62 +838,87 @@ example of this before we go any further. >>> p() 4 -While this example is not extremely useful, it allows you to understand a few of -the concepts for nesting functions. As you can see, the *parent_function* contains -a function named *child_function*. The *parent_function* calls the *child_function* -passing an argument. What we have created in this example is a simple *Closure* -function. Each time the function is called, it executes the inner function and -increments the variable *x* which is only available within the scope of this -closure. +While this example is not extremely useful, it allows you to understand a few of the concepts for nesting functions. +As you can see, the ``parent_function`` contains a function named ``child_function``. +The ``parent_function`` in this example returns the ``child_function``. +What we have created in this example is a simple Closure function. +Each time the function is called, it executes the inner function and increments the variable x which is only available within the scope of this closure. +In the context of Jython, using closures such as the one defined previously can be useful for integrating Java concepts as well. +It is possible to import Java classes into the scope of your function just as it is possible to work with other Python modules. +It is sometimes useful to import in a function call in order to avoid circular imports, which is the case when function A imports function B, which in turn contains an import to function A. +By specifying an ``import`` in a function call you are only using the import where it is needed. +You will learn more about using Java within Jython in Chapter 10. -In the context of Jython, using closures such as the one defined above can be -useful for integrating Java concepts as well. It is possible to import Java -classes into the scope of your function just as it is possible to work with -other Python modules. You will learn more about using Java within Jython in -Chapter 7 and Chapter 10. Function Decorators -------------------- +=================== +Decorators are a convenient syntax that describes a way to transform a function. +They are essentially a metaprogramming technique that enhances the action of the function that they decorate. +To program a function decorator, a function that has already been defined can be used to decorate another function, which basically allows the decorated function to be passed into the function that is named in the decorator. +Let’s look at a simple example. -Decorators are a convenient syntax that describes how to transform a function. -They are essentially a metaprogramming technique that enhances the action -of the function that they decorate. To program a function decorator, -a function that has already been defined can be used to decorate another function, -which basically allows the decorated function to be passed into the function that -is named in the decorator. Let's look at a simple example. -*Example 4_1.py* :: +*Listing 4-33.* +:: def plus_five(func): - x = func() - return x + 5 + x = func() + return x + 5 @plus_five def add_nums(): return 1 + 2 -In the given example, the *add_nums()* function is decorated with the *plus_five()* -function. This has the same effect as passing the *add_nums* function into the -*plus_five* function. In other words, this decorator is syntactic sugar that -makes this technique easier to use. The decorator above has the same functionality -as the following code. +In this example, the ``add_nums()`` function is decorated with the ``plus_five()`` function. +This has the same effect as passing the ``add_nums`` function into the ``plus_five`` function. +In other words, this decorator is syntactic sugar that makes this technique easier to use. +The decorator above has the same functionality as the following code. +*Listing 4-34.* :: add_nums = plus_five(add_nums) -Now that we've covered the basics of function decorators it is time to take a look -at a more in-depth example of the concept. In the following decorator function -example, we are taking a twist on the old tip_calculator function and adding a -sales tax calculation. As you see, the original *calc_bill* funciton takes -a sequence of amounts, namely the amounts for each item on the bill. The -*calc_bill* function then simply sums the amounts and returns the value. In -the given example, we apply the *sales_tax* decorator to the function which -then transforms the function so that it not only calculates and returns the -sum of all amounts on the bill, but it also applies a standard sales tax -to the bill and returns the tax amount and total amounts as well. +In actuality, ``add_nums`` is now no longer a function, but rather an integer. +After decorating with ``plus_five`` you can no longer call ``add_nums()``, we can only reference it as if it were an integer. +As you can see, ``add_nums`` is being passed to ``plus_five`` at import time. +Normally, we’d want to have ``add_nums`` finish up as a function so that it is still callable. +In order to make this example more useful, we’ll want to make ``add_nums`` callable again and we will also want the ability to change the numbers that are added. +To do so, we need to rewrite the decorator function a bit so that it includes an inner function that accepts arguments from the decorated function. -*Example 4_2.py* :: +*Listing 4-35.* +:: + + def plus_five(func): + def inner(*args, **kwargs): + x = func(*args, **kwargs) + 5 + return x + return inner + + @plus_five + def add_nums(num1, num2): + return num1 + num2 + +Now we can call the ``add_nums()`` function once again and we can also pass two arguments to it. +Because it is decorated with the ``plus_five`` function it will be passed to it and then the two arguments will be added together and the number five will be added to that sum. +The result will then be returned. + +*Listing 4-36.* +:: + + >>> add_nums(2,3) + 10 + >>> add_nums(2,6) + 13 + +Now that we’ve covered the basics of function decorators it is time to take a look at a more in-depth example of the concept. +In the following decorator function example, we are taking a twist on the old ``tip_calculator`` function and adding a sales tax calculation. +As you see, the original ``calc_bill`` function takes a sequence of amounts, namely the amounts for each item on the bill. +The ``calc_bill`` function then simply sums the amounts and returns the value. +In the given example, we apply the ``sales_tax`` decorator to the function which then transforms the function so that it not only calculates and returns the sum of all amounts on the bill, but it also applies a standard sales tax to the bill and returns the tax amount and total amounts as well. + +*Listing 4-37.* +:: def sales_tax(func): ''' Applies a sales tax to a given bill calculator ''' @@ -1008,19 +932,16 @@ to the bill and returns the tax amount and total amounts as well. @sales_tax def calc_bill(amounts): - ''' Takes a sequence of amouunts and returns sum ''' + ''' Takes a sequence of amounts and returns sum ''' return sum(amounts) -The decorator function contains an inner function that accepts two arguments, -a sequence of arguments and a dictionary of keyword args. We must pass these -arguments to our original function when calling from the decorator to ensure -that the arguments that we passed to the original function are applied within -the decorator function as well. In this case, we want to pass a sequence of -amounts to *calc_bill*, so passing the *\*args*, and *\*\*kwargs* arguments to the -function ensures that our amounts sequnce is passed within the decorator. -The decorator function then performs simple calculations for the tax and total -dollar amounts and prints the results. Let's see this in action: +The decorator function contains an inner function that accepts two arguments, a sequence of arguments and a dictionary of keyword args. +We must pass these arguments to our original function when calling from the decorator to ensure that the arguments that we passed to the original function are applied within the decorator function as well. +In this case, we want to pass a sequence of amounts to ``calc_bill``, so passing the ``**args``, and ``**kwargs`` arguments to the function ensures that our amounts sequnce is passed within the decorator. +The decorator function then performs simple calculations for the tax and total dollar amounts and prints the results. +Let’s see this in action: +*Listing 4-38.* :: >>> amounts = [12.95,14.57,9.96] @@ -1029,14 +950,12 @@ dollar amounts and prints the results. Let's see this in action: Tax Amount: $ 6.75 Total bill: $ 44.23 -It is also possible to pass arguments to decorator functions. In order to do -so, we must nest another function within our decorator function. The outer -function will accept the arguments to be passed into the decorator function, -the inner function will accept the decorated function, and the inner most -function will perform the work. We'll take another spin on the tip calculator -example and create a decorator that will apply the tip calculation to the -*calc_bill* function. +It is also possible to pass arguments to decorator functions when doing the decorating. +In order to do so, we must nest another function within our decorator function. +The outer function will accept the arguments to be passed into the decorator function, the inner function will accept the decorated function, and the inner most function will perform the work. +We’ll take another spin on the tip calculator example and create a decorator that will apply the tip calculation to the ``calc_bill`` function. +*Listing 4-39.* :: def tip_amount(tip_pct): @@ -1049,15 +968,15 @@ example and create a decorator that will apply the tip calculation to the return calc_tip_impl return calc_tip_wrapper -Now let's see this decorator function in action. As you'll notice, we pass -a percentage amount to the decorator itself and it is applied to the decorator -function. +Now let’s see this decorator function in action. +As you’ll notice, we pass a percentage amount to the decorator itself and it is applied to the decorator function. +*Listing 4-40.* :: >>> @tip_amount(.18) ... def calc_bill(amounts): - ... ''' Takes a sequence of amouunts and returns sum ''' + ... ''' Takes a sequence of amounts and returns sum ''' ... return sum(amounts) ... >>> amounts = [20.95, 3.25, 10.75] @@ -1066,26 +985,35 @@ function. Tip amount: $ 6.29 Total with tip: $ 41.24 -As you can see, we have a similar result as was produced with the sales tax -calculator. All of the amounts in the sequence of amounts are summed up and -then the tip is applied. +As you can see, we have a similar result as was produced with the sales tax calculator, except that with this decorator solution we can now vary the tip percentage. +All of the amounts in the sequence of amounts are summed up and then the tip is applied. +Let’s take a quick look at what is actually going on if we do not use the decorator @ syntax. -Coroutines ----------- +*Listing 4-41.* +:: + + calc_bill = tip_amount(.18)(calc_bill) -Coroutines are often compared to generator functions in that they also make use -of the *yield* statement. However, a coroutine is exactly the opposite -of a generator in terms of functionality. A coroutine actually treats a -*yield* statement as an expression, and it accepts data instead of returning -it. Coroutines are oftentimes overlooked as they may at first seem like -a dounting topic. However, once it is understood that coroutines and generators -are not the same thing then the concept of how they work is a bit easier to -grasp. +At import time, the ``tip_amount()`` function takes both the tip percentage and the ``calc_bill`` function as arguments, and the result becomes the new ``calc_bill`` function. +By including the decorator, we’re actually decorating ``calc_bill`` with the function which is returned by ``tip_amount(.18)``. +In the larger scale of the things, if we applied this decorator solution to a complete application then we could accept the tip percentage from the keyboard and pass it into the decorator as we’ve shown in the example. +The tip amount would then become a variable that can fluctuate based upon a different situation. +Lastly, if we were dealing with a more complex decorator function, we have the ability to change the inner-working of the function without adjusting the original decorated function at all. +Decorators are an easy way to make our code more versatile and manageable. -A coroutine is a function that receives data and does something with it. We will -take a look at a simple coroutine example and then break it down to study -the functionality. +Coroutines +========== + +Coroutines are often compared to generator functions in that they also make use of the ``yield`` statement. +However, a coroutine is exactly the opposite of a generator in terms of functionality. +A coroutine actually treats a ``yield`` statement as an expression, and it accepts data instead of returning it. +Coroutines are oftentimes overlooked as they may at first seem like a daunting topic. +However, once it is understood that coroutines and generators are not the same thing then the concept of how they work is a bit easier to grasp. +A coroutine is a function that receives data and does something with it. +We will take a look at a simple coroutine example and then break it down to study the functionality. + +*Listing 4-42.* :: def co_example(name): @@ -1096,26 +1024,31 @@ the functionality. my_text.append(txt) print my_text -Here we have a very simplistic coroutine example. It accepts a value as the -"name" of the coroutine. It then accepts strings of text, and each time -a string of text is sent to the coroutine, it is appended to a list. The -*yield* statement is where text is being entered by the user. It is assigned -to the *txt* variable and then processing continues. Let's take a look at how -to actually use the coroutine. +Here we have a very simplistic coroutine example. +It accepts a value as the “name” of the coroutine. +It then accepts strings of text, and each time a string of text is sent to the coroutine, it is appended to a list. +The ``yield`` statement is the point where text is being entered by the user. +It is assigned to the txt variable and then processing continues. +It is important to note that the ``my_text`` list is held in memory throughout the life of the coroutine. +This allows us to append values to the list with each ``yield``. +Let’s take a look at how to actually use the coroutine. +*Listing 4-43.* :: >>> ex = co_example("example1") >>> ex.next() Entering coroutine example1 -In the code above, we assign the name "example1" to this coroutine. We could -actually accept any type of argument for the coroutine and do whatever we want -with it. We'll see a better example after we understand how this works. The -next line of code calls *next()* on the function. The *next()* must be called -once to intialize the coroutine. Once this has been done, the function is -ready to accept values. +In this code, we assign the name “example1” to this coroutine. +We could actually accept any type of argument for the coroutine and do whatever we want with it. +We’ll see a better example after we understand how this works. +Moreover, we could assign this coroutine to multiple variables of different names and each would then be its own coroutine object that would function independently of the others. +The next line of code calls ``next()`` on the function. +The ``next()`` must be called once to initialize the coroutine. +Once this has been done, the function is ready to accept values. +*Listing 4-44.* :: >>> ex.send("test1") @@ -1125,13 +1058,14 @@ ready to accept values. >>> ex.send("test3") ['test1', 'test2', 'test3'] -As you can see, we use the *send()* method to actually send data values into -the coroutine. In the function itself, the text we *send* is inserted where -the *(yield)* expression is placed. We can really coninue to use the coroutine -forever, or until our JVM is out of memory. However, it is a best practice -to *close()* the coroutine once it is no longer needed. The *close()* call will -cause the coroutine to be garbage collected. +As you can see, we use the ``send()`` method to actually send data values into the coroutine. +In the function itself, the text we send is inserted where the ``(yield)`` expression is placed. +We can really continue to use the coroutine forever, or until our JVM is out of memory. +However, it is a best practice to ``close()`` the coroutine once it is no longer needed. +The ``close()`` call will cause the coroutine to be garbage collected. + +*Listing 4-45.* :: >>> ex.close() @@ -1140,22 +1074,18 @@ cause the coroutine to be garbage collected. File "", line 1, in StopIteration -If we try to send more data to the function once it has been closed then a -*StopIteration* error is raised. Coroutines can be very helpful in a number -of situations. While the example above doesn't do much, there are a number of -great applications to which we can apply the use of coroutines. +If we try to send more data to the function once it has been closed then a StopIteration error is raised. +Coroutines can be very helpful in a number of situations. +While the previous example doesn’t do much, there are a number of great applications to which we can apply the use of coroutines and we will see a more useful example in a later section. -Decorators in Coroutines -~~~~~~~~~~~~~~~~~~~~~~~~ -While the initialization of a coroutine by calling the *next()* method is not -difficult to do, we can eliminate this step to help make things even easier. By -applying a decorator function to our coroutine, we can automatically initialize -it so it is ready to receive data. - -Let's define a decorator that we can apply to the coroutine in order to make -the call to *next()*. +Decorators in Coroutines +------------------------ +While the initialization of a coroutine by calling the ``next()`` method is not difficult to do, we can eliminate this step to help make things even easier. +By applying a decorator function to our coroutine, we can automatically initialize it so it is ready to receive data. +Let’s define a decorator that we can apply to the coroutine in order to make the call to ``next()``. +*Listing 4-46.* :: def coroutine_next(f): @@ -1165,8 +1095,7 @@ the call to *next()*. return coroutine return initialize -Now we will apply our decorator to the coroutine function and then make use -of it. +Now we will apply our decorator to the coroutine function and then make use of it. :: @@ -1187,23 +1116,26 @@ of it. ['one', 'two'] >>> ex2.close() -As you can see, while it is not necessary to use a decorator for performing -such tasks, it definitely makes things easier to use. +As you can see, while it is not necessary to use a decorator for performing such tasks, it definitely makes things easier to use. +If we chose not to use the syntactic sugar of the @ syntax, we could do the following to initialize our coroutine with the ``coroutine_next()`` function. -Coroutine Example -~~~~~~~~~~~~~~~~~ +*Listing 4-47.* +:: -Now that we understand how coroutines are used, let's take a look at a more in-depth -example. Hopefully after reviewing this example you will understand how -useful such functionality can be. + co_example = coroutine_next(co_example) -In this example, we will pass the name of a file to the coroutine on initiliziation. -After that, we will send strings of text to the function and it will open the -text file that we sent to it (given that the file resides in the correct location), -and search for the number of matches per a given word. The numeric result -for the number of matches will be returned to the user. -*Example-4_3.py* :: +Coroutine Example +----------------- + +Now that we understand how coroutines are used, let’s take a look at a more in-depth example. +Hopefully after reviewing this example you will understand how useful such functionality can be. +In this example, we will pass the name of a file to the coroutine on initialization. +After that, we will send strings of text to the function and it will open the text file that we sent to it (given that the file resides in the correct location), and search for the number of matches per a given word. +The numeric result for the number of matches will be returned to the user. + +*Listing 4-48.* +:: def search_file(filename): print 'Searching file %s' % (filename) @@ -1212,13 +1144,12 @@ for the number of matches will be returned to the user. my_file.close() while True: search_text = (yield) - search_result = 0 search_result = file_content.count(search_text) print 'Number of matches: %d' % (search_result) -The coroutine above opens the given file, reads it's content, and then -searches and returns the number of matches for any given *send* call. +The coroutine above opens the given file, reads its content, and then searches and returns the number of matches for any given send call. +*Listing 4-49.* :: >>> search = search_file("example4_3.txt") @@ -1235,33 +1166,19 @@ searches and returns the number of matches for any given *send* call. >>> search.close(); - -Conclusion ----------- - -In this chapter, we have covered the use of functions in the Python language. There -are many different use-cases for functions and we have learned techniques that -will allow us to apply the functions to many situations. Functions are -first-class objects in Python, and they can be treated as any other object. We -started this chapter by learning the basics of how to define a function. After -learning about the basics, we began to evolve our knowledge of functions by -learning how to use parameters and make recursive function calls. - -There are a wide variety of built-in functions available for use. If you take -a look at Appendix C of this book you can see a listing of these built-ins. It -is a good idea to become familiar with what built-ins are available for you. After -all, it doesn't make much sense to re-write something that has already been done. - -This chapter also discussed some alternative ways to define functions including -the lambda notation, as well as some alternative types of functions including -decorators, generators and coroutines. Wrapping up this chapter, you should now be familiar -with Python functions and how o create and use them. You should also be -familiar with some of the advanced techniques that can be applied to functions. - -In the next chapter, you will learn a bit about input and output with Jython and -the basics of Python I/O. Later in Part I of this book, we will build upon -object-orientation and learn how to use classes in Python. - - - - +Summary +======= +In this chapter, we have covered the use of functions in the Python language. +There are many different use-cases for functions and we have learned techniques that will allow us to apply the functions to many situations. +Functions are first-class objects in Python, and they can be treated as any other object. +We started this chapter by learning the basics of how to define a function. +After learning about the basics, we began to evolve our knowledge of functions by learning how to use parameters and make recursive function calls. +There are a wide variety of built-in functions available for use. +If you take a look at Appendix C of this book you can see a listing of these built-ins. +It is a good idea to become familiar with what built-ins are available. +After all, it doesn’t make much sense to rewrite something that has already been written. +This chapter also discussed some alternative ways to define functions including the lambda notation, as well as some alternative types of function including decorators, generators and coroutines. +Wrapping up this chapter, you should now be familiar with Python functions and how to create and use them. +You should also be familiar with some of the advanced techniques that can be applied to functions. +In the next chapter, you will learn a bit about input and output with Jython and the basics of Python I/O. +Later in this book, we will build upon object-orientation and learn how to use classes in Python. diff --git a/ExceptionHandlingDebug.rst b/ExceptionHandlingDebug.rst index 1d8e691..86dcc93 100644 --- a/ExceptionHandlingDebug.rst +++ b/ExceptionHandlingDebug.rst @@ -1,4 +1,4 @@ -Chapter 6: Exception Handling and Debugging +Chapter 7: Exception Handling and Debugging +++++++++++++++++++++++++++++++++++++++++++ Any good program makes use of a language’s exception handling mechanisms. There is no better way to frustrate an end-user then by having them run into an issue with your software and displaying a big ugly error message on the screen, followed by a program crash. Exception handling is all about ensuring that when your program encounters an issue, it will continue to run and provide informative feedback to the end-user or program administrator. Any Java programmer becomes familiar with exception handling on day one, as some Java code won’t even compile unless there is some form of exception handling put into place via the try-catch-finally syntax. Python has similar constructs to that of Java, and we’ll discuss them in this chapter. diff --git a/InputOutput.rst b/InputOutput.rst index d817d0e..7c56fb9 100644 --- a/InputOutput.rst +++ b/InputOutput.rst @@ -1,279 +1,383 @@ -Chapter 9: Input and Output +Chapter 5: Input and Output +++++++++++++++++++++++++++ -A program means very little if it does not take input of some kind from the program user. Likewise, if there is no form of output from a program then one may ask whey we have a program at all. Input and output operations can define the user experience and usability of any program. This chapter is all about how to put information or data into a program, and then how to display it or save it to a file. This chapter does not discuss working with databases, but rather, working at a more rudimentary level with files. Throughout this chapter you will learn such techniques as how to input data for a program via a terminal or command line, likewise, you will learn now to read input from a file and write to a file. After reading this chapter, you should know how to persist Python objects to disk using the *pickle* module and also how to retrieve objects from disk and use them. There will be a broad variety of topics discussed in this chapter, all of them relating to input and output. +A program means very little if it does not take input of some kind from the program user. +Likewise, if there is no form of output from a program then one may ask why we have a program at all. +Input and output operations can define the user experience and usability of any program. +This chapter is all about how to put information or data into a program, and then how to display it or save it to a file. +This chapter does not discuss working with databases, but rather, working at a more rudimentary level with files. +Throughout this chapter you will learn such techniques as how to input data for a program via a terminal or command line, likewise, you will learn how to read input from a file and write to a file. +After reading this chapter, you should know how to persist Python objects to disk using the ``pickle`` module and also how to retrieve objects from disk and use them. Input from the Keyboard ======================= +As stated, almost every program takes input from a user in one form or another. +Most basic applications allow for keyboard entry via a terminal or command line environment. +Python makes keyboard input easy, and as with many other techniques in Python there is more than one way to enable keyboard input. +In this section, we’ll cover each of those different ways to perform this task, along with a couple of use-cases. +In the end you should be able to identify the most suitable method of performing input and output for your needs. +``sys.stdin`` and ``raw_input`` +------------------------------- -As stated in the preface to this chapter, almost every program takes input from a user in one form or another. Most basic applications allow for keyboard entry via a terminal or command line environment. Python makes keyboard input easy, and as with many other techniques in Python there are more than one way to enable keyboard input. In this section, we’ll cover each of those different ways to perform this task, along with a couple of use-cases. In the end you should be able to identify the most suitable application of this feature for your needs. +Making use of ``std.stdin`` is by far the most widely used method to read input from the command line or terminal. +This procedure consists of importing the ``sys`` package, then writing a message prompting the user for some input, and lastly reading the input by making a call to ``sys.stdin.readln()`` and assigning the returned value to a variable. +The process looks like the code that is displayed in Listing 5-1. -sys.stdin and raw_input ------------------------ +*Listing 5-1. Using ``sys.stdin``* +:: -Making use of std.stdin is by far the most widely used method to read input from the command line or terminal. This procedure consists of importing the sys package, then writing a message prompting the user for some input, and lastly reading the input by making a call to *sys.stdin.readln()* and assigning the returned value to a variable. The process looks like the code that is displayed below. :: + # Obtain a value from the command line and store it into a variable + >>> import sys + >>> fav_team = sys.stdin.readline() + Cubs + >>> sys.stdout.write("My favorite team is: %s" % fav_team) + My favorite team is: Cubs - # Obtain a value from the command line and store it into a variable - >>> import sys - >>> sys.stdout.write("Enter your favorite team: ") - >>> fav_team = sys.stdin.readline() - >>> print fav_team - Enter your favorite team: Cubs +You can see that the ``sys`` module is quite easy to use. +However, even simpler is the ``raw_input`` function. +It basically generates some text on the command line or terminal, accepts user input, and assigns it to a variable. +Let’s take a look at the same example from above using the ``raw_input`` syntax. -You can see that the usage of sys modules is quite simplistic. However, another approach to performing this same task is to make use of the *raw_input* function. This function uses a more simplistic syntax in order to perform the same procedure. It basically generates some text on the command line or terminal, accepts user input, and assigns it to a variable. Let’s take a look at the same example from above using the *raw_input* syntax. :: +*Listing 5-2. Using ``raw_input``* +:: - # Obtain a value using raw_input and store it into a variable - >>> fav_team = raw_input("Enter your favorite team: ") - Enter your favorite team: Cubs + # Obtain a value using raw_input and store it into a variable + >>> fav_team = raw_input("Enter your favorite team: ") + Enter your favorite team: Cubs + +Note that another function ``input`` performs a similar task. +However, the ``input`` function needs to be used with great care as it could be a potential security risk. +The ``raw_input`` function returns just what was typed, whereas the ``input`` function takes it and *evaluates it as an expression*, opening a door to arbitrary code execution. +It is safest to stay away from using ``input``. -Obtaining Variables from Jython Environment -------------------------------------------- -It is possible to retrieve values directly from the Jython environment for use within your applications. For instance, we can obtain system environment variables or use the variables that are assigned to sys.argv at runtime. +Obtaining Variables from Jython Environment +=========================================== -To use environment variable values within your Jython application, simply import the *os* module and use it’s *environ* dictionary to access them. Since this is a dictionary object, you can obtain a listing of all environment variables by simply typing *os.environ* at will. :: +It is possible to retrieve values directly from the Jython environment for use within your applications. +For instance, we can obtain system environment variables or the strings that have been passed into the command line or terminal when running the program. +To use environment variable values within your Jython application, simply import the ``os`` module and use its ``environ`` dictionary to access them. +Since this is a dictionary object, you can obtain a listing of all environment variables by simply typing ``os.environ``. +*Listing 5-3. Obtaining and Altering System Environment Variables* +:: - >>> import os - >>> home = os.environ["HOME"] - >>> home - '/Users/juneau' + >>> import os + >>> os.environ["HOME"] + '/Users/juneau' + # Change home directory for the Python session + >>> os.environ["HOME"] = "/newhome" + >>> os.environ["HOME"] + /newhome' - # Change home directory for the Python session - >>> os.environ["HOME"] = "/newhome" - >>> home = os.environ["HOME"] - >>> home - '/newhome' +When you are executing a Jython module from the command prompt or terminal, you can make use of the ``sys.argv`` list that takes values from the command prompt or terminal after invoking the Jython module. +For instance, if we are interested in having our program user enter some arguments to be used by the module, they can simply invoke the module and then type all of the text entries followed by spaces, using quotes to pass an argument that contains a space. +The number of arguments can be any size (limited by the shell), so the possibilities are endless. -When you are executing a Jython module from the command prompt or terminal, you can make use of the *sys.argv* list that takes values from the command prompt or terminal after invoking the Jython module. For instance, if we are interested in having our program user enter some text to be used by the module, they can simply invoke the module and then use type all of the text entries followed by spaces, using quotes if you wish to pass an argument that contains a space. The number of arguments can be any size (I’ve never hit an upper bound anyways), so the possibilities are endless. :: +*Listing 5-4. Using ``sys.argv``* +:: - # sysargv_print.py – Prints all of the arguments provided at the command line - import sys - for sysargs in sys.argv: - print sysargs + # sysargv_print.py – Prints all of the arguments provided at the command line + import sys + for sysargs in sys.argv: + print sysargs - # Usage - >>> jython sysargv_print.py "test" "test2" "test3" - sysargv_print.py - test - test2 - test3 +Usage:: -As you can see, the first entry in sys.argv is the script name, and then each additional argument provided after the module name is then added to the sys.argv list. This is quite useful for creating scripts to use for automating tasks, etc. + $ jython sysargv_print.py test test2 "test three" + sysargv_print.py + test + test2 + test three +As you can see, the first entry in ``sys.argv`` is the script name, and then each additional argument provided after the module name is then added to the ``sys.argv`` list. +This is quite useful for creating scripts to use for automating tasks, etc. File I/O ======== -We learned a bit about the *File* data type in chapter 2 of this book. In that chapter, we briefly discussed a few of the operations that can be performed using this type. In this section, we will go into detail on what we can do with a *File* object. We’ll start with the basics, and move into more detail. To begin, you should take a look at the table below that lists all of the methods available to a *File* object and what they do. - - - -================= ====================================================================================== -Method Description -================= ====================================================================================== -close() Close file -fileno() Returns integer file descriptor -flush() Used to flush the output buffers -isatty() If the file is an interactive terminal, returns 1 -next() Returns the next line in the file. If no line is found, returns StopIteration -read(x) Reads x bytes -readline(x) Reads single line up to x characters, or entire line if x is omitted -readlines(size) Reads all lines in file into a list. If *size* > 0, reads that number of characters -seek() Moves cursor to a new position in the file -tell() Returns the current position of the cursor -truncate() Truncates a file -write(string) Writes a string -writelines(seq) Writes all strings contained in a sequence -================= ====================================================================================== - -Table 9-1: File Object Methods - -We’ll start by creating a file for use. As discussed in chapter 2, the *open(filename[, mode])* built-in function creates and opens a specified file in a particular manner. The *mode* specifies what mode we will open the file into, be it read, read-write, etc. :: - - >>> myFile = open('mynewfile.txt','w') - >>> firstString = “This is the first line of text.” - >>> myFile.write(firstString) - >>> myFile.close() - -In the example above, the file “mynewfile.txt” did not exist until the *open* function was called. The file was created in *write* mode and then we do just that, write a string to the file. Now, it is important to make mention that the *firstString* is not actually written to the file until it is closed or *flush() *is performed. It is also worth mentioning that if we were to perform a subsequent *write()* operation on the file then the first contents of the file would be overwritten by the subsequent contents. - -Now we’ll step through each of the file functions in an example. The main focus of this example is to provide you with a place to look for actual working file I/O code. :: - - # Write lines to file, flush, and close - >>> myFile.write('This is the first line of text.') - >>> myFile.write('This is the second line of text.') - >>> myFile.write('This is the last line of text.') - >>> myFile.flush() - >>> myFile.close() - - # Open file in read mode - >>> myFile = open('mynewfile.txt','r') - >>> myFile.read() - 'My second line of text.This is the first line of text.This is the second line of text.This is the last line of text.' - - # If we read again, we get a ‘’ because cursor is at the end of text - >>> myFile.read() - '' - - # Seek back to the beginning of file and perform read again - >>> myFile.seek(0) - >>> myFile.read() - 'My second line of text.This is the first line of text.This is the second line of text.This is the last line of text.' - - # Seek back to beginning of file and perform readline() - >>> myFile.seek(0) - >>> myFile.readline() - 'This is the first line of text.This is the second line of text.This is the last line of text.' - - # Use tell() to display current cursor position - >>> myFile.tell() - 93L - >>> myFile.seek(0) - >>> myFile.tell() - 0L - - # Loop through lines of file - >>> for line in myFile: - ... print line - ... - This is the first line of text.This is the second line of text.This is the last line of text. - - -There are a handful of read-only attributes that we can use to find out more information about file objects. For instance, if we are working with a file and want to see if it is still open or if it has been closed, we could view the *closed* attribute on the file to return a boolean stating whether the file is closed. The following table lists each of these attributes and what they tell us about a file object. - -=========== ===================================================== -Attribute Description -=========== ===================================================== -closed Returns a boolean to indicate if the file is closed -encoding Returns a string indicating encoding on file -mode Returns the I/O mode for a file -name Returns the name of the file -newlines Returns the newline representation in the file -=========== ===================================================== - -File Attributes :: - - >>> myFile.closed - False - >>> myFile.mode - 'r' - >>> myFile.name - 'mynewFile.txt' +You learned a bit about the ``file`` data type in Chapter 2. +In that chapter, we briefly discussed a few of the operations that can be performed using this type. +In this section, we will go into detail on what we can do with a ``file`` object. +We’ll start with the basics, and move into more detail. +To begin, you should take a look at Table 5-1 that lists all of the methods available to a ``file`` object and what they do. + +*Table 5-1. ``file`` Object Methods* + ++-------------------+-------------------------------------------------------------+ +|Method |Description | ++-------------------+-------------------------------------------------------------+ +|``close()`` |Close file | ++-------------------+-------------------------------------------------------------+ +|``fileno()`` |Returns integer file descriptor | ++-------------------+-------------------------------------------------------------+ +|``flush()`` |Used to flush or clear the output buffers and write content | +| |to the file | ++-------------------+-------------------------------------------------------------+ +|``isatty()`` |If the file is an interactive terminal, returns 1 | ++-------------------+-------------------------------------------------------------+ +|``next()`` |This allows the file to be iterated over. | +| |Returns the next line in the file. | +| |If no line is found, raises StopIteration. | ++-------------------+-------------------------------------------------------------+ +|``read(x)`` |Reads x bytes | ++-------------------+-------------------------------------------------------------+ +|``readline(x)`` |Reads single line up to x characters, or entire line if x is | +| |omitted. | ++-------------------+-------------------------------------------------------------+ +|``readlines(size)``|Reads all lines in file into a list. | +| |If size > 0, reads that number of characters. | ++-------------------+-------------------------------------------------------------+ +|``seek()`` |Moves cursor to a new position in the file | ++-------------------+-------------------------------------------------------------+ +|``tell()`` |Returns the current position of the cursor | ++-------------------+-------------------------------------------------------------+ +|``truncate(size)`` |Truncates file’s size. | +| |Size defaults to current position unless specified | ++-------------------+-------------------------------------------------------------+ +|``write(string)`` |Writes a string to the file object | ++-------------------+-------------------------------------------------------------+ +|``writelines(seq)``|Writes all strings contained in a sequence with no separator | ++-------------------+-------------------------------------------------------------+ + + +We’ll start by creating a file for use. +As discussed in Chapter 2, the ``open(filename[, mode])`` built-in function creates and opens a specified file in a particular manner. +The ``mode`` specifies what mode we will open the file into, be it read, read-write, and so on. + +*Listing 5-5. Creating, Opening, and Writing to a ``file``* +:: + + >>> my_file = open('mynewfile.txt','w') + >>> first_string = "This is the first line of text." + >>> my_file.write(first_string) + >>> my_file.close() + +In this example, the file “mynewfile.txt” did not exist until the ``open`` function was called. +If it did exist already, the previous version is overwritten by the new version and it is now empty. +The file was created in write mode and then we do just that, write a string to the file. +Now, it is important to make mention that the ``first_string`` is not actually written to the file until it is closed or ``flush()`` is performed. +It is also worth mentioning that if we were to close the file, reopen it, and perform a subsequent ``write()`` operation on the file then the previous contents of the file would be overwritten by content of the new write. + +Now we’ll step through each of the file functions in an example. +The main focus of this example is to provide you with a place to look for actual working file I/O code. + +*Listing 5-6.* +:: + + # Write lines to file, flush, and close + >>> my_file = open('mynewfile.txt','w') + >>> my_file.write('This is the first line of text.\n') + >>> my_file.write('This is the second line of text.\n') + >>> my_file.write('This is the last line of text.\n') + >>> my_file.flush()  # Unneccesary if closing the file but useful to clear buffer + >>> my_file.close() + # Open file in read mode + >>> my_file = open('mynewfile.txt','r') + >>> my_file.read() + 'This is the first line of text.\nThis is the second line of text.\nThis is the last line of text.\n' + # If we read again, we get a '' because cursor is at the end of text + >>> my_file.read() + '' + # Seek back to the beginning of file and perform read again + >>> my_file.seek(0) + >>> my_file.read() + 'This is the first line of text.This is the second line of text.This is the last line of text.' + # Seek back to beginning of file and perform readline() + >>> my_file.seek(0) + >>> my_file.readline() + 'This is the first line of text.\n' + >>> my_file.readline() + 'This is the second line of text.\n' + >>> my_file.readline() + 'This is the last line of text.\n' + >>> my_file.readline() + '' + # Use tell() to display current cursor position + >>> my_file.tell() + 93L + >>> my_file.seek(0) + >>> my_file.tell() + 0L + # Loop through lines of file + >>> for line in my_file: + ... print line + ... + This is the first line of text. + This is the second line of text. + This is the last line of text. + +There are a handful of read-only attributes that we can use to find out more information about file objects. +For instance, if we are working with a file and want to see if it is still open or if it has been closed, we could view the ``closed`` attribute on the file to return a boolean stating whether the file is closed. +Table 5-2 lists each of these attributes and what they tell us about a ``file`` object. + +*Table 5-2. ``file`` Attributes* + ++-------------+-------------------------------------------------------------------+ +| Attribute |Description | ++-------------+-------------------------------------------------------------------+ +|``closed`` |Returns a boolean to indicate if the file is closed | ++-------------+-------------------------------------------------------------------+ +|``encoding`` |Returns a string indicating encoding on file | ++-------------+-------------------------------------------------------------------+ +|``mode`` |Returns the I/O mode for a file(i.e., ‘r’, ‘w’, ‘r+,’rb’, etc.) | ++-------------+-------------------------------------------------------------------+ +|``name`` |Returns the name of the file | ++-------------+-------------------------------------------------------------------+ +|``newlines`` |Returns the newline representation in the file. | +| |This keeps track of the types of newlines encountered while | +| |reading the file. | +| |Allows for universal newline support. | ++-------------+-------------------------------------------------------------------+ + + +*Listing 5-7. ``file`` Attribute Usage* +:: + + >>> my_file.closed + False + >>> my_file.mode + 'r' + >>> my_file.name + 'mynewfile.txt' Pickle ====== -One of the most popular modules in the Python language is the *pickle* module. The goal of this module is basically to allow for the serialization and persistence of Python objects to disk in file format. A *pickled* object can be written to disk using this module, and it can also be read back in and utilized in object format. Just about any Python object can be persisted using *pickle*. - -To write an object to disk, we call the *pickle()* function. The object will be written to file in a format that my be unusable by anything else, but we can then read that file back into our program and use the object as it was prior to writing it out. In the following example, we’ll create a *Player* object and then persist it to file using *pickle.* Later, we will read it back into a program and make use of it. We will make use of the *File* object when working with the *pickle* module. :: - - >>> import pickle - >>> class Player(object): - ... def __init__(self, first, last, position): - ... self.first = first - ... self.last = last - ... self.position = position - ... - >>> player = Player('Josh','Juneau','Forward') - >>> pickleFile = open('myPlayer','wb') - >>> pickle.dump(player, pickleFile) - >>> pickleFile.close() - -In the example above, we’ve persisted a *Player* object to disk using the *dump(object, file)* method in the *pickle* module. Now let’s read the object back into our program and print it out. :: - - >>> pickleFile = open('myPlayer','rb') - >>> player1 = pickle.load(pickleFile) - >>> pickleFile.close() - >>> player1.first - 'Josh' - >>> player1.last, player1.position - ('Juneau', 'Forward') - - -Similarly, we read the pickled file back into our program using the load(file) method. Once read and stored into a variable, we can close the file and work with the object. If we had to perform a sequence of dump or load tasks, we could do so one after the other without issue. You should also be aware that there are different pickle protocols that can be used in order to make pickle work in different Python environments. The default protocol is 0, but protocols 1 and 2 are also available for use. It is best to stick with the default as it works well in most situations, but if you run into any trouble using pickle with binary formats then please give the others a try. - -If we had to store objects to disk and reference them at a later time, it may make sense to use the shelve module which acts like a dictionary for pickeled objects. With the shelve technique, you basically pickle an object and store it using a string-based key value. You can later retrieve the object by passing the key to the opened file object. This technique is very similar to a filing cabinet for our objects in that we can always reference our objects by key value. Let’s take a look at this technique and see how it works. :: - - # Store different player objects - >>> import shelve - >>> player1 = Player('Josh','Juneau','forward') - >>> player2 = Player('Jim','Baker','defense') - >>> player3 = Player('Frank','Wierzbicki','forward') - >>> player4 = Player('Leo','Soto','defense') - >>> player5 = Player('Vic','Ng','center') - >>> data = shelve.open("players") - >>> data['player1'] = player1 - >>> data['player2'] = player2 - >>> data['player3'] = player3 - >>> data['player4'] = player4 - >>> data['player5'] = player5 - >>> playerTemp = data['player3'] - >>> playerTemp.first, playerTemp.last, playerTemp.position - ('Frank', 'Wierzbicki', 'forward') - >>> data.close() - -In the scenario above, we used the same *Player* object that was defined in the previous examples. We then opened a new *shelve* and named it “players”, this shelve actually consists of a set of three files that are written to disk. These three files can be found on disk named “players.bak”, “players.dat”, and “players.dir” once the objects were persisted into the *shelve* and it was closed. As you can see, all of the *Player* objects we’ve instantiated have all been stored into this *shelve* unit, but they exist under different keys. We could have named the keys however we wished, as long as they were each unique. In the example, we persist five objects and then at the end one of the objects is retrieved and displayed. This is quite a nice technique to make a small data store. +One of the most popular modules in the Python language is the ``pickle`` module. +The goal of this module is basically to allow for the serialization and persistence of Python objects to disk in file format. +A pickled object can be written to disk using this module, and it can also be read back in and utilized in object format. +Just about any Python object can be persisted using ``pickle``. + +To write an object to disk, we call the ``pickle()`` function. +The object will be written to file in a format that may be unusable by anything else, but we can then read that file back into our program and use the object as it was prior to writing it out. +In the following example, we’ll create a ``Player`` object and then persist it to file using ``pickle``. +Later, we will read it back into a program and make use of it. +We will make use of the ``file`` object when working with the ``pickle`` module. + +*Listing 5-8. Write an Object to Disk Using Pickle* +:: + + >>> import pickle + >>> class Player(object): + ... def __init__(self, first, last, position): + ... self.first = first + ... self.last = last + ... self.position = position + ... + >>> player = Player('Josh','Juneau','Forward') + >>> pickle_file = open('myPlayer','wb') + >>> pickle.dump(player, pickle_file) + >>> pickle_file.close() + +In the example above, we’ve persisted a ``Player`` object to disk using the ``dump(object, file)`` method in the ``pickle`` module. +Now let’s read the object back into our program and print it out. + +*Listing 5-9. Read and Use a Pickled Object* +:: + + >>> pickle_file = open('myPlayer','rb') + >>> player1 = pickle.load(pickle_file) + >>> pickle_file.close() + >>> player1.first + 'Josh' + >>> player1.last, player1.position + ('Juneau', 'Forward') + +Similarly, we read the pickled file back into our program using the ``load(file)`` method. +Once read and stored into a variable, we can close the file and work with the object. +If we had to perform a sequence of ``dump`` or ``load`` tasks, we could do so one after the other without issue. +You should also be aware that there are different ``pickle`` protocols that can be used in order to make ``pickle`` work in different Python environments. +The default protocol is 0, but protocols 1 and 2 are also available for use. +It is best to stick with the default as it works well in most situations, but if you run into any trouble using ``pickle`` with binary formats then please give the others a try. + +If we had to store objects to disk and reference them at a later time, it may make sense to use the ``shelve`` module which acts like a dictionary for pickled objects. +With the ``shelve`` technique, you basically ``pickle`` an object and store it using a string-based key value. +You can later retrieve the object by passing the key to the opened file object. +This technique is very similar to a filing cabinet for our objects in that we can always reference our objects by key value. +Let’s take a look at this technique and see how it works. + +*Listing 5-10. Using the Shelve Technique* +:: + + # Store different player objects + >>> import shelve + >>> player1 = Player('Josh','Juneau','forward') + >>> player2 = Player('Jim','Baker','defense') + >>> player3 = Player('Frank','Wierzbicki','forward') + >>> player4 = Player('Leo','Soto','defense') + >>> player5 = Player('Vic','Ng','center') + >>> data = shelve.open("players") + >>> data['player1'] = player1 + >>> data['player2'] = player2 + >>> data['player3'] = player3 + >>> data['player4'] = player4 + >>> data['player5'] = player5 + >>> player_temp = data['player3'] + >>> player_temp.first, player_temp.last, player_temp.position + ('Frank', 'Wierzbicki', 'forward') + >>> data.close() + +In the scenario above, we used the same ``Player`` object that was defined in the previous examples. +We then opened a new shelf and named it “players”. +This shelf actually consists of a set of three files that are written to disk. +These three files can be found on disk named “players.bak”, “players.dat”, and “players.dir” once the objects were persisted into the shelf and when ``close()`` was called on the object. +As you can see, all of the ``Player`` objects we’ve instantiated have all been stored into this shelf, but they exist under different keys. +We could have named the keys however we wished, as long as they were each unique. +In the example, we persist five objects and then, at the end, one of the objects is retrieved and displayed. +This is quite a nice technique to make a small data store. Output Techniques ================= -We basically covered the *print* statement in chapter 2 very briefly when discussing string formatting. The *print* statement is by far the most utilized form of output in most Python programs. Although we covered some basics such as conversion types and how to format a line of output in chapter 2, here we will go into a bit more depth on some different variations of the *print* statement as well as other techniques for generating output. There are basically two formats that can be used with the *print* statement. We covered the first in chapter two, and it makes use of a string and some conversion types embedded within the string and preceded by a percent (%) symbol. After the string, we use another percent(%) symbol followed by a parenthesized list of arguments that will be substituted in place of the embedded conversion types in our string in order. We can also use a comma instead of a percent symbol in order to achieve the same effect. It is merely a matter of preference. Check out the examples of each depicted in the example below. :: - - # Using the % symbol - >>> x = 5 - >>> y = 10 - >>> print 'The sum of %d and %d is %d' % (x, y, (x + y)) - The sum of 5 and 10 is 15 - - >>> adjective = "awesome" - >>> print 'Jython programming is %s' % (adjective) - Jython programming is awesome - - - # Using a comma - >>> print y, " divided by ", x, " is ", y/5 - 10 divided by 5 is 2 - - -You can also format floating-point output using the conversion types that are embedded in your string. You may specify a number of decimal places you’d like to print by using a “.# of places” syntax in the embedded conversion type. :: - - >>> pi = 3.14 - >>> print 'Here is some formatted floating point arithmetic: %.2f' % (pi + y) - Here is some formatted floating point arithmetic: 13.14 - >>> print 'Here is some formatted floating point arithmetic: %.3f' % (pi + y) - Here is some formatted floating point arithmetic: 13.140 - - -If we were working with a list or a range of numbers, we could use a generator to help us with output. It works like as follows: create a generator function that “prints” some output using the *yield* statement. Assign the returned value(s) from the generator to a variable, then print the variable to see the outcome. :: - - >>> def writeX(upper, lower): - ... x = lower - ... y = upper - ... while x < y: - ... yield 'The value of x is: %d' % (x+1) - ... x = x + 1 - ... - >>> out = "".join(writeX(10,5)) - >>> print out - The value of x is: 6The value of x is: 7The value of x is: 8The value of x is: 9The value of x is: 10 - - -Conclusion -========== - -It goes without saying that Python has its share of input and output strategies. This chapter covered most of those techniques starting with basic terminal or command line I/O and then onto file manipulation. We learned how to make use of the *open* function for creating, reading, or writing a file. The command line sys.argv arguments are another way that we can grab input, and environment variables can also be used from within our programs. Following those topics, we took a brief look at the *pickle* module and how it can be used to persist Python objects to disk. *shelve* is another twist on using *pickle* that allows for multiple objects to be indexed and stored within the same file. Finally, we discussed a couple of techniques for performing output in our programs. - - - -Although there are some details that were left out as I/O could consume an entire book, this chapter was a solid starting point into the broad topic of I/O in Python. As with much of the Python language specifics discussed in this book, there are many resources available on the web and in book format that will help you delve deeper into the topics if you wish. - - - -In the next chapter, we will discuss using Jython and Java together. This topic is at the heart of Jython, it is one of the main reasons why Python was implemented in Java. - - +We covered the print statement in Chapter 2 very briefly when discussing string formatting. +The print statement is by far the most utilized form of output in most Python programs. +Although we covered some basics such as conversion types and how to format a line of output in Chapter 2, here we will go into a bit more depth on some different variations of the print statement as well as other techniques for generating output. +There are basically two formats that can be used with the print statement. +We covered the first in Chapter 2, and it makes use of a string and some conversion types embedded within the string and preceded by a percent (``%``) symbol. +After the string, we use another percent(``%``) symbol followed by a parenthesized list of arguments that will be substituted in place of the embedded conversion types in our string in order. +Check out the examples of each depicted in the example below. + +*Listing 5-11. Output With the Print Statement* +:: + + # Using the % symbol + >>> x = 5 + >>> y = 10 + >>> print 'The sum of %d and %d is %d' % (x, y, (x + y)) + The sum of 5 and 10 is 15 + >>> adjective = "awesome" + >>> print 'Jython programming is %s' % (adjective) + Jython programming is awesome + +You can also format floating-point output using the conversion types that are embedded in your string. +You may specify a number of decimal places you’d like to print by using a ``".# of places"`` syntax in the embedded conversion type. + +*Listing 5-12. Formatting Floating-Point Arithmetic* +:: + + >>> pi = 3.14 + >>> print 'Here is some formatted floating point arithmetic: %.2f' % (pi + y) + Here is some formatted floating point arithmetic: 13.14 + >>> print 'Here is some formatted floating point arithmetic: %.3f' % (pi + y) + Here is some formatted floating point arithmetic: 13.140 + +Summary +======= + +It goes without saying that Python has its share of input and output strategies. +This chapter covered most of those techniques starting with basic terminal or command line I/O and then onto file manipulation. +We learned how to make use of the ``open`` function for creating, reading, or writing a file. +The command line ``sys.argv`` arguments are another way that we can grab input, and environment variables can also be used from within our programs. +Following those topics, we took a brief look at the ``pickle`` module and how it can be used to persist Python objects to disk. +The ``shelve`` module is another twist on using ``pickle`` that allows for multiple objects to be indexed and stored within the same file. +Finally, we discussed a couple of techniques for performing output in our programs. + +Although there are some details that were left out as I/O could consume an entire book, this chapter was a solid starting point into the broad topic of I/O in Python. +As with much of the Python language specifics discussed in this book, there are many resources available on the web and in book format that will help you delve deeper into the topics if you wish. +A good resource is “Beginning Python: From Novice to Professional” by Magnus Lie Hetland. +You may also wish to look at the Python documentation which can be found at ``www.python.org/doc/``. diff --git a/LangSyntax.rst b/LangSyntax.rst index 4271055..845d9a4 100644 --- a/LangSyntax.rst +++ b/LangSyntax.rst @@ -1,834 +1,1054 @@ -Chapter 1: Language and Syntax -++++++++++++++++++++++++++++++ - - - - -“Elegant”, that is an adjective that is often used to describe the Python language. The term elegant is defined as “pleasingly graceful and stylish in appearance or manner”. “Uncomplicated”, and “powerful” could also be great words to assist in the description of this language. It is a fact that Python is an elegant language that lets one create powerful applications in an uncomplicated manner. One may say that if you look at trends that are occurring within the computing industry today, Python can be looked at as the main objective. There are dozens, if not hundreds, of programming languages available today which each offer a different flavor to the field. Although there are many flavors, there is a similar objective for each of these programming languages...and that is to produce powerful and uncomplicated code that is easy to construct and maintain. Python does just that. - - - -While we’ve easily defined the goal of programming languages in a broad sense in paragraph one, we have left out one main advantage of learning the Python programming language. The Python language can run everywhere because it has been extended to run on the Java platform. We are talking about Jython, the language implementation that takes the elegance, power, and ease of Python and runs it on the JVM. The Java platform is an asset to the Jython language much like the C libraries are for Python. Jython is able to run just about everywhere, which gives lots of flexibility when deciding how to implement an application. Not only does the Java platform allow for flexibility, but it also offers a vast library containing thousands of APIs which are available for use by Jython. Add-in the maturity of the Java platform and it becomes easy to see why Jython is undoubtedly the main objective of every programming language. The goal, if you will, of any programming language is to grant its developers the same experience which Jython does. Simply put, learning Jython will be an asset to any developer. - - - -As I’ve mentioned that the Jython language implementation basically takes Python and runs it on the JVM, you will find out that it does so much more. Once you have experienced the power of programming on the Java platform it would be a difficult feat to move away from it. Learning Jython not only allows one to stay running on the JVM, but it also allows you to learn a new way to harness the power of the platform. The language increases productivity as it has an easily understood syntax which reads almost as if it were pseudo code. It also adds dynamic abilities that are not available in the Java language itself. In this chapter you will learn how to install and configure your environment, and you will also get an overview of those features which the Python language has to offer. This chapter is not intended to delve so deep into the concepts of syntax as to bore you, but rather to give you a quick and informative introduction to the syntax so that you will know the basics and learn the language as you move on through the book. It will also allow you the chance to compare some Java examples with those which are written in Python so you can see some of the advantages this language has to offer. - - - -By the time you have completed this chapter, you should know the basic structure and organization that Python code should follow. You’ll know how to use basic language concepts such as defining variables, using reserved words, and performing basic tasks. It will give you a taste of using statements and expressions. As every great program contains comments, you’ll learn how to document single lines of code as well as entire code blocks. As you move through the book, you will use this chapter as a reference to the basics. This chapter will not cover each feature in completion, but it will give you enough basic knowledge to start using the Python language. - - - -The Difference Between Jython and Python +Chapter 1: Language and Syntax ++++++++++++++++++++++++++++++++ + +*Elegant* is an adjective that is often used to describe the Python language. +The word elegant is defined as “pleasingly graceful and stylish in appearance or manner.” +*Uncomplicated* and *powerful* could also be great words to assist in the description of this language. +It is a fact that Python is an elegant language that lets one create powerful applications in an uncomplicated manner. +The ability to make reading and writing complex software easier is the objective of all programming languages, and Python does just that. + +While we’ve easily defined the goal of programming languages in a broad sense in paragraph one, we have left out one main advantage of learning the Python programming language: Python has been extended to run on the Java platform, and so it can run anywhere with a JVM. +There are also C and .NET versions of Python with multiplatform support. +So, Python can run nearly everywhere. +In this book, we focus on Jython, the language implementation that takes the elegance, power, and ease of Python and runs it on the JVM. + +The Java platform is an asset to the Jython language much like the C libraries are for Python. +Jython is able to run just about everywhere, which gives lots of flexibility when deciding how to implement an application. +Not only does the Java platform allow for flexibility with regards to application deployment, but it also offers a vast library containing thousands of APIs that are available for use by Jython. +Add in the maturity of the Java platform and it becomes easy to see why Jython is such an attractive programming language. +The goal, if you will, of any programming language is to grant its developers the same experience that Jython does. +Simply put, learning Jython will be an asset to any developer. + +As I’ve mentioned, the Jython language implementation takes Python and runs it on the JVM, but it does much more than that. +Once you have experienced the power of programming on the Java platform, it will be difficult to move away from it. +Learning Jython not only allows you to run on the JVM, but it also allows you to learn a new way to harness the power of the platform. +The language increases productivity as it has an easily understood syntax that reads almost as if it were pseudocode. +It also adds dynamic abilities that are not available in the Java language itself. + +In this chapter you will learn how to install and configure your environment, and you will also get an overview of those features that the Python language has to offer. +This chapter is not intended to delve so deep into the concepts of syntax as to bore you, but rather to give you a quick and informative introduction to the syntax so that you will know the basics and learn the language as you move on through the book. +It will also allow you the chance to compare some Java examples with those which are written in Python so you can see some of the advantages this language has to offer. + +By the time you have completed this chapter, you should know the basic structure and organization that Python code should follow. +You’ll know how to use basic language concepts such as defining variables, using reserved words, and performing basic tasks. +It will give you a taste of using statements and expressions. +As every great program contains comments, you’ll learn how to document single lines of code as well as entire code blocks. +As you move through the book, you will use this chapter as a reference to the basics. +This chapter will not cover each feature in completion, but it will give you enough basic knowledge to start using the Python language. + +The Difference between Jython and Python ======================================== -Jython is an implementation of the Python language for the Java platform. Throughout this book, you will be learning how to use the Python language, and along the way we will show you where the Jython implementation differs from CPython, which is the canonical implementation of Python written in the C language. It is important to note that the Python language syntax remains consistent throughout the different implementations. At the time of this writing, there are three mainstream implementations of Python. These implementations are: CPython, Jython for the Java platform, and IronPython for the .NET platform. - - - -This book will reference the Python language in sections regarding the language syntax or functionality that is inherent to the language itself. However, the book will reference the name Jython when discussing functionality and techniques that are specific to the Java platform implementation. No doubt about it, this book will go in-depth to cover the key features of Jython and you’ll learn concepts that only adhere the Jython implementation. Along the way, you will learn how to program in Python and advanced techniques. - +Jython is an implementation of the Python language for the Java platform. +Throughout this book, you will be learning how to use the Python language, and along the way we will show you where the Jython implementation differs from CPython, which is the canonical implementation of Python written in the C language. +It is important to note that the Python language syntax remains consistent throughout the different implementations. +At the time of this writing, there are three mainstream implementations of Python. +These implementations are: CPython, Jython for the Java platform, and IronPython for the .NET platform. +At the time of this writing, CPython is the most prevalent of the implementations. +Therefore if you see the word Python somewhere, it could well be referring to that implementation. +This book will reference the Python language in sections regarding the language syntax or functionality that is inherent to the language itself. +However, the book will reference the name Jython when discussing functionality and techniques that are specific to the Java platform implementation. +No doubt about it, this book will go in-depth to cover the key features of Jython and you’ll learn concepts that only adhere the Jython implementation. +Along the way, you will learn how to program in Python and advanced techniques. -Developers from all languages and backgrounds will benefit from this book. Whether you are interested in learning Python from for the first time or discovering Jython techniques and advanced concepts, this book is a good fit for any developer. Java developers and those who are new to the Python language will find specific interest in reading through Part I of this book as it will teach the Python language from the basics to more advanced concepts. Seasoned Python developers will probably find more interest in Part II and Part III as they focus more on the Jython implementation specifics. Often times in this reference, you will see Java code compared with Python code. - +Developers from all languages and backgrounds will benefit from this book. +Whether you are interested in learning Python for the first time or discovering Jython techniques and advanced concepts, this book is a good fit. +Java developers and those who are new to the Python language will find specific interest in reading through Part I of this book as it will teach the Python language from the basics to more advanced concepts. +Seasoned Python developers will probably find more interest in Part II and Part III as they focus more on the Jython implementation specifics. +Often in this reference, you will see Java code compared with Python code. Installing and Configuring Jython ================================= - - - -Before we delve into the basics of the language, we’ll learn how to obtain Jython and configure it for your environment. To get started, you will need to obtain a copy of Jython from the official website http://www.jython.org. Since this book focuses on release 2.5, it would be best to visit the site now and download that release. You will see that there are previous releases that are available to you, but they do not contain many of the features which have been included in the 2.5 release. - - - -I think at this point it is important to mention that the Jython implementation maintains consistent features which match those in the Python language for each version. For example, if you download the Jython 2.2.1 release, it will include all of the features that the Python 2.2 release contains. Similarly, when using the 2.5 release you will have access to the same features which are included in Python 2.5. There are also a couple of extra pieces included with the 2.5 release which are specific to Jython. We’ll discuss more about these extra features throughout the book. - - - -Okay, well if you haven’t done so already then please grab yourself a copy of the Jython 2.5 release. You will see that the release is packaged as a cross-platform executable JAR file. Right away, you can see the obvious advantage of running on the Java platform…one installer that works for various platforms. It doesn’t get much easier than that! In order to install the Jython language, you will need to have Java 5 or greater installed on your machine. If you do not have Java 5 or greater then you’d better go and grab that from http://www.java.com and install it before trying to initiate the Jython installer. - - - -You can initiate the Jython installer by simply double-clicking on the JAR file. It will run you through a series of standard installation questions. At one point you will need to determine which features you’d like to install. If you are interested in looking through the source code for Jython, or possibly developing code for the project then you should choose the “All” option to install everything…including source. However, for most Jython developers and especially for those who are just beginning to learn the language, I would recommend choosing the “Standard” installation option. Once you’ve chosen your options and supplied an installation path then you will be off to the races. - - - -In order to run Jython, you will need to invoke the jython.bat executable file on Windows or the jython.sh file on \*NIX machines and Mac OS X. That being said, you’ll have to traverse into the directory that you’ve installed Jython where you will find the file. It would be best to place this directory within your PATH environment variable on either Windows, \*NIX, or OS X machines so that you can fire up Jython from within any directory on your machine. Once you’ve done this then you should be able to open up a terminal or command prompt and issue type “jython” then hit enter to invoke the interactive interpreter. This is where our journey begins! The Jython interactive interpreter is a great place to evaluate code and learn the language. It is a real-time testing environment that allows you to type code and instantly see the result. As you are reading through this chapter, I recommend you open up the Jython interpreter and follow along with the code examples. +Before we delve into the basics of the language, we’ll learn how to obtain Jython and configure it for your environment. +To get started, you will need to obtain a copy of Jython from the official website www.jython.org. +Because this book focuses on release 2.5.x, it would be best to visit the site now and download the most recent version of that release. +You will see that there are previous releases that are available to you, but they do not contain many of the features which have been included in the 2.5.x series. + +Jython implementation maintains consistent features which match those in the Python language for each version. +For example, if you download the Jython 2.2.1 release, it will include all of the features that the Python 2.2 release contains. +Similarly, when using the 2.5 release you will have access to the same features which are included in Python 2.5. +There are also some extra pieces included with the 2.5 release which are specific to Jython. +We’ll discuss more about these extra features throughout the book. + +Please grab a copy of the most recent version of the Jython 2.5 release. +You will see that the release is packaged as a cross-platform executable JAR file. +Right away, you can see the obvious advantage of running on the Java platform...one installer that works for various platforms. +It doesn’t get much easier than that! In order to install the Jython language, you will need to have Java 5 or greater installed on your machine. +If you do not have Java 5 or greater then you’d better go and grab that from www.java.com and install it before trying to initiate the Jython installer. + +You can initiate the Jython installer by simply double-clicking on the JAR file. +It will run you through a series of standard installation questions. +At one point you will need to determine which features you’d like to install. +If you are interested in looking through the source code for Jython, or possibly developing code for the project then you should choose the “All” option to install everything...including source. +However, for most Jython developers and especially for those who are just beginning to learn the language, I would recommend choosing the “Standard” installation option. +Once you’ve chosen your options and supplied an installation path then you will be off to the races. + +In order to run Jython, you will need to invoke the jython.bat executable file on Windows or the jython.sh file on \*NIX machines and Mac OS X. +That being said, you’ll have to traverse into the directory that you’ve installed Jython where you will find the file. +It would be best to place this directory within your PATH environment variable on either Windows, \*NIX, or OS X machines so that you can fire up Jython from within any directory on your machine. +Once you’ve done this then you should be able to open up a terminal or command prompt and type “jython” then hit enter to invoke the interactive interpreter. +This is where our journey begins! The Jython interactive interpreter is a great place to evaluate code and learn the language. +It is a real-time testing environment that allows you to type code and instantly see the result. +As you are reading through this chapter, I recommend you open up the Jython interpreter and follow along with the code examples. Identifiers and Declaring Variables =================================== +Every programming language needs to contain the ability to capture or calculate values and store them. +Python is no exception, and doing so is quite easy. +Defining variables in Python is very similar to other languages such as Java, but there are a few differences that you need to note. +To define a variable in the Python language, you simply name it using an identifier. +An identifier is a name that is used to identify an object. +The language treats the variable name as a label that points to a value. +It does not give any type for the value. +Therefore, this allows any variable to hold any type of data. +It also allows the ability of having one variable contain of different data types throughout the life cycle of a program. +So a variable that is originally assigned with an integer, can later contain a String. +Identifiers in Python can consist of any ordering of letters, numbers, or underscores. +However, an identifier must always begin with a non-numeric character value. +We can use identifiers to name any type of variable, block, or object in Python. +As with most other programming languages, once an identifier is defined, it can be referenced elsewhere in the program. -Every programming language needs to contain the ability to capture or calculate values and store them. Python is no exception, and doing so is quite easy. Defining variables in Python is very similar to other languages such as Java, but there are a few differences that you need to note. - - - -First, variables in Python have no declared type. Therefore, this allows any variable to hold any type of data. It also allows the ability of having one variable contain of different data types throughout the life cycle of a program. So a variable that is originally assigned with an integer, can later contain a String. +Once declared, a variable is untyped and can take any value. +This is one difference between using a statically typed language such as Java, and using dynamic languages like Python. +In Java, you need to declare the type of variable which you are creating, and you do not in Python. +It may not sound like very much at first, but this ability can lead to some extraordinary results. +Consider the following two listings, lets define a value ‘x’ below and we’ll give it a value of zero. +*Listing 1-1. Java – Declare Variable* -To define a variable in the Python language, you simply name it using an identifier. An identifier is a name that is used to identify an object. The language treats the variable name as a label that points to a value. It does not give any type for the value. Identifiers in Python can consist of any ordering of letters, numbers, or underscores. However, an identifier must always begin with a non-numeric character value. We can use identifiers to name any type of variable, block, or object in Python. As with most other programming languages, once an identifier is defined, it can be referenced elsewhere in the program. - - - -Once declared, a variable is untyped and can take any value. This is one difference between using a statically typed language such as Java, and using dynamic languages like Python. In Java, you need to declare the type of variable which you are creating, and you do not in Python. It may not sound like very much at first, but this ability can lead to some extraordinary results. Consider the following, lets define a value ‘x’ below and we’ll give it a value of zero. - -*Java - Declare Variable* :: +.. code-block:: java int x = 0; - -*Python - Declare Variable* :: +*Listing 1-2. Python – Declare Variable* :: x = 0 +As you see, we did not have to give a type to this variable. +We simply choose a name and assign it a value. +Since we do not need to declare a type for the variable, we can change it to a different value and type later in the program. -As you see, we did not have to give a type to this variable. We simply name it and assign a value. You can also see that in Python there is no need to end the declaration with a semicolon. Since we do not need to declare a type for the variable, we can change it to a different value and type later in the program. - +*Listing 1-3.* :: + x = 'Hello Jython' - x = 'Hello Jython' +We’ve just changed the value of the variable ‘x’ from a numeric value to a String without any consequences. +What really occurred is that we created a new variable ‘Hello Jython’ and assigned it to the identifier ‘x’, which in turn lost its reference to 0. +This is a key to the dynamic language philosophy...change should not be difficult. +Let us take what we know so far and apply it to some simple calculations. +Based upon the definition of a variable in Python, we can assign an integer value to a variable, and change it to a float at a later point. +For instance: -We’ve just changed the value of the variable ‘x’ from a numeric value to a String without any consequences. This is a key to the dynamic language philosophy...change should not be difficult, but rather easy to integrate. +*Listing 1-4.* :: + >>> x = 6 + >>> y = 3.14 + >>> x = x * y + >>> print x + 18.84 - -Let us take what we know so far and apply it to some simple calculations. Based upon the definition of a variable in Python, we can assign an integer value to a variable, and change it to a float at a later point. For instance: - - - >>> x = 6 - >>> y = 3.14 - >>> x = x * y - >>> print x - 18.84 - -In the previous example we’ve demonstrated that we can dynamically change the type of any given variable by simply performing a calculation upon it. In other languages, we would have had to begin by assigning a float type to the ‘x’ variable so that we could later change it’s value to a float. Not here, Python allows us to bypass type constriction and gives us an easy way to do it. +In the previous example, we’ve demonstrated that we can dynamically change the type of any given variable by simply performing a calculation upon it. +In other languages such as Java, we would have had to begin by assigning a float type to the ‘x’ variable so that we could later change its value to a float. +Not here, Python allows us to bypass type constriction and gives us an easy way to do it. Reserved Words ============== +There are a few more rules to creating identifiers that we must follow in order to adhere to the Python language standard. +Certain words are not to be used as identifiers as the Python language reserves them for performing a specific role within our programs. +These words which cannot be used are known as reserved words. +If we try to use one of these reserved words as an identifier, we will see a SyntaxError thrown as Python wants these reserved words as its own. +There are no symbols allowed in identifiers. +Yes, that means the Perl developers will have to get used to defining variables without the $. -There are a few more rules to creating identifiers that we must follow in order to adhere to the Python language standard. Certain words are not to be used as identifiers as the Python language reserves them for performing a specific role within our programs. These words which cannot be used are known as reserved words. If we try to use one of these reserved words as an identifier, we will see a SyntaxError thrown as Python wants these reserved words as it’s own. - -There are no symbols allowed in identifiers. Yes, that means the Perl developers will have to get used to defining variables without the $. - +Table 1-1 lists all of the Python language reserved words: +**Table 1-1.** Reserved Words -The complete listing of reserved words is as follows: ++------+---------+-------+-------+----------+ +| and | assert | break | class | continue | ++------+---------+-------+-------+----------+ +| def | del | elif | else | except | ++------+---------+-------+-------+----------+ +| exec | finally | for | from | global | ++------+---------+-------+-------+----------+ +| or | pass | print | raise | return | ++------+---------+-------+-------+----------+ +| try | while | with | yield | | ++------+---------+-------+-------+----------+ -======== ========= ======= ======= ========== -Words -======== ========= ======= ======= ========== -and assert break class continue -def del elif else except -exec finally for from global -if or pass print raise -return try while with yield -======== ========= ======= ======= ========== - -Table 1-1. Reserved Words. The following lists all of the Python language reserved words +It is important to take care when naming variables so that you do not choose a name that matches one of the module names from the standard library. Coding Structure ----------------- - -Another key factor in which Python differs from other languages is it’s coding structure. Back in the day, we had to develop programs based upon a very strict structure such that certain pieces must begin and end within certain punctuations. Python uses positioning and code must adhere to an ordered structure. Unlike languages such as Java that use brackets to open or close a code block, Python uses spacing as to make code easier to read and also limit unnecessary symbols in your code. It strictly enforces ordered and organized code, but it lets the programmer define the rules. - -Python ensures that each block of code adheres to its defined spacing strategy in a consistent manner. What is the defined spacing strategy? You decide. As long as the first line of a code block is out-dented by at least one space, the rest of the block can maintain a consistent indentation, which makes code easy to read. Many argue that it is the structuring technique that Python adheres to which makes them so easy to read. No doubt, adhering to a standard spacing throughout an application makes for organization. As a matter of fact, the Python standard spacing technique is to use four spaces for indentation. If you adhere to these standards then your code will be easy to read and maintain in the future. - -For instance, let’s jump ahead and look at a simple ‘if’ statement. Although you may not yet be familiar with this construct, I think you will agree that it is easy to determine the outcome. Take a look at the following block of code written in Java first, and then we’ll compare it to the Python equivalent. +================ +Another key factor in which Python differs from other languages is its coding structure. +Back in the day, we had to develop programs based upon a very strict structure such that certain pieces must begin and end within certain punctuations. +Python uses indentation rather than punctuation to define the structure of code. +Unlike languages such as Java that use brackets to open or close a code block, Python uses spacing as to make code easier to read and also limit unnecessary symbols in your code. +It strictly enforces ordered and organized code but it lets the programmer define the rules for indentation, although a standard of four characters exists. -*Java if-statement* :: +For instance, let’s jump ahead and look at a simple ‘if’ statement. +Although you may not yet be familiar with this construct, I think you will agree that it is easy to determine the outcome. +Take a look at the following block of code written in Java first, and then we’ll compare it to the Python equivalent. - x = 100; +*Listing 1-5. Java if-statement* - if(x > 0){ - System.out.println("Wow, this is Java"); - } else { - System.out.println("Java likes curly braces"); - } +.. code-block:: java + x = 100; + if (x > 0) { + System.out.println("Wow, this is Java"); + } else { + System.out.println("Java likes curly braces"); + } Now, let’s look at a similar block of code written in Python. -*Python if-statement* :: - - x = 100 - if x > 0: - print 'Wow, this is elegant' - else: - print 'Organization is the key' +*Listing 1-6. Python if-statement* :: - - - -Okay, my example is cheesy but we will go through it nonetheless as it is demonstrating a couple of key points to the Python language. As you see, the program evaluates if the value of the variable ‘x’ is greater than zero. If so, it will print ‘Wow, this is elegant’. Otherwise, it will print ‘Organization is the key’. Look at the indentation which is used within the ‘if’ block. This particular block of code uses four spaces to indent the ‘print’ statement from the initial line of the block. Likewise, the ‘else’ jumps back to the first space of the line and its corresponding implementation is also indented by four spaces. This technique must be adhered to throughout an entire Python application. By doing so we gain a couple of major benefits: Easy-to-read code, and no need to use curly braces. Most other programming languages such as Java use a bracket “[“ or curly brace “{“ to open and close a block of code. There is no need to do so when using Python as the spacing takes care of this for you. Less code = easier to read and maintain. + x = 100 + if x > 0: + print 'Wow, this is elegant' + else: + print 'Organization is the key' + +Okay, this is cheesy but we will go through it nonetheless as it is demonstrating a couple of key points to the Python language. +As you see, the Python program evaluates if the value of the variable ‘x’ is greater than zero. +If so, it will print ‘Wow, this is elegant.’ Otherwise, it will print ‘Organization is the key.’ Look at the indentation which is used within the ‘if’ block. +This particular block of code uses four spaces to indent the ‘print’ statement from the initial line of the block. +Likewise, the ‘else’ jumps back to the first space of the line and its corresponding implementation is also indented by four spaces. +This technique must be adhered to throughout an entire Python application. +By doing so, we gain a couple of major benefits: easy-to-read code and no need to use curly braces. +Most other programming languages such as Java use a bracket “[” or curly brace “{” to open and close a block of code. +There is no need to do so when using Python as the spacing takes care of this for you. +Less code = easier to read and maintain. +It is also worth noting that the Java code in the example could have been written on one line, or worse, but we chose to format it nicely. + +Python ensures that each block of code adheres to its defined spacing strategy in a consistent manner. +What is the defined spacing strategy? You decide. +As long as the first line of a code block is out-dented by at least one space, the rest of the block can maintain a consistent indentation, which makes code easy to read. +Many argue that it is the structuring technique that Python adheres to which makes them so easy to read. +No doubt, adhering to a standard spacing throughout an application makes for organization. +As mentioned previously, the Python standard spacing technique is to use four characters for indentation. +If you adhere to these standards then your code will be easy to read and maintain in the future. +Your brain seems hard-wired to adhering to some form of indentation, so Python and your brain are wired up the same way. Operators ---------- - -The operators that are used by Python are very similar to those used in other languages...straightforward and easy to use. As with any other language, you have your normal operators such as +, -, \*, and / which are available for performing calculations. As you can see from the examples below, there is no special trick to using any of these operators. - -*Example 1: Performing Integer based operations* :: - - >>> x = 9 - >>> y = 2 - >>> x + y - 11 - >>> x - y - 7 - >>> x * y - 18 - >>> x / y - 4 - -Perhaps the most important thing to note with calculations is that if you are performing calculations based on integer values then you will receive a rounded result. If you are performing calculations based upon floats then you will receive float results, etc. +========= -*Example 2: Performing float based operations* :: +The operators that are used by Python are very similar to those used in other languages...straightforward and easy to use. +As with any other language, you have your normal operators such as +, -, \*, and /, which are available for performing calculations. +As you can see from the following examples, there is no special trick to using any of these operators. - >>> x = 9.0 - >>> y = 2.0 - >>> x + y - 11.0 - >>> x - y - 7.0 - >>> x * y - 18.0 - >>> x / y - 4.5 +*Listing 1-7. Performing Integer-based Operations* :: -It is important to note this distinction because as you can see from the differences in the results of the division (/) operations in examples 1 and 2, we have rounding on the integer values and not on the float. A good rule of thumb is that if your application requires precise calculations to be defined, then it is best to use float values for all of your numeric variables, or else you will run into a rounding issue. + >>> x = 9 + >>> y = 2 + >>> x + y + 11 + >>> x - y + 7 + >>> x * y + 18 + >>> x / y + 4 + +Perhaps the most important thing to note with calculations is that if you are performing calculations based on integer values then you will receive a rounded result. +If you are performing calculations based upon floats then you will receive float results, and so on. + +*Listing 1-8. Performing Float-based Operations* :: + + >>> x = 9.0 + >>> y = 2.0 + >>> x + y + 11.0 + >>> x - y + 7.0 + >>> x * y + 18.0 + >>> x / y + 4.5 + +It is important to note this distinction because as you can see from the differences in the results of the division (/) operations in Listings 1-7 and 1-8, we have rounding on the integer values and not on the float. +A good rule of thumb is that if your application requires precise calculations to be defined, then it is best to use float values for all of your numeric variables, or else you will run into a rounding issue. +In Python 2.5 and earlier, integer division always rounds down, producing the floor as the result. +In Python 2.2, the // operator was introduced which is another way to obtain the floor result when dividing integers or floats. +This operator was introduced as a segue way for changing integer division in future releases so that the result would be a *true* division. +In Chapter 3, we’ll discuss division using a technique that always performs *true* division. Expressions ------------ - -Expressions are just what they sound like...they are a piece of Python code that produces a value. For example, if we wish to assign a particular value to a variable then we would use an expression. Similarly, if I wish to perform a calculation based upon two variables or numeric values then I am performing a expression. +=========== -*Examples of Expressions* :: +Expressions are just what they sound like. +They are a piece of Python code that can be evaluated and produces a value. +Expressions are not instructions to the interpreter, but rather a combination of values and operators that are evaluated. +If we wish to perform a calculation based upon two variables or numeric values then we are producing an expression. - >>> x = 9 - >>> y = 2 - >>> z = 9 * 2 - >>> x + y - >>> x - y - >>> x * y - >>> x / y +*Listing 1-9. Examples of Expressions* :: -The examples of expressions that are shown above are very simplistic. Expressions can be made to be very complex and perform powerful computations. They can be combined together to produce complex results. + >>> x + y + >>> x - y + >>> x * y + >>> x / y +The examples of expressions that are shown above are very simplistic. +Expressions can be made to be very complex and perform powerful computations. +They can be combined together to produce complex results. -Statements ----------- +Functions +========= -When we refer to statements, we are really referring to a line of code that does something. There are several statements that can be issued in Python that ultimately define the different constructs available for use within an application. In this section, we will take a tour of statement keywords and learn how they can be used. +Oftentimes it is nice to take suites of code that perform specific tasks and extract them into their own unit of functionality so that the code can be reused in numerous places without retyping each time. +A common way to define a reusable piece of code is to create a function. +Functions are named portions of code that perform that usually perform one or more tasks and return a value. +In order to define a function we use the *def* statement. -Let’s start out by listing each of these different statement keywords, and then we will go into more detail about how to use each of them with different examples. I will not cover each statement keyword in this chapter as some of them are better left for later in the chapter or the book, but you should have a good idea of how to code an action which performs a task after reading through this section. While this section will provide implementation details about the different statements, you should refer to later chapters to find advance uses of these features. +The *def* statement will become second nature for usage throughout any Python programmer’s life. +The *def* statement is used to define a function. +Here is a simple piece of pseudocode that shows how to use it. -Table 1-1. Statement Keywords +*Listing 1-10.* :: + def my_function_name(parameter_list): + implementation -======== ===== -Words -======== ===== -if -else -for -while -continue -break -======== ===== +The pseudocode above demonstrates how one would use the *def* statement, and how to construct a simple function. +As you can see, *def* precedes the function name and parameter list when defining a function. -If - Else Statement -------------------- +*Listing 1-11.* :: + >>> def my_simple_function(): + ... print 'This is a really basic function' + ... + >>> my_simple_function() + This is a really basic function -The if statement simply performs a comparison on two or more values and provides a logical outcome based upon that evaluation. If statements are quite often used for branching code into one direction or another based upon certain values which have been calculated or provided in the code. +This example is about the most basic form of function that can be created. +As you can see, the function contains one line of code which is a print statement. +We will discuss the print statement in more detail later in this chapter; however, all you need to know now is that it is used to print some text to the screen. +In this case, we print a simple message whenever the function is called. +Functions can accept parameters, or other program variables, that can be used within the context of the function to perform some task and return a value. -For instance, the statement will compare the values and return a boolean result, namely True or False. A corresponding action is then taken based upon the outcome of the boolean result. Pseudocode would be as follows:: +*Listing 1-12.* :: + >>> def multiply_nums(x, y): + ... return x * y + ... + >>> multiply_nums(25, 7) + 175 - if True: - perform an action - else: - perform another action +As seen above, parameters are simply variables that are assigned when the function is called. +Specifically, we assign 25 to *x* and 7 to *y* in the example. +The function then takes *x* and *y,* performs a calculation and returns the result. +Functions in Python are just like other variables and they be passed around as parameters to other functions if needed. +Here we show a basic example of passing one function to another function. +We’ll pass the *multiply_nums* function into the function below and then use it to perform some calculations. -Any number of *if/else* statements can be linked together in order to create a logical code branch, if you wish to use more than one else statement then all but the last else statements must be *elif* instead...and the last would be *else*. Note that each expression must be indented with the conditional statement out-dented and the resulting operation indented. Remember, a consistent indentation must be followed throughout the course of the program. The if statement is a good example of how well the consistent use of indention helps readability of a program. If you are coding in Java for example, you can space the code however you’d like as long as you use the curly braces to enclose the statement. This can lead to code that is very hard to read…the indentation which Python requires really shines through here. +*Listing 1-13.* :: -:: + >>> def perform_math(oper): + ... return oper(5, 6) + ... + >>> perform_math(multiply_nums) + 30 - >>> if x == y: - ... print 'x is equal to y' - ... elif x > y: - ... print 'x is greater than y' - ... else: - ... print 'x is less than y' - ... - x is greater than y +Although this example is very basic, you can see that another function can be passed as a parameter and then used within another function. +For more detail on using *def* and functions, please take a look at Chapter 4, which is all about functions. +Classes +======= -While the code is simple, it demonstrates that using an *if* statement can result in branching code logic. +Python is an object-oriented programming language. +which means that everything in the language is an object of some type. +Much like building blocks are used for constructing buildings, each object in Python can be put together to build pieces of programs or entire programs. +This section will give you a brief introduction to Python classes, which are one of the keys to object orientation in this language. + +Classes are defined using the *class* keyword. +Classes can contain functions, methods, and variables. +Methods are just like functions in that the *def* keyword is used to create them, and they accept parameters. +The only difference is that methods take a parameter known as *self* that refers to the object to which the method belongs. +Classes contain what is known as an initializer method, and it is called automatically when a class is instantiated. +Let’s take a look at a simple example and then explain it. + +*Listing 1-14. Simple Python Class* :: + + >>> class my_object: + ... def __init__(self, x, y): + ... self.x = x + ... self.y = y + ... + ... def mult(self): + ... print self.x * self.y + ... + ... def add(self): + ... print self.x + self.y + ... + >>> obj1 = my_object(7, 8) + >>> obj1.mult() + 56 + >>> obj1.add() + 15 + +In this class example, we define a class named *my_object*. +The class accepts two parameters, *x* and *y*. +A class initializer method is named *__init__()*, and it is used to initialize any values that may be used in the class. +An initializer also defines what values can be passed to a class in order to create an object. +You can see that each method and function within the class accepts the *self* argument. +The *self* argument is used to refer to the object itself, this is how the class shares variables and such. +The *self* keyword is similar to *this* in Java code. +The *x* and *y* variables in the example are named *self.x* and *self.y* in the initializer, that means that they will be available for use throughout the entire class. +While working with code within the object, you can refer to these variables as *self.x* and *self.y*. +If you create the object and assign a name to it such as *obj1*, then you can refer to these same variables as *obj1.x* and *obj1.y*. + +As you can see, the class is called by passing the values 7 and 8 to it. +These values are then assigned to *x* and *y* within the class initializer method. +We assign the class object to an identifier that we call *obj1*. +The *obj1* identifier now holds a reference to *my_object()* with the values we’ve passed it. +The *obj1* identifier can now be used to call methods and functions that are defined within the class. + +For more information on classes, please see Chapter 6, which covers object orientation in Python. +Classes are very powerful and the fundamental building blocks for making larger programs. -There are also some statements in Python which assist in logic flow. These statements can be placed within an if statement or a loop (discussed in chapter 2) which will cause the logic of the statement to go in one direction or the other. +Statements +========== +When we refer to statements, we are really referring to a line of code that contains an instruction that does something. +A statement tells the Python interpreter to perform a task. +Ultimately, programs are made up of a combination of expressions and statements. +In this section, we will take a tour of statement keywords and learn how they can be used. +Let’s start out by listing each of these different statement keywords, and then we will go into more detail about how to use each of them with different examples. +I will not cover every statement keyword in this section as some of them are better left for later in the chapter or the book, but you should have a good idea of how to code an action which performs a task after reading through this section. +While this section will provide implementation details about the different statements, you should refer to later chapters to find advanced uses of these features. -pass Statement --------------- +**Table 1-2.** Statement Keywords -Another useful statement for while working within loops is the *pass* statement. Often times we have the need to use a placeholder value in an application in order to simply pass through an area without performing any tasks when an area of code requires an implementation. The pass statement simply does nothing. An example for it’s usage would be when you have a block of code which you’d like to bypass for debugging purposes. It can also be used as a placeholder for a block of code which has not yet been implemented. ++----------------+----------------------+ +| if\-elif\-else | for | ++----------------+----------------------+ +| while | continue | ++----------------+----------------------+ +| break | try\-except\-finally | ++----------------+----------------------+ +| assert | def | ++----------------+----------------------+ +| print | del | ++----------------+----------------------+ +| raise | import | ++----------------+----------------------+ -:: +Now that we’ve taken a look at each of these keywords, it is time to look at each of them in detail. +It is important to remember that you cannot use any of these keywords for variable names. - while False: - pass +if-elif-else Statement +---------------------- +The if statement simply performs an evaluation on an expression and does different things depending on whether it is *True* or *False*. +If the expression evaluates to *True* then one set of statements will be executed, and if it evaluates to *False* a different set of statements will be executed. +If statements are quite often used for branching code into one direction or another based upon certain values which have been calculated or provided in the code. -def Statement -------------- -This is one of those statements that will become second nature for usage throughout any Python programmer's life. The *def* statement is used to define a function in an application. While we will not get into functions in this chapter, I will show you an example of this statement's usage. +Pseudocode would be as follows: -:: +*Listing 1-15.* :: + if : + perform an action + else: + perform a different action - def myFunctionName(parameterList): - implementation +Any number of *if/else* statements can be linked together in order to create a logical code branch. +When there are multiple expressions to be evaluated in the same statement, then the *elif* statement can be used to link these expressions together*. +*Note that each set of statements within an *if-elif-*else statement must be indented with the conditional statement out-dented and the resulting set of statements indented. +Remember, a consistent indentation must be followed throughout the course of the program. +The *if* statement is a good example of how well the consistent use of indention helps readability of a program. +If you are coding in Java for example, you can space the code however you’d like as long as you use the curly braces to enclose the statement. +This can lead to code that is very hard to read…the indentation which Python requires really shines through here. +*Listing 1-16. Example of if statement* :: + >>> x = 3 + >>> y = 2 + >>> if x == y: + ... print 'x is equal to y' + ... elif x > y: + ... print 'x is greater than y' + ... else: + ... print 'x is less than y' + ... + x is greater than y -The pseudocode above demonstrates how one would use the *def* statement. +While the code is simple, it demonstrates that using an *if* statement can result in branching code logic. print Statement --------------- -The *print* statement is used to display program output onto the screen. It can be used for displaying messages which are printed from within a program and also for printing values which may have been calculated. In order to display variable values within a print statement, we need to learn how to use some of the formatting options which are available to Python. This section will cover the basics of using the print statement along with how to display values by formatting your strings of text. +The *print* statement is used to display program output onto the screen (you’ve already seen it in action several times). +It can be used for displaying messages, which are printed from within a program, and also for printing values, which may have been calculated. +In order to display variable values within a print statement, we need to learn how to use some of the formatting options that are available to Python. +This section will cover the basics of using the print statement along with how to display values by formatting your strings of text. +In the Java language, we need to make a call to the System library in order to print something to the command line. +In Python, this can be done with the use of the *print* statement. +The most basic use of the *print* statement is to display a line of text. +In order to do so, you simply enclose the text that you want to display within single or double quotes. +Take a look at the following example written in Java, and compare it to the example immediately following which is rewritten in Python. +I think you’ll see why the *print* statement in Python makes life a bit easier. +*Listing 1-17. Java Print Output Example* -In the Java language, we need to make a call to the System library in order to print something to the command line. In Python, this can be done with the use of the print statement. The most basic use of the *print* statement is to display a line of text. In order to do so, you simply enclose the text which you want to display within single or double quotes. Take a look at the following example written in Java, and compare it to the example immediately following which is rewritten in Python. I think you’ll see why the print statement in Jython makes life a bit easier. +.. code-block:: java -Java Print Output Example :: + System.out.println("This text will be printed to the command line"); - public void inspectValue(String val){ - if (val == null){ - System.out.println("The value you have entered is not valid, please try again"; - } else { - System.out.println("The value you have entered is valid"); +*Listing 1-18. Python Print Output Example* :: + print 'This text will be printed to the command line' -Python Print Output Example :: - - def inspectValue(val): - if val == None: - print 'The value you have entered is not valid, please try again' - else: - print 'The value you have entered valid' +As you can see from this example, printing a line of text in Python is very straightforward. +We can also print variable values to the screen using the *print* statement. +*Listing 1-19.* :: -As you can see from the example above, printing a line of text in Python is very straight forward. We can also print variable values to the screen using the print statement. :: + >>> my_value = 'I love programming in Jython' + >>> print my_value + I love programming in Jython - myValue = 'I love programming in Jython' - print myValue +Once again, very straightforward in terms of printing values of variables. +Simply place the variable within a print statement. +We can also use this technique in order to append the values of variables to a line of text. +In order to do so, just place the concatenation operator (+) in between the String of text which you would like to append to, and the variable you’d like to append. - >>> I love programming in Jython +*Listing 1-20.* :: + >>> print 'I like programming in Java, but ' + my_value + I like programming in Java, but I love programming in Jython -Once again, very straight forward in terms of printing values of variables. Simply place the variable within a print statement. We can also use this technique in order to append the values of variables to a line of text. In order to do so, just place the concatenation operator (+) in between the String of text which you would like to append to, and the variable you'd like to append. :: +This is great and all, but really not useful if you’d like to properly format your text or work with *int* values. +After all, the Python parser is treating the (+) operator as a concatenation operator in this case...not as an addition operator. +Python bases the result of the (+) operator on the type of the first operand. +If you try to append a numeric value to a String you will end up with an error. - print 'I like programming in Java, but ' + myValue +*Listing 1-21.* :: - >>> I like programming in Java, but I love programming in Jython - -This is great and all, but really not useful if you'd like to properly format your text or work with int values. After all, the Jython parser is treating the (+) operator as a concatenation operator in this case...not as an addition operator. If you try to append a numeric value to a String you will end up with an error. :: - - z = 10 + >>> z = 10 >>> print 'I am a fan of the number: ' + z Traceback (most recent call last): File "", line 1, in TypeError: cannot concatenate 'str' and 'int' objects +As you can see from this example, Python does not like this trick very much. +So in order to perform this task correctly we will need to use some of the aforementioned Python formatting options. +This is easy and powerful to do, and it allows one to place any content or value into a print statement. +Before you see an example, let’s take a look at some of the formatting operators and how to choose the one that you need. ++----+---------+ +| %s | String | ++----+---------+ +| %d | Decimal | ++----+---------+ +| %f | Float | ++----+---------+ -As you can see from the example, Python does not like this trick very much. So in order to perform this task correctly we will need to use some of the aforementioned Python formatting options. This is easy and powerful to do, and it allows one to place any content or value into a print statement. Before you see an example, let's take a look at some of the formatting operators and how to choose the one that you need. -%s - String -%d - Decimal -%f - Float +If you wish to include the contents of a variable or the result of an expression in your *print* statement, you’ll use the following syntax: -If you wish to include the contents of a variable or the result of an expression in your print statement, you'll use the following syntax: :: +*Listing 1-22.* :: print 'String of text goes here %d %s %f' % (decimalValue, stringValue, floatValue) -In the pseudocode above (if we can really have pseudocode for print statements), we wish to print the string of text which is contained within the single quotes, but also have the values of the variables contained where the formatting operators are located. Each of the formatting operators, which are included in the string of text, will be replaced with the corresponding values from those variables at the end of the print statement. The % symbol between the line of text and the list of variables tells Python that the it should expect the variables to follow, and that these value of these variables should be placed within the string of text in their corresponding positions. :: +In the pseudocode above (if we can really have pseudocode for print statements), we wish to print the string of text, which is contained within the single quotes, but also have the values of the variables contained where the formatting operators are located. +Each of the formatting operators, which are included in the string of text, will be replaced with the corresponding values from those variables at the end of the print statement. +The % symbol between the line of text and the list of variables tells Python that it should expect the variables to follow, and that the value of these variables should be placed within the string of text in their corresponding positions. - >>> stringValue = 'hello world' - >>> floatValue = 3.998 - >>> decimalValue = 5 - >>> print 'Here is a test of the print statement using the values: %d, %s, and %f' % (decimalValue, stringValue, floatValue) +*Listing 1-23.* :: + >>> string_value = 'hello world' + >>> float_value = 3.998 + >>> decimal_value = 5 + >>> print 'Here is a test of the print statement using the values: %d, %s, and %f' % (decimal_value, string_value, float_value) Here is a test of the print statement using the values: 5, hello world, and 3.998000 -As you can see this is quite easy to use and very flexible. The next example shows that we also have the option of using expressions as opposed to variables within our statement. :: +As you can see this is quite easy to use and very flexible. +The next example shows that we also have the option of using expressions as opposed to variables within our statement. + +*Listing 1-24.* :: >>> x = 1 >>> y = 2 >>> print 'The value of x + y is: %d' % (x + y) The value of x + y is: 3 +The formatting operator that is used determines how the output looks, it does not matter what type of input is passed to the operator. +For instance, we could pass an integer or float to %s and it would print just fine, but it will in effect be turned into a string in its exact format. +If we pass an integer or float to %d or %f, it will be formatted properly to represent a decimal or float respectively. +Take a look at the following example to see the output for each of the different formatting operators. -Another useful feature of the print statement is that it can be used for debugging purposes . If we simply need to find out the value of a variable during processing then it is easy to display using the *print* statement. Often times, using this technique can really assist in debugging and writing your code. +*Listing 1-25.* :: + >>> x = 2.3456 + >>> print '%s' % x + 2.3456 + >>> print '%d' % x + 2 + >>> print '%f' % x + 2.345600 + +Another useful feature of the print statement is that it can be used for debugging purposes. +If we simply need to find out the value of a variable during processing then it is easy to display using the *print* statement. +Using this technique can often really assist in debugging and writing your code. try-except-finally ------------------ -The *try-except-finally* is the supported method for performing error handling within a Python application. The idea is that we try to run a piece of code and if it fails then it is caught and the error is handled in a proper fashion. We all know that if someone is using a program that displays an ugly long error message, it is not usually appreciated. Using the *try-except-finally* statement to properly catch and handle our errors can mitigate an ugly program dump. - - - -This approach is the same concept that is used within many languages, including Java. There are a number of defined *error types* within the Python programming language and we can leverage these error types in order to facilitate the *try-except-finally* process. When one of the defined error types is caught, then an implementation can be coded for handling the error, or can simply be logged, ignored, etc. The main idea is to avoid those ugly error messages and handle them neatly. If there is an exception that is caught within the block of code and we need a way to perform some cleanup tasks, we would place the cleanup code within the finally clause of the block. All code within the finally clause is always invoked. - - - -To begin, let's work with defining a generic *try-except-finally* example in which we simply place the *try* block around a piece of code and catch any errors that may be thrown. We'll assume that we are not sure exactly which type of error will be thrown, so to generically define the *try-except-finally*, we will use an error type of *Exception*...the default Python error type. - - - -:: - - - try: - implementation that may throw an error - except Exception: - handle the error which was thrown - finally: - perform some cleanup…called everytime - - - -To augment this example, we'll go ahead and define a simple function which takes two parameters and returns the value of the first parameter divided by the second. In order to demonstrate the *try-except-finally*, we'll throw one around the print statement in order to catch the programmer's mistake gracefully. - -:: - - - >>> def myFunction(x,y): - ... try: - ... print x / y - ... except Exception: - ... print 'An error has been caught by the program' - ... finally: - ... print 'Perform some cleanup' +The *try-except-finally* is the supported method for performing error handling within a Python application. +The idea is that we try to run a piece of code and if it fails then it is caught and the error is handled in a proper fashion. +We all know that if someone is using a program that displays an ugly long error message, it is not usually appreciated. +Using the *try-except-finally* statement to properly catch and handle our errors can mitigate an ugly program dump. - >>> myFunction(0,0) - An error has been caught by the program - Perform some cleanup +This approach is the same concept that is used within many languages, including Java. +There are a number of defined *error types* within the Python programming language and we can leverage these error types in order to facilitate the *try-except-finally* process. +When one of the defined error types is caught, then a suite of code can be coded for handling the error, or can simply be logged, ignored, and so on. +The main idea is to avoid those ugly error messages and handle them neatly by displaying a formatted error message or performing another process. +*Listing 1-26.* :: -We can see that by throwing the *try-except-finally* statement around the erroneous code, we've successfully caught the error and displayed a nice message. This will make our application users happy. However, this is not very practical because we don't really have any idea why the error was thrown or which error was thrown. In order to provide more specific details of the error, it is possible to name the exception and then display it or log it in the implementation. - -:: - - - >>> def myFunction(x,y): - ... try: - ... print x / y - ... except Exception, err: - ... print 'The following error has been caught: %s' %(err) - - >>> myFunction(4,2) - 2 - >>> myFunction(0,0) - The following error has been caught: integer division or modulo by zero - - - -Alright, this is looking much better now as we have named the exception "err" and then displayed it in our output. Now the application user has a meaningful error message to tell us about when they reach this piece of code. While this is much better than the generic error that we included in the first example, we still have not found the best way to handle the error. The details of this topic can be read about more in Chapter 5: Exception Handling in Jython. - -assert Statement ----------------- - -Assert statements are used for debugging purposes and error handling within a Python program. Basically, the assert statement checks to ensure that some value or expression is True. If it is True, then execution will continue without anything happening, but if it is False then the program will indicate as such by throwing an *AssertionError*. Errors and exceptions will be covered in more detail in later chapters. For now, understand that by throwing an *AssertionError*, the code can be flagged as incorrect in an instance where we are trying to debug for a True value. - -Example of Assertion: :: - - >>> x = 10 - >>> assert x == 11 - Traceback (most recent call last): - File "", line 1, in - AssertionError - -In the given example, the assertion checks to see if x is equal to eleven. Obviously we can see that it is not, so it throws the expected AssertionError. + >>> # Suppose we've calculated a value and assigned it to x + >>> x + 8.97 + >>> y = 0 + >>> try: + ... print 'The rocket trajectory is: %f' % (x/y) + ... except: + ... print 'Houston, we have a problem. + ... + Houston, we have a problem. +If there is an exception that is caught within the block of code and we need a way to perform some cleanup tasks, we would place the cleanup code within the *finally* clause of the block. +All code within the *finally* clause is always invoked before the exception is raised. +The details of this topic can be read about more in Chapter 7. +In the next section, we’ll take a look at the raise statement, which we can use to raise exceptions at any point in our program. raise Statement --------------- +As mentioned in the previous section, the *raise* statement is used to throw or “raise” an exception in Python. +We know that a *try-except* clause is needed if Python decides to raise an exception, but what if you’d like to raise an exception of your own? You can place a *raise* statement anywhere that you wish to raise a specified exception. +There are a number of defined exceptions within the language which can be raised. +For instance, NameError is raised when a specific piece of code is undefined or has no name. +For a complete list of exceptions in Python, please visit Chapter 7. -The raise statement is used to throw or “raise” an exception in Python. You can place a raise statement anywhere that you wish to throw a specified error. There are a number of defined exceptions within the language which can be thrown. For instance, NameError is thrown when a specific piece of code is undefined or has no name. For a complete list of exceptions in Python, please visit Chapter 5. - -:: - - - >>> raise NameError - Traceback (most recent call last): - File "", line 1, in - NameError - - - -If you wish to specify your own message within a raise then you can do so by raising a generic Exception, and then specifying your message on the statement as follows. - +*Listing 1-27.* :: + >>> raise NameError + Traceback (most recent call last): + File "", line 1, in + NameError - >>> raise Exception('Custom Exception') - Traceback (most recent call last): - File "", line 1, in - Exception: Custom Exception +If you wish to specify your own message within a *raise* then you can do so by raising a generic Exception, and then specifying your message on the statement as follows. +*Listing 1-28.* :: + >>> raise Exception('Custom Exception') + Traceback (most recent call last): + File "", line 1, in + Exception: Custom Exception import Statement ---------------- +A program can be made up of one or more suites of code. +In order to save a program so that it can be used later, we place the code into files on our computer. +Files that contain Python code should contain a *.py* suffix such as my_code.py and so forth. +These files are known as modules in the Python world. +The *import* statement is used much like it is in other languages, it brings external modules or code into a program so that it can be used. +This statement is ultimately responsible for reuse of code in multiple locations. +The *import* statement allows us to save code into a flat file or script, and then use it in an application at a later time. -The import statement is use much like it is in other languages, it brings external modules or code into a program so that it can be used. This statement is ultimately responsible for reuse of code in multiple locations. The import statement allows us to save code into a flat file or script, and then use it in an application at a later time. +If a class is stored in an external module that is named the same as the class itself, the *import* statement can be used to explicitly bring that class into an application. +Similarly, if you wish to import only a specific identifier from another module into your current module, then the specific code can be named within using the syntax *from <> import <>*. +Time to see some examples. +*Listing 1-29.* :: + # Import a module named TipCalculator + import TipCalculator + # Import a function tipCalculator from within a module called ExternalModule.py + from ExternalModule import tipCalculator -There are a couple of different ways in which this statement can be used. It can be used to simply import a named module into an application, or it can be used to import a module or piece of code. If a class is stored in an external module that is named the same as the class itself, the import statement can be used to explicitly bring that class into an application. Similarly, if you wish to import only a portion of code which is contained within an external module, then the specific code can be named within using the syntax from <> import <>. Time to see some examples. +When importing modules into your program, you must ensure that the module being imported does not conflict with another name in your current program. +To import a module that is named the same as another identifier in your current program, you can use the *as* syntax. +In the following example, let’s assume that we have defined an external module with the name of *tipCalculator.py* and we want to use it’s functionality in our current program. +However, we already have a function named *tipCalculator()* within the current program. +Therefore, we use the *as* syntax to refer to the *tipCalculator* module. -:: +*Listing 1-30.* :: + import tipCalculator as tip - # Import a class named TipCalculator which is contained within - # a module named TipCalculator.py +This section just touches the surface of importing and working with external modules. +For a more detailed discussion, please visit Chapter 7 which covers this topic specifically. - import TipCalculator +Iteration +========= +The Python language has several iteration structures which are used to traverse through a series of items in a list, database records, or any other type of collection. +A list in Python is a container that holds objects or values and can be indexed. +For instance, we create a list of numbers in the following example. +We then obtain the second element in the list by using the index value of 1 (indexing starts at zero, so the first element of the list is my_numbers[0]). - # Import a function tipCalculator from within a module called ExternalModule.py - - from ExternalModule import tipCalculator - -Other Python Statements ------------------------ - - -There are some other Python statements that can be used within applications as well, but they are probably better meant to be discussed within a later chapter as they provide more advanced functionality. The following is a listing of other Python statements which you will read more about later on: - - - -exec – Execute Python code in a dynamic fashion - -global – References a global variable (Chapter 4) - -with – New feature in 2.5 using __future__ (Chapter 7) - -class – Create or define a new class object (Chapter 6) - -yield – Used with generators, returns a value (Chapter 4) +*Listing 1-31.* :: + >>> my_numbers = [1, 2, 3, 4, 5] + >>> my_numbers + [1, 2, 3, 4, 5] + >>> my_numbers[1] + 2 -Iteration -========= +For more information on lists, please see Chapter 2 that goes into detail about lists and other containers that can be used in Python. +The most commonly used iteration structure within the language is probably the *for* loop, which is known for its easy syntax and practical usage. -The Python language has several iteration structures which are used to traverse through a series of items in a list, database records, or any other type of collection. The most commonly used iteration structure within the language is probably the *for* loop, which is known for its easy syntax and practical usage. However, the *while* loop still plays an important role in iteration, especially when you are not dealing with collections of data, but rather working with conditional expressions. +*Listing 1-32.* :: + >>> for value in my_numbers: + ... print value + ... + 1 + 2 + 3 + 4 + 5 +However, the *while* loop still plays an important role in iteration, especially when you are not dealing with collections of data, but rather working with conditional expressions. +In this simple example, we use a *while* loop to iterate over the contents of *my_numbers*. +Note that the *len()* function just returns the number of elements that are contained in the list. -This section will take you though each of these two iteration structures and touch upon the basics of using them. The *while* loop is relatively basic in usage, whereas there are many different implementations and choices when using the *for* loop. I will only touch upon the *for* loop from a high-level perspective in this introductory chapter, but if you wish to go more in-depth then please visit Chapter 3. +*Listing 1-33.* :: + >>> x = 0 + >>> while x < len(my_numbers): + ... print my_numbers[x] + ... x = x + 1 + ... + 1 + 2 + 3 + 4 + 5 +This section will take you though each of these two iteration structures and touch upon the basics of using them. +The *while* loop is relatively basic in usage, whereas there are many different implementations and choices when using the *for* loop. +I will only touch upon the *for* loop from a high-level perspective in this introductory chapter, but if you wish to go more in-depth then please visit Chapter 3. While Loop ---------- -The *while* loop construct is used in order to iterate through code based upon a provided conditional statement. As long as the condition is true, then the loop will continue to process. Once the condition evaluates to false, the looping ends. The pseudocode for *while* loop logic reads as follows: - -:: - +The *while* loop construct is used in order to iterate through code based upon a provided conditional statement. +As long as the condition is true, then the loop will continue to process. +Once the condition evaluates to false, the looping ends. +The pseudocode for *while* loop logic reads as follows:: while True - perform operation - -The loop begins with the declaration of the *while* and conditional expression, and it ends once the conditional has been met. Keep in mind that we need to indent each of the lines of code that exist within the *while* loop. This not only helps the code to maintain readability, but it also allows Python to do away with the curly braces! + perform operation +The loop begins with the declaration of the *while* and conditional expression, and it ends once the conditional has been met and the expression is *True*. +The expression is checked at the beginning of each looping sequence, so normally some value that is contained within the expression is changed within the suite of statements inside the loop. +Eventually the value is changed in such a way that it makes the expression evaluate to False, otherwise an infinite loop would occur. +Keep in mind that we need to indent each of the lines of code that exist within the *while* loop. +This not only helps the code to maintain readability, but it also allows Python to do away with the curly braces! +*Listing 1-34. Example of a Java While Loop* -:: +.. code-block:: java - int x = 9; - int y = 2; - int z = x – y; - while (y < x){ - System.out.println("y is " + z + " less than x"); - y = y++; - } + int x = 9; + int y = 2; + while (y < x) { + System.out.println("y is " + (x-y) + " less than x"); + y += 1; + } Now, let’s see the same code written in Python. +*Listing 1-35. Example of a Python While Loop* :: - >>> x = 9 - >>> y = 2 - >>> while y < x: - ... print 'y is %d less than x' % (x-y) - ... y = y + 1 - ... - y is 7 less than x - y is 6 less than x - y is 5 less than x - y is 4 less than x - y is 3 less than x - y is 2 less than x - y is 1 less than x - - - -In the example above, you can see that the conditional *y < x* is evaluated each time the loop passes. Along the way, we increment the value of *y* by one each time we iterate, so that eventually *y* is no longer < than *x* and the loop ends. - - + >>> x = 9 + >>> y = 2 + >>> while y < x: + ... print 'y is %d less than x' % (x-y) + ... y += 1 + ... + y is 7 less than x + y is 6 less than x + y is 5 less than x + y is 4 less than x + y is 3 less than x + y is 2 less than x + y is 1 less than x + +In this example, you can see that the conditional *y < x* is evaluated each time the loop passes. +Along the way, we increment the value of *y* by one each time we iterate, so that eventually *y* is no longer less than *x* and the loop ends. For Loop -------- -We will lightly touch upon *for* loops in this chapter, but you can delve deeper into the topic in chapter two or three when lists, dictionaries, tuples, and ranges are discussed. For now, you should know that a *for* loop is used to iterate through a defined set of values. *For* loops are very useful for performing iteration through values because this is a concept which is used in just about any application. For instance, if you retrieve a list of database values, you can use a *for* loop to iterate through them and print each one out. - - - -The pseudocode to *for* loop logic is as follows: +We will lightly touch upon *for* loops in this chapter, but you can delve deeper into the topic in chapter two or three when lists, dictionaries, tuples, and ranges are discussed. +For now, you should know that a *for* loop is used to iterate through a defined set of values. +The *for* loop is very useful for performing iteration through values because this is a concept which is used in just about any application. +For instance, if you retrieve a list of database values, you can use a *for* loop to iterate through them and print each one out. -:: +The pseudocode to *for* loop logic is as follows:: for each value in this defined set: - perform operation - -As you can see with the pseudocode, I’ve indented in a similar fashion to the way in which the other expression constructs are indented. This uniform indentation practice is consistent throughout the Python programming language. We’ll compare the for loop in Java to the Python syntax below so that you can see how the latter makes code more concise. - + perform suite of operations +As you can see with the pseudocode, I’ve indented in a similar fashion to the way in which the other expression constructs are indented. +This uniform indentation practice is consistent throughout the Python programming language. +We’ll compare the *for* loop in Java to the Python syntax below so that you can see how the latter makes code more concise. -:: - - for (x = 0; x <= 10; x++){ - System.out.println(x); - } +*Listing 1-36. Example of Java For Loop* +.. code-block:: java + for (int x = 0; x <= 10; x++) { + System.out.println(x); + } Now, the same code implemented in Python: - >>> for x in range(10): - ... print x - ... - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - - - -In the above example, we use a construct which has not yet been discussed. A range is a built-in function for Python which simply provides a range from one particular value to another. In the example, we pass the value 10 into the range which gives us all values between 0 and 10. We see this in the resulting print out after the expression. - - - -It is time to go back and cover a couple of Python statement keywords which we passed over previously. Now that we’ve seen how to implement a loop within the language, it is a good time to cover some statements that can be used along with a loop. - -continue Statement ------------------- - -The *continue* statement is to be used when you are within a looping construct, and you have the requirement to tell Python to *continue* processing past the rest of the statements in the current loop. Once the Python interpreter sees a *continue* statement, it ends the current iteration of the loop and goes on to continue processing the next iteration. The continue statement can be used with any looping construct. - - - -:: - - - >>> x = 10 - >>> while x >= 0: - ... if x == 0: - ... continue - ... else: - ... print "x is currently equal to ", x - ... x = x - 1 - ... - x is currently equal to 10 - x is currently equal to 9 - x is currently equal to 8 - x is currently equal to 7 - x is currently equal to 6 - x is currently equal to 5 - x is currently equal to 4 - x is currently equal to 3 - x is currently equal to 2 - x is currently equal to 1 - - - -In the example above, the x variable decreased by one each time the loop iterates. On the final pass, as the x is equal to 0 we do not display a message. Why is this example useful? It’s not really…only to give you an understanding of the context in which the continue statement would be used. - -break Statement ---------------- - -Much like the *continue* statement, the *break* statement can be used inside of a loop. We use the *break* statement in order to break out of a current loop so that a program can move onto its next task. If we are working with a break statement that resides within a loop that is contained in another loop (nested loop construct), then that inner loop will be terminated. Let’s check it out: +*Listing 1-37. Example of Python For Loop* :: + + >>> for x in range(10): + ... print x + ... + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + +In this example, we use a construct which has not yet been discussed. +A range is a built-in function for Python which simply provides a range from one particular value to another. +In the example, we pass the value 10 into the range which gives us all values between 0 and 10, inclusive of the zero at the front and exclusive at the end. +We see this in the resulting print out after the expression. + +Basic Keyboard Input +==================== + +The Python language has a couple of built-in functions to take input from the keyboard as to facilitate the process of writing applications that allow user input. +Namely, *raw_input()*, and *input()* can be used to prompt and accept user input from the command-line. +Not only is this useful for creating command-line applications and scripts, but it also comes in handy for writing small tests into your applications. + +The *raw_input()* function accepts keyboard entry and converts it to a string, stripping the trailing newline character. +Similarly, the *input()* function accepts keyboard entry as *raw_input()*, but it then evaluates it as an expression. +The *input()* function should be used with caution as it expects a valid Python expression to be entered. +It will raise a *SyntaxError* if this is not the case. +Using *input()* could result in a security concern as it basically allows your user to run arbitrary Python code at will. +It is best to steer clear of using *input()* in most cases and just stick to using raw_input. +Let’s take a look at using each of these functions in some basic examples. + +*Listing 1-38. Using raw_input() and input()* :: + + # The text within the function is optional, and it is used as a prompt to the user + >>> name = raw_input("Enter Your Name:") + Enter Your Name:Josh + >>> print name + Josh + # Use the input function to evaluate an expression entered in by the user + >>> val = input ('Please provide an expression: ') + Please provide an expression: 9 * 3 + >>> val + 27 + # The input function raises an error if an expression is not provided + >>> val = input ('Please provide an expression: ') + Please provide an expression: My Name is Josh + Traceback (most recent call last): + File "", line 1, in + File "", line 1 + My Name is Josh + ^ + SyntaxError: invalid syntax +There will be examples provided later in the book for different ways of using the *raw_input()* function. +Now let’s take a look at some of the other Python statements that have not yet been covered in this chapter. +Other Python Statements +======================= -:: +There are some other Python statements that can be used within applications as well, but they are probably better meant to be discussed within a later chapter as they provide more advanced functionality. +The following is a listing of other Python statements which you will read more about later on: +**exec** - Execute Python code in a dynamic fashion - x = 10 - while x >= 0: - if x == 0: - print "x is now equal to zero!" - break - else: - if x % 2 == 0: - print x - x = x – 1 +**global** — References a variable a global (Chapter 4) - Results: +**with** - New feature in 2.5 using __future__ - 10 - 8 - 6 - 4 - 2 - x is now equal to zero! +**class** - Create or define a new class object (Chapter 6) +**yield** — Used with generators, returns a value (Chapter 4) Documenting Code ================ -Code documentation, an annoyingly important part of every application developer’s life. Although many of us despise code documentation, it must exist for any application that is going to be used for production purposes. Not only is proper code documentation a must for manageability and long-term understanding of Python code fragments, but it also plays an important role in debugging some code as we will see in some examples below. - +Code documentation: an annoyingly important part of every application developer’s life. +Although many of us despise code documentation, it must exist for any application that is going to be used for production purposes. +Not only is proper code documentation a must for manageability and long-term understanding of Python code fragments, but it also plays an important role in debugging some code as we will see in some examples below. +Sometimes we wish to document an entire function or class, and other times we wish to document only a line or two. +Whatever the case, Python provides a way to do it in a rather unobtrusive manner. +Much like many of the other programming languages that exist today, we can begin a comment on any part of any code line. +We can also comment spanning multiple lines if we wish. +Just on a personal note, we rather like the Python documentation symbol (#) or hash, as it provides for clear-cut readability. +There are not many places in code that you will use the (#) symbol unless you are trying to perform some documentation. +Many other languages use symbols such as (/) which can make code harder to read as those symbols are evident in many other non-documenting pieces of code. +Okay, it is time to get off my soap box on Python and get down to business. -Sometimes we wish to document an entire function or class, and other times we wish to document only a line or two. Whatever the case, Python provides a way to do it in a rather unobtrusive manner. Much like many of the other programming languages that exist today, we can begin a comment on any part of any code line. We can also comment spanning multiple lines if we wish. Just on a personal note, I rather like the Python documentation symbol (#) or hash, as it provides for clear-cut readability. There are not many places in code that you will use the (#) symbol unless you are trying to perform some documentation. Many other languages use symbols such as (/) which can make code harder to read as those symbols are evident in many other non-documenting pieces of code. Okay, it is time to get off my soap box on Python and get down to business. +In order to document a line of code, you simply start the document or comment with a (#) symbol. +This symbol can be placed anywhere on the line and whatever follows it is ignored by the Python compiler and treated as a comment or documentation. +Whatever precedes the symbol will be parsed as expected. -In order to document a line of code, you simply start the document or comment with a (#) symbol. This symbol can be placed anywhere on the line and whatever follows it is ignored by the Python compiler and treated as a comment or documentation. Whatever precedes the symbol will be parsed as expected. -:: +*Listing 1-39.* :: - - >>> # This is a line of documentation - >>> x = 0 # This is also documentation - >>> y = 20 - >>> print x + y - 20 + >>> # This is a line of documentation + >>> x = 0 # This is also documentation + >>> y = 20 + >>> print x + y + 20 As you can see, the Python parser ignores everything after the #, so we can easily document or comment as needed. - - One can easily document multiple lines of code using the # symbol as well by placing the hash at the start of each line. -It nicely marks a particular block as documentation. However, Python also provides a multi-line comment using the triple-quote (`'''`) -designation at the beginning and end of a comment. This type of multi-line comment is also referred to as a doc string and it is only -to be used at the start of a module, class, or function. Let’s take a look at these two instances of multi-line documentation in the examples that follow. :: - - - # This function is used in order to provide the square - # of any value which is passed in. The result will be - # passed back to the calling code. - def square_val(value): - return value * value - ... - >>> print square_val(3) - 9 - - - def tip_calc(value, pct): - ''' This function is used as a tip calculator based on a percentage - which is passed in as well as the value of the total amount. In - this function, the first parameter is to be the total amount of a - bill for which we will calculate the tip based upon the second - parameter as a percentage ''' - return value * (pct * .01) - ... - >>> print tip_calc(75,15) - 11.25 - - -Okay, as we can see, both of the documentation methods above can be used to get the task of documenting or comment code done. -In the first example, we used multiple lines of documentation beginning with the # symbol in order to document the *square_val* function. -In the second example, we use the triple-quote method in order to span multiple lines of documentation. Both of them appear to work as -defined...however, the second option provides a greater purpose as it allows one to document specific named code blocks and retrieve that -documentation by calling the __doc__ function on that block. For instance, if we wish to find out what the *square_val* code does, we need -to visit the code and either read the multi-line comment or simply parse the code. However, if we wish to find out what the tip_calc function -does, we can call the tip_calc.__doc__ function and the multi-line comment will be returned to us. This provides a great tool to use for -finding out what code does without actually visiting the code itself. :: - - - >>> print tip_calc.__doc__ - This function is used as a tip calculator based on a percentage - which is passed in as well as the value of the total amount. In - this function, the first parameter is to be the total amount of a - bill for which we will calculate the tip based upon the second - parameter as a percentage +It nicely marks a particular block as documentation. +However, Python also provides a multi-line comment using the triple-quote (‘‘‘) designation at the beginning and end of a comment. +This type of multi-line comment is also referred to as a doc string and it is only to be used at the start of a module, class, or function. +While string literals can be placed elsewhere in code, they will not be treated as docstrings unless used at the start of the code. +Let’s take a look at these two instances of multi-line documentation in the examples that follow. + +*Listing 1-40. Multiple Lines of Documentation Beginning With #* :: + + # This function is used in order to provide the square + # of any value which is passed in. The result will be + # passed back to the calling code. + def square_val(value): + return value * value + ... + >>> print square_val(3) + 9 + +*Listing 1-41. Multiple Lines of Documentation **Enclosed in Triple Quotes (''')* :: + + def tip_calc(value, pct): + ''' This function is used as a tip calculator based on a percentage + which is passed in as well as the value of the total amount. In + this function, the first parameter is to be the total amount of a + bill for which we will calculate the tip based upon the second + parameter as a percentage ''' + return value * (pct * .01) + ... + >>> print tip_calc(75,15) + 11.25 + +Okay, as we can see, both of these documentation methods can be used to get the task of documenting or comment code done. +In Listing 1-40, we used multiple lines of documentation beginning with the # symbol in order to document the *square_val* function. +In Listing 1-41, we use the triple-quote method in order to span multiple lines of documentation. +Both of them appear to work as defined. +However, the second option provides a greater purpose as it allows one to document specific named code blocks and retrieve that documentation by calling the *help(function)* function. +For instance, if we wish to find out what the *square_val* code does, we need to visit the code and either read the multi-line comment or simply parse the code. +However, if we wish to find out what the tip_calc function does, we can call the help(tip_calc) function and the multi-line comment will be returned to us. +This provides a great tool to use for finding out what code does without actually visiting the code itself. + +*Listing 1-42. Printing the Documentation for the tip_calc Function* :: + + >>> help(tip_calc) + Help on function tip_calc in module __main__: + + tip_calc(value, pct) + This function is used as a tip calculator based on a percentage + which is passed in as well as the value of the total amount. In + this function, the first parameter is to be the total amount of a + bill for which we will calculate the tip based upon the second + parameter as a percentage These examples and short explanations should give you a pretty good feel for the power of documentation that is provided by the Python language. -As you can see, using the multi-line triple-quote method is very suitable for documenting classes or functions. Commenting with the # symbol -provides a great way to organize comments within source and also for documenting those lines of code which may be “not so easy” to understand. - - +As you can see, using the multi-line triple-quote method is very suitable for documenting classes or functions. +Commenting with the # symbol provides a great way to organize comments within source and also for documenting those lines of code which may be “not so easy” to understand. Python Help =========== -Getting help when using the Jython interpreter is quite easy. Built into the interactive interpreter is an excellent help() -option which provides information on any module, keyword, or topic available to the Python language. While making use of the -help() system, you can either use the interactive help which is invoked within the interpreter by simply typing help(), or you -can obtain help on a specific object by typing help(object). - -Summary -======= - -This chapter has covered lots of basic Python programming material. It should have provided a basic foundation for the fundamentals -of programming in Python. This chapter shall be used to reflect upon while delving deeper into the language throughout the remainder of this book. +Getting help when using the Jython interpreter is quite easy. +Built into the interactive interpreter is an excellent *help()* option which provides information on any module, keyword, or topic available to the Python language. +By calling the *help()* function without passing in the name of a function, the Python help system is invoked. +While making use of the *help()* system, you can either use the interactive help which is invoked within the interpreter by simply typing *help()*, or as we have seen previously you can obtain the docstring for a specific object by typing *help(object)*. +It should be noted that while using the help system in the interactive mode, there is a plethora of information available at your fingertips. +If you would like to see for yourself, simply start the Jython interactive interpreter and type *help()*. +After you are inside the interactive help, you can exit at any time by typing *quit*. +In order to obtain a listing of modules, keywords, or topics you just type either “*modules*,” “*keywords*,” or “*topics*”, and you will be provided with a complete listing. +You will also receive help for using the interactive help system...or maybe this should be referred to as *meta-help*! +Although the Jython interactive help system is great, you may still need further assistance. +There are a large number of books published on the Python language that will be sure to help you out. +Make sure that you are referencing a book that provides you with information for the specific Python release that you are using as each version contains some differences. +As mentioned previously in the chapter, the Jython version number contains is consistent with its CPython counterpart. +Therefore, each feature that is available within CPython 2.5, for instance, should be available within Jython 2.5 and so on. -We began by discussing the declaration of variables and explained the dynamic tendencies of the language. This gives us an understanding -that variables do not have any type declared with them, rather, they are untyped and can be modified into any Python data type. -We then went on to present the reserved words of the language and then discussed the coding structure which must be adhered to when -developing a Python application. After that, we discussed operators, expressions, and statements. We learned that expressions are -generally blocks of code that produce a value, and that statements consist of conditional and declarative reserved words that allow -us to perform different tasks within our applications. Each of the Python statements were discussed and examples were given. Iteration -constructs were then discussed so that we could begin to use our statements and program looping tasks. - +Summary +======= +This chapter has covered lots of basic Python programming material. +It should have provided a basic foundation for the fundamentals of programming in Python. +This chapter shall be used to reflect upon while delving deeper into the language throughout the remainder of this book. + +We began by discussing some of the differences between CPython and Jython. +There are many good reasons to run Python on the JVM, including the availability of great Java libraries and excellent deployment targets. +Once we learned how to install and configure Jython, we dove into the Python language. +We learned about the declaration of variables and explained the dynamic tendencies of the language. +We then went on to present the reserved words of the language and then discussed the coding structure which must be adhered to when developing a Python application. +After that, we discussed operators and expressions. +We learned that expressions are generally pieces of code that are evaluated to produce a value. +We took a brief tour of Python functions as to cover their basic syntax and usage. +Functions are a fundamental part of the language and most Python developers use functions in every program. +A short section introducing classes followed, it is important to know the basics of classes early even though there is much more to learn in Chapter 6. +We took a look at statements and learned that they consist of instructions that allow us to perform different tasks within our applications. +Each of the Python statements were discussed and examples were given. +Iteration constructs were then discussed so that we could begin to use our statements and program looping tasks. + +Following the language overview, we took a brief look at using keyboard input. +This is a feature for many programs, and it is important to know for building basic programs. +We then learned a bit about documentation, it is an important part of any application and Python makes it easy to do. +Not only did we learn how to document lines of code, but also documenting entire modules, functions and classes. +We touched briefly on the Python help() system as it can be a handy feature to use while learning the language. +It can also be useful for advanced programmers who need to look up a topic that they may be a bit rusty on. -Following the language overview, documentation was discussed. It is an important part of any application, and Python makes it easy to do. -Not only did we learn how to document lines of code, but also documenting entire blocks of code. Throughout the rest of the book, you will learn more in-depth and advanced uses of the topics that we’ve discussed in this chapter. You will also learn concepts and techniques that you’ll be able to utilize in your own programs to make them more powerful and easy to maintain. - - - - - - diff --git a/ModulesPackages.rst b/ModulesPackages.rst index 9e3ab8e..c76a262 100644 --- a/ModulesPackages.rst +++ b/ModulesPackages.rst @@ -1,4 +1,4 @@ -Chapter 7: Modules and Packages +Chapter 8: Modules and Packages +++++++++++++++++++++++++++++++ Up until this chapter we have been looking at code at the level of the diff --git a/ObjectOrientedJython.rst b/ObjectOrientedJython.rst index fd15815..09c113c 100644 --- a/ObjectOrientedJython.rst +++ b/ObjectOrientedJython.rst @@ -1,4 +1,4 @@ -Chapter 5: Object Oriented Jython +Chapter 6: Object Oriented Jython ================================== This chapter is going to cover the basics of object oriented diff --git a/OpsExpressPF.rst b/OpsExpressPF.rst index 6e0ef1e..16d7350 100644 --- a/OpsExpressPF.rst +++ b/OpsExpressPF.rst @@ -1,359 +1,1023 @@ -Chapter 3: Operators, Expressions, and Program Flow -+++++++++++++++++++++++++++++++++++++++++++++++++++ +Chapter 3: Operators, Expressions, and Program Flow +++++++++++++++++++++++++++++++++++++++++++++++++++++ -Up until this point, we’ve have not yet covered the different means of writing expressions in Python. The focus of this chapter is to go in depth on each of the ways we can evaluate code, and write meaningful blocks of conditional logic. We’ll cover the details of each operator that can be used in Python expressions. This chapter will also cover some topics that have already been discussed in more meaningful detail. +.. Trick to get around disruptive effect of a literal | in tables +.. |vert| replace:: \| +The focus of this chapter is an in-depth look at each of the ways that we can evaluate code, and write meaningful blocks of conditional logic. +We’ll cover the details of many operators that can be used in Python expressions. +This chapter will also cover some topics that have already been discussed in more meaningful detail such as the looping constructs, and some basic program flow. +We’ll begin by discussing details of expressions. +If you’ll remember from Chapter 1, an expression is a piece of code that evaluates to produce a value. +We have already seen some expressions in use while reading through the previous chapters. +In this chapter, we’ll focus more on the internals of operators used to create expressions, and also different types of expressions that we can use. +This chapter will go into further detail on how we can define blocks of code for looping and conditionals. -We will begin by discussing details of expressions. We have already seen some expressions in use while reading through the previous chapters. Here we will focus more on the internals of operators used to create expressions, and also different types of expressions that we can use. This chapter will go into further detail on how we can define blocks of code for looping and conditionals. +This chapter will also go into detail on how you write and evaluate mathematical expressions, and Boolean expressions. +And last but not least, we'll discuss how you can use augmented assignment operations to combine two or more operations into one. Types of Expressions --------------------- +==================== -An expression in Python is a block of code that produces a result or value. Most often, we think of expressions that are used to perform mathematical operations within our code. However, there are a multitude of expressions used for other purposes as well. In Chapter 2, we covered the details of String manipulation, sequence and dictionary operations, and touched upon working with sets. All of the operations performed on these objects are forms of expressions in Python. - -This chapter will go into detail on how you write and evaluate mathematical expressions, boolean expressions, and augmented assignments. +An expression in Python is a piece of code that produces a result or value. +Most often, we think of expressions that are used to perform mathematical operations within our code. +However, there are a multitude of expressions used for other purposes as well. +In Chapter 2, we covered the details of String manipulation, sequence and dictionary operations, and touched upon working with sets. +All of the operations performed on these objects are forms of expressions in Python. +Other examples of expressions could be pieces of code that call methods or functions, and also working with lists using slicing and indexing. Mathematical Operations ------------------------ - -The Python language of course contains all of your basic mathematical operations. This section will briefly touch upon each operator that is available for use in Python and how they function. You will also learn about a few built-in functions which can be used to assist in your mathematical expressions. Finally, you’ll see how to use conditionals in the Python language and learn order of evaluation. - -Assuming that this is not the first programming language you are learning, there is no doubt that you are at least somewhat familiar with performing mathematical operations within your programs. Python is no different than the rest when it comes to mathematics, as with most programming languages, performing mathematical computations and working with numeric expressions is straightforward. - - - -========== ============================================= -Operator Description -========== ============================================= -'+' Addition -'-' Subtraction -'*' Multiplication -/ Division -// Truncating Division -% Modulo (Remainder of Division) -\*\* Power Operator -+var Unary Plus --var Unary Minus -========== ============================================= - -Table 3-1: Numeric Operators - -Most of the operators in the table above are easily understood. However, the truncating division, modulo, power, and unary operators could use some explanation. Truncating division will automatically truncate a division result into an integer. Modulo will return the remainder of a division operation. The power operator does just what you’d expect as it returns the result of the number to the left of the operator multiplied by itself n times, where n represents the number to the right of the operator. Unary plus and unary minus are used to evaluate positive or negative numbers. The following set of examples will help to clarify these topics. :: - - # Performing basic mathematical computations - - >>> 10 - 6 - 4 - >>> 9 * 7 - 63 - >>> 9 / 3 - 3 - >>> 10 / 3 - 3 - >>> 10 // 3 - 3 - >>> 3.14 / 2 - 1.57 - >>> 3.14 // 2 - 1.0 - >>> 36 / 5 - 7 - >>> 36 % 5 - 1 - >>> 5**2 - 25 - >>> 100**2 - 10000 - >>> -10 + 5 - -5 - >>> +5 - 5 - 0 - -There is a new means of division available in Jython 2.5 by importing from __future__. In a standard division for 2.5 and previous releases, the quotient returned is an integer or the floor of the quotient when arguments are ints or longs. However, a reasonable approximation of the division is returned if the arguments are floats or complex. Often times this solution is incorrect as the quotient should be the reasonable approximation or “true division” in any case. When we import *division* from the __future__ module then we alter the return value of division by causing true division when using the / operator, and floor division when using the // operator. Since this is going to be the standard in future releases, it is best practice to import from __future__ when performing division in Jython 2.5. :: - - >>> from __future__ import division - >>> 9/5 - 1.8 - >>> 9/4 - 2.25 - >>> 9/3 - 3.0 - >>> 9//3 - 3 - >>> 9//5 - 1 - +======================= + +The Python contains all of your basic mathematical operations. +This section will briefly touch upon each operator and how it functions. +You will also learn about a few built-in functions which can be used to assist in your mathematical expressions. + +Assuming that this is not the first programming language you are learning, there is no doubt that you are at least somewhat familiar with performing mathematical operations within your programs. +Python is no different than the rest when it comes to mathematics, as with most programming languages, performing mathematical computations and working with numeric expressions is straightforward. +Table 3-1 lists the numeric operators. + +*Table 3-1. Numeric Operators* + ++----------+--------------------------------+ +| Operator | Description | ++==========+================================+ +| \+ | Addition | ++----------+--------------------------------+ +| \- | Subtraction | ++----------+--------------------------------+ +| \* | Multiplication | ++----------+--------------------------------+ +| / | Division | ++----------+--------------------------------+ +| // | Truncating Division | ++----------+--------------------------------+ +| % | Modulo (Remainder of Division) | ++----------+--------------------------------+ +| \*\* | Power Operator | ++----------+--------------------------------+ +| +var | Unary Plus | ++----------+--------------------------------+ +| -var | Unary Minus | ++----------+--------------------------------+ + + +Most of the operators in Table 3-1 work exactly as you would expect, so for example: + +*Listing 3-1. Mathematical Operator*:: + + # Performing basic mathematical computations + >>> 10 - 6 + 4 + >>> 9 * 7 + 63 + +However, division, truncating division, modulo, power, and the unary operators could use some explanation. +Truncating division will automatically truncate a division result into an integer by rounding down, and modulo will return the remainder of a truncated division operation. +The power operator does just what you’d expect as it returns the result of the number to the left of the operator multiplied by itself n times, where n represents the number to the right of the operator. + +*Listing 3-2. Truncating Division and Powers*:: + + >>> 36 // 5 + 7 + # Modulo returns the remainder + >>> 36 % 5 + 1 + # Using powers, in this case 5 to the power of 2 + >>> 5**2 + 25 + # 100 to the power of 2 + >>> 100**2 + 10000 + +Division itself is an interesting subject as its current implementation is somewhat controversial in some situations. +The problem 10/5 = 2 definitely holds true. +However, in its current implementation, division rounds numbers in such a way that sometimes yields unexpected results. +There is a new means of division available in Jython 2.5 by importing from __future__. In a standard division for 2.5 and previous releases, the quotient returned is the floor (nearest integer after rounding down) of the quotient when arguments are ints or longs. +However, a reasonable approximation of the division is returned if the arguments are floats or complex. +Often times this solution is not what was expected as the quotient should be the reasonable approximation or “true division” in any case. +When we import division from the __future__ module then we alter the return value of division by causing true division when using the / +operator, and floor division only when using the , // operator. +In an effort to not break backward compatibility, the developers have placed the repaired division implementation in a module known as __future__. The  __future__ module actually contains code that is meant to be included as a part of the standard language in some future revision. +In order to use the new repaired version of division, it is important that you always import from __future__ prior to working with division. +Take a look at the following piece of code. + +*Listing 3-3. Division Rounding Issues*:: + + # Works as expected + >>> 14/2 + 7 + >>> 10/5 + 2 + >>> 27/3 + 9 + # Now divide some numbers that should result in decimals + # Here we would expect 1.5 + >>> 3/2 + 1 + # The following should give us 1.4 + >>> 7/5 + 1 + # In the following case, we'd expect 2.3333 + >>> 14/6 + 2 + +As you can see, when we’d expect to see a decimal value we are actually receiving an integer value. +The developers of this original division implementation have acknowledged this issue and repaired it using the new +__future__ implementation. + +*Listing 3-4. Working With __future__ Division*:: + + # We first import division from __future__ + from __future__ import division + # We then work with division as usual and see the expected results + >>> 14/2 + 7.0 + >>> 10/5 + 2.0 + >>> 27/3 + 9.0 + >>> 3/2 + 1.5 + >>> 7/5 + 1.4 + >>> 14/6 + 2.3333333333333335 + +It is important to note that the Jython implementation differs somewhat from CPython in that Java provides extra rounding in some cases. +The differences are in display of the rounding only as both Jython and CPython use the same IEEE float for storage. +Let’s take a look at one such case. + +*Listing 3-5. Subtle Differences Between Jython and CPython Division*:: + + # CPython 2.5 Rounding + >>> 5.1/1 + 5.0999999999999996 + # Jython 2.5 + >>> 5.1/1 + 5.1 + +Unary operators can be used to evaluate positive or negative numbers. +The unary plus operator multiplies a number by positive 1 (which generally doesn’t change it at all), and a unary minus operator multiplies a number by negative 1. + +*Listing 3-6. Unary Operators*:: + + # Unary minus + >>> -10 + 5 + -5 + >>> +5 - 5 + 0 + >>> -(1 + 2) + -3 As stated at the beginning of the section, there are a number of built-in mathematical functions that are at your disposal. - -================= =============================================================================== -Function Description -================= =============================================================================== -abs(var) Absolute value -pow(x, y) Used in place of power operator -pow(x,y,modulo) Ternary power-modulo -round(var[, n]) Returns a value rounded to the nearest 10-n -divmod(x, y) Returns both the quotient and remainder of division operation -================= =============================================================================== - -Table 3-2: Mathematical Built-in functions :: - - # The following code provides some examples for using mathematical built-ins - >>> abs(9) - 9 - >>> abs(-9) - 9 - >>> divmod(8,4) - (2, 0) - >>> pow(8,2) - 64 - >>> pow(8,2,3) - 1 - >>> round(5.67,1) - 5.7 - >>> round(5.67) - 6.0 - - - -The bitwise and logical operators as well as the conditional operators can be used to combine and compare logic. As with the mathematical operators described above, these operators have no significant difference to that of Java. - - - -========== ==================================== -Operator Description -========== ==================================== -> Greater than -< Less than ->= Greater than or equal -<= Less than or equal -!= Not equal -== Equal -& Bitwise and -| Bitwise or -^ Bitwise xor -~ Bitwise negation -<< Shift left ->> Shift right -========== ==================================== - -Table 3-3: Bitwise and Conditional Operators - - - -Augmented assignment operators are those that combine two or more operations into one. While augmented assignment can assist in coding concisely, some say that too many such operators can make code more difficult to read. - - - -========== =================================== -Operator Description and Logic -========== =================================== -+= a = a + b --= a = a – b -\*= a = a * b -/= a = a / b -%= a = a % b -//= a = a // b -\*\*= a = a \*\* b -&= a = a & b -\|= a = a \| b -^= a = a ^ b ->>= a = a >> b -<<= a = a << b -========== =================================== - -Table 3-4: Augmented Assignment Operators - +Table 3-2 lists the built-in mathematical functions. + +*Table 3-2. Mathematical Built-in Functions* + ++-----------------+---------------------------------------------------------------+ +| Function | Description | ++=================+===============================================================+ +| abs(var) | Absolute value | ++-----------------+---------------------------------------------------------------+ +| pow(x, y) | Can be used in place of ** operator | ++-----------------+---------------------------------------------------------------+ +| pow(x,y,modulo) | Ternary power-modulo (x*\*y) % modulo | ++-----------------+---------------------------------------------------------------+ +| round(var[, n]) | Returns a value rounded to the nearest 10-n or (10**-n), | +| | where n defaults to 0) | ++-----------------+---------------------------------------------------------------+ +| divmod(x, y) | Returns a tuple of the quotient and the remainder of division | ++-----------------+---------------------------------------------------------------+ + + +*Listing 3-7. Mathematical Built-ins*:: + + #  The following code provides some examples for using mathematical built-ins + # Absolute value of 9 + >>> abs(9) + 9 + # Absolute value of -9 + >>> abs(-9) + 9 + # Divide 8 by 4 and return quotient, remainder tuple + >>> divmod(8,4) + (2, 0) + # Do the same, but this time returning a remainder (modulo) + >>> divmod(8,3) + (2, 2) + # Obtain 8 to the power of 2 + >>> pow(8,2) + 64 + # Obtain 8 to the power of 2 modulo 3  ((8 **2) % 3) + >>> pow(8,2,3) + 1 + # Perform rounding + >>> round(5.67,1) + 5.7 + >>> round(5.67) + 6.00 + +Comparison Operators +==================== + +Comparison operators can be used for comparison of two or more expressions or variables. +As with the mathematical operators described above, these operators have no significant difference to that of Java. +See Table 3-3. + +*Table 3-3. Comparison Operators* + ++----------+-----------------------+ +| Operator | Description | ++==========+=======================+ +| > | Greater than | ++----------+-----------------------+ +| < | Less than | ++----------+-----------------------+ +| >= | Greater than or equal | ++----------+-----------------------+ +| <= | Less than or equal | ++----------+-----------------------+ +| != | Not equal | ++----------+-----------------------+ +| == | Equal | ++----------+-----------------------+ + + +*Listing 3-8. Examples of Comparison Operators*:: + + # Simple comparisons + >>> 8 > 10 + False + >>> 256 < 725 + True + >>> 10 == 10 + True + # Use comparisons in an expression + >>> x = 2*8 + >>> y = 2 + >>> while x != y: + ...     print 'Doing some work...' + ...     y = y + 2 + ... + Doing some work... + Doing some work... + Doing some work... + Doing some work... + Doing some work... + Doing some work... + Doing some work... + # Combining comparisons + >>> 3<2<3 + False + >>> 3<4<8 + True + +Bitwise Operators +================= + +Bitwise operators in Python are a set of operators that are used to work on numbers in a two’s complement binary fashion. +That is, when working with bitwise operators numbers are treated as a string of bits consisting of 0s and 1s. +If you are unfamiliar with the concept of two's complement, a good place to start would be at the Wikipedia page discussing the topic: (http://en.wikipedia.org/wiki/Two's_complement). It is important to know that bitwise operators can only be applied to integers and long integers. +Let’s take a look at the different bitwise operators that are available to us (Table 3-4), and then we’ll go through a few examples. + +*Table 3-4. Bitwise Operators* + ++----------+----------------------------------------------------------------------+ +| Operator | Description | ++==========+======================================================================+ +| & | Bitwise and operator copies a bit to the result if a bit appears in | +| | both operands | ++----------+----------------------------------------------------------------------+ +| |vert| | Bitwise or operator copies a bit to the result if it exists in | +| | either of the operands | ++----------+----------------------------------------------------------------------+ +| ^ | Bitwise xor operator copies a bit to the result if it exists in only | +| | one operand | ++----------+----------------------------------------------------------------------+ +| ~ | Bitwise negation operator flips the bits, and returns the exact | +| | opposite of each bit | ++----------+----------------------------------------------------------------------+ + + +Suppose we have a couple of numbers in binary format and we would like to work with them using the bitwise operators. +Let’s work with the numbers 14 and 27. +The binary (two's complement) representation of the number 14 is 00001110, and for 27 it is 00011011. +The bitwise operators look at each 1 and 0 in the binary format of the number and perform their respective operations, and then return a result. +Python does not return the bits, but rather the integer value of the resulting bits. +In the following examples, we take the numbers 14 and 27 and work with them using the bitwise operators. + +*Listing 3-9. Bitwise Operator Examples*:: + + >>> 14 & 27 + 10 + >>> 14 | 27 + 31 + >>> 14 ^ 27 + 21 + >>> ~14 + -15 + >>> ~27 + -28 + +To summarize the examples above, let’s work through the operations using the binary representations for each of the numbers.:: + + 14 & 27 = 00001110 and 00011011 = 00001010 (The integer 10) + 14 | 27 = 00001110 or 000110011 = 00011111 (The integer 31) + 14 ^ 27 = 00001110 xor 000110011 = 00010101 (The integer 21) + ~14 = 00001110 = 11110001 (The integer -15) + +The shift operators (see Table 3-5) are similar in that they work with the binary bit representation of a number. +The left shift operator moves the left operand’s value to the left by the number of bits specified by the right operand. +The right shift operator does the exact opposite as it shifts the left operand's value to the right by the number of bits specified by the right operand. +Essentially this translates to the left shift operator multiplying the operand on the left by the number two as many times as specified by the right operand. +The opposite holds true for the right shift operator that divides the operand on the left by the number two as many times as specified by the right operand. + +*Table 3-5. Shift Operators* + ++----------+-----------------------------------------------------------------------+ +| Operator | Description | ++==========+=======================================================================+ +| x << n | Shift left (The equivalent of multiplying the number x by 2, n times) | ++----------+-----------------------------------------------------------------------+ +| x >> n | Shift right (The equivalent of dividing the number x by 2, n times) | ++----------+-----------------------------------------------------------------------+ + + +More specifically, the left shift operator (<<) will multiply a number by two n times, n being the number that is to the right of the shift operator. +The right shift operator will divide a number by two n times, n being the number to the right of the shift operator. +The __future__division import does not make a difference in the outcome of such operations. + +*Listing 3-10. Shift Operator Examples*:: + + # Shift left, in this case  3*2 + >>> 3<<1 + 6 + # Equivalent of 3*2*2 + >>> 3<<2 + 12 + # Equivalent of 3*2*2*2*2*2 + >>> 3<<5 + 96 + # Shift right + # Equivalent of 3/2 + >>> 3>>1 + 1 + # Equivalent of 9/2 + >>> 9>>1 + 4 + # Equivalent of 10/2 + >>> 10>>1 + 5 + # Equivalent of 10/2/2 + >>> 10>>2 + 2 + +While bitwise operators are not the most commonly used operators, they are good to have on hand. +They are especially important if you are working in mathematical situations. + +Augmented Assignment +==================== + +Augmented assignment operators (see Table 3-6) combine an operation with an assignment. +They can be used to do things like assign a variable to the value it previously held, modified in some way. +While augmented assignment can assist in coding concisely, some say that too many such operators can make code more difficult to read. + +*Listing 3-11. Augmented Assignment Code Examples*:: + + >>> x = 5 + >>> x + 5 + # Add one to the value of x and then assign that value to x + >>> x+=1 + >>> x + 6 + # Multiply the value of x by 5 and then assign that value to x + >>> x*=5 + >>> x + 30 + +*Table 3-6. Augmented Assignment Operators* + ++---------------+----------------+ +| Operator | Equivalent | ++===============+================+ +| a += b | a = a + b | ++---------------+----------------+ +| a -= b | a = a – b | ++---------------+----------------+ +| a \*= b | a = a \* b | ++---------------+----------------+ +| a /= b | a = a / b | ++---------------+----------------+ +| a %= b | a = a % b | ++---------------+----------------+ +| a //= b | a = a // b | ++---------------+----------------+ +| a \*\*=  b | a = a \*\* b | ++---------------+----------------+ +| a &= b | a = a & b | ++---------------+----------------+ +| a |vert|\ = b | a = a |vert| b | ++---------------+----------------+ +| a ^= b | a = a ^ b | ++---------------+----------------+ +| a >>= b | a = a >> b | ++---------------+----------------+ +| a <<= b | a = a << b | ++---------------+----------------+ Boolean Expressions -------------------- - -Comparing two or more values or expressions also uses a similar syntax to that of other languages, and the logic is quite the same. Note that in Python, *True* and *False* are very similar to constants in the Java language. *True* actually represents the number *1*, and *False* represents the number *0*. One could just as easily code using 0 and 1 to represent the boolean values, but for readability and maintenance the *True* and *False* “constants” are preferred. Java developers, make sure that you capitalize the first letter of these two words as you will receive an ugly *NameError* if you do not. - - - -============= ======= ================================================================= -Conditional Logic -============= ======= ================================================================= -and In an *x and y* evaluation, both x and y must evaluate to True -or In an *x or y* evaluation, if x is false then y is evaluated. -not In a *not x* evaluation, if *not x*, we mean the opposite of x -============= ======= ================================================================= - -Table 3-5: Boolean Conditionals +=================== + +Evaluating two or more values or expressions also uses a similar syntax to that of other languages, and the logic is quite the same. +Note that in Python, True and False are very similar to constants in the Java language. +True actually represents the number 1, and False represents the number 0. +One could just as easily code using 0 and 1 to represent the Boolean values, but for readability and maintenance the True and False “constants” are preferred. +Java developers, make sure that you capitalize the first letter of these two words as you will receive an ugly NameError if you do not. + +Boolean properties are not limited to working with int and bool values, but they also work with other values and objects. +For instance, simply passing any non-empty object into a Boolean expression will evaluate to True in a Boolean context. +This is a good way to determine whether a string contains anything. +See Table 3-7. + +*Listing 3-12. Testing a String*:: + + >>> mystr = '' + >>> if mystr: + ...     'Now I contain the following: %s' % (mystr) + ... else: + ...     'I do not contain anything' + ... + 'I do not contain anything' + >>> mystr = 'Now I have a value' + >>> if mystr: + ...     'Now I contain the following: %s' % (mystr) + ... else: + ...     'I do not contain anything' + ... + 'Now I contain the following: Now I have a value' + +*Table 3-7. Boolean Conditionals* + ++-------------+-------------------------------------------------------------------+ +| Conditional | Logic | ++=============+===================================================================+ +| and | In an x and y evaluation, if x evaluates to false then its value | +| | is returned, otherwise y is evaluated and the resulting value is | +| | returned | ++-------------+-------------------------------------------------------------------+ +| or | In an x or y evaluation, if x evaluates to true then its value is | +| | returned, otherwise y is evaluated and the resulting value is | +| | returned | ++-------------+-------------------------------------------------------------------+ +| not | In a not x evaluation, if not x, we mean the opposite of x | ++-------------+-------------------------------------------------------------------+ + + +As with all programming languages, there is an order of operations for deciding what operators are evaluated first. +For instance, if we have an expression a + b \*c, then which operation would take place first? +The order of operations for Python is shown in Table 3-8 with those operators that receive the highest precedence shown first, and those with the lowest shown last. +Repeats of the same operator are grouped from left to the right with the exception of the power (**) operator. + +*Table 3-8. Python Operator Precedence from Highest to Lowest* + ++---------------------------------+---------------------------------+ +| Operator | Name | ++=================================+=================================+ +| +var, -var, ~var | Unary Operations | ++---------------------------------+---------------------------------+ +| \*\* | Power Operations | ++---------------------------------+---------------------------------+ +| \*, /, //, % | Multiplication, Division, Floor | +| | Division, Modulo | ++---------------------------------+---------------------------------+ +| +, - | Addition, Subtraction | ++---------------------------------+---------------------------------+ +| <<, >> | Left and Right Shift | ++---------------------------------+---------------------------------+ +| & | Bitwise And | ++---------------------------------+---------------------------------+ +| ^ | Bitwise Exclusive Or | ++---------------------------------+---------------------------------+ +| |vert| | Bitwise Or | ++---------------------------------+---------------------------------+ +| <, >, <=. >= , <> | Comparison Operators | ++---------------------------------+---------------------------------+ +| ==, != , is, is not, in, not in | Equality and Membership | ++---------------------------------+---------------------------------+ +| and, or, not | Boolean Conditionals | ++---------------------------------+---------------------------------+ + + +An important note is that when working with Boolean conditionals, 'and' and +'or' group from the left to the right. +Let’s take a look at a few examples. + +*Listing 3-13. Order of Operations Examples*:: + + # Define a few variables + >>> x = 10 + >>> y = 12 + >>> z = 14 + # (y*z) is evaluated first, then x is added + >>> x + y * z + 178 + # (x * y) is evaluated first, then z is subtracted from the result + >>> x * y - z + 106 + # When chaining comparisons, a logical 'and' is implied.  In this + # case, x < y and y <= z and z > x + >>> x < y <= z > x + True + #  (2 * 0) is evaluated first and since it is False or zero, it is returned + >>> 2 * 0 and 5 + 1 + 0 + # (2 * 1) is evaluated first, and since it is True or not zero, the (5 + 1) is evaluated and + # returned + >>> 2 * 1 and 5 + 1 + 6 + # x is returned if it is True, otherwise y is returned if it is False.  If neither + # of those two conditions occur, then z is returned. + >>> x or (y and z) + 10 + # In this example, the (7 – 2) is evaluated and returned because of the 'and' 'or' + # logic + >>> 2 * 0 or ((6 + 8) and (7 - 2)) + 5 + # In this case, the power operation is evaluated first, and then the addition + >>> 2 ** 2 + 8 + 12 Conversions ------------ - - - -There are a number of conversion functions built into the language in order to help conversion of one data type to another. While every data type in Jython is actually a class object, these conversion functions will really convert one class type into another. For the most part, the built-in conversion functions are easy to remember because they are primarily named after the type to which you are trying to convert. - -======================= ======================================================================================================= -Function Description -======================= ======================================================================================================= -chr(value) Converts integer to a character -complex(real [,imag]) Produces a complex number -dict(sequence) Produces a dictionary from a given sequence of (key,value) tuples -eval(string) Evaluates a string to return an object…useful for mathematical computations -float(value) Converts to float -frozenset(set) Converts a set into a frozen set -hex(value) Converts an integer into a hex string -int(value [, base]) Converts to an integer using a base if a string is given -list(sequence) Converts a given sequence into a list -long(value [, base]) Converts to a long using a base if a string is given -oct(value) Converts integer to octal -ord(value) Converts a character into it’s integer value -repr(value) Converts object into an expression string. Same as enclosing expression in reverse quotes ( `x + y`) -set(sequence) Converts a sequence into a set -str(value) Converts an object into a string -tuple(sequence) Converts a given sequence to a tuple -unichr(value) Converts integer to a Unicode character -======================= ======================================================================================================= - -Table 3-6: Conversion Functions - -The following is an example of using the *eval()* functionality as it is perhaps the one conversion function for which an example helps to understand. :: - - # Suppose keyboard input contains an expression in string format (x * y) - >>> x = 5 - >>> y = 12 - >>> keyboardInput = 'x * y' - >>> eval(keyboardInput) - 60 - -Program Flow ------------- - -The Python programming language has structure that sets it apart from the others. As you’ve learned in previous references in this book, the statements that make up programs in Python are structured with attention to spacing, order, and technique. In order to develop a statement in Python, you must adhere to proper spacing techniques throughout the code block. Convention and good practice adhere to four spaces of indentation per statement throughout the entire program. Follow this convention along with some control flow and you’re sure to develop some easily maintainable software. - -The standard Python if-else conditional statement is used in order to evaluate expressions and branch program logic based upon the outcome. Expressions that are usable in an if-else statement can consist of any operators we’ve discussed previously. The objective is to write and compare expressions in order to evaluate to a *True* or *False* outcome. As shown in Chapter 1, the logic for an *if-else* statement follows one path if an expression evaluates to *True*, or a different path if it evaluates to *False.* - -You can chain as many *if-else* expressions together as needed. The combining *if-else* keyword is *elif*, which is used for every expression in between the first and the last expressions within a conditional statement. :: - - # terminal symbols are left out of this example so that you can see the concise indentation - pi =3.14 - x = 2.7 * 1.45 - if x == pi: - print ‘The number is pi’ - elif x > pi: - print ‘The number is greater than pi’ - else: - print ‘The number is less than pi’ - -Another construct that we touched upon in Chapter 1 was the loop. Every programming language provides looping implementations, and Python is no different. The Python language provides two main types of loops known as the *while* and the *for* loop. The *while* loop logic follows the same semantics as the *while* loop in Java. The loop will continue processing until the expression evaluates to *False*. At this time the looping ends and that would be it for the Java implementation. However, in Python the *while * loop construct also contains an *else* clause which is executed when the looping completes. :: - - while True: - # perform some processing - else: - print ‘Processing Complete…’ - -This *else* clause can come in handy while performing intensive processing so that we can inform the user of the completion of such tasks. It can also be handy when debugging code. Also mentioned in Chapter 1 were the *break*, and *continue* statements. These all come in handy when using any looping construct. The *break* statement can be used to break out of a loop. It should be noted that if there are nested loops then the *break* statement will break out of the inner-most loop only, the outer loops will continue to process. The *continue* statement can be used to break out of the current processing statement and continue the loop from the beginning. The *continue* can be thought of as a skipping statement as it will cause execution to skip all remaining statements in the block and restart from the beginning (if the loop expression still evaluates to *True* of course). :: - - while x != y: - # perform some processing - if x < 0: - break - else: - print ‘The program executed to completion’ - -In the example above, the program will continue to process until x does not equal y. However, if at any point during the processing the x variable evaluates less than zero, then the execution stops. The *else* clause will not be executed if the *break* statement is invoked. It will only be executed under normal termination of the loop. - - - -The *for* loop can be used on any iterable object. It will simply iterate through the object and perform some processing during each pass. Both the *break* and *continue* statements can also be used within the *for* loop. The *for* statement in Python also differs from the same statement in Java because in Python we also have the *else* clause with this construct. Once again, the *else* clause is executed when the *for* loop processes to completion without any *break* intervention. Also, if you are familiar with pre-Java 5 *for* loops then you will love the Python syntax. In Java 5, the syntax of the *for* statement was adjusted a bit to make it more in line with syntactically easy languages such as Python. :: - - for(x = 0; x <= myList.size(); x++){ - // processing statements iterating through myList - System.out.println(“The current index is: “ + x); - } - - x = 0 - for value in myList: - # processing statements using value as the current item in myList - print ‘The current index is %i’ % (x) - x = x + 1 - -As you can see, the Python syntax is a little easier to understand, but it doesn’t really save too many keystrokes at this point. We still have to manage the index (x in this case) by ourselves by incrementing it with each iteration of the loop. However, Python does provide a built-in function that can save us some keystrokes and provides a similar functionality to that of Java with the automatically incrementing index on the *for* loop. The *enumerate(sequence)* function does just that. It will provide an index for our use and automatically manage it for us. :: - - >>> myList = ['jython','java','python','jruby','groovy'] - >>> for index, value in enumerate(myList): - ... print index, value - ... - 0 jython - 1 java - 2 python - 3 jruby - 4 groovy - - -Now we have covered the program flow for conditionals and looping constructs in the Python language. Note that you can next to any level, and provide as many *if-else* conditionals as you’d like. However, good programming practice will tell you to keep it as simple as possible or the logic will become too hard to follow. +=========== + +There are a number of conversion functions built into the language in order to help conversion of one data type to another (see Table 3-9). While every data type in Jython is actually a class object, these conversion functions will really convert one class type into another. +For the most part, the built-in conversion functions are easy to remember because they are primarily named after the type to which you are trying to convert. + +*Table 3-9. Conversion Functions* + ++-----------------+----------------------------------------------------------------+ +| Function | Description | ++=================+================================================================+ +| chr(value) | Converts integer to a character | ++-----------------+----------------------------------------------------------------+ +| complex(real | Produces a complex number | +| [,imag]) | | ++-----------------+----------------------------------------------------------------+ +| dict(sequence) | Produces a dictionary from a given sequence of (key, value) | +| | tuples | ++-----------------+----------------------------------------------------------------+ +| eval(string) | Evaluates a string to return an object…useful for mathematical | +| | computations. Note: This function should be used with extreme | +| | caution as it can pose a security hazard if not used properly. | ++-----------------+----------------------------------------------------------------+ +| float(value) | Converts number to float | ++-----------------+----------------------------------------------------------------+ +| frozenset(set) | Converts a set into a frozen set | ++-----------------+----------------------------------------------------------------+ +| hex(value) | Converts an integer into a string representing that number | +| | in hex | ++-----------------+----------------------------------------------------------------+ +| int(value [, | Converts to an integer using a base if a string is given | +| base]) | | ++-----------------+----------------------------------------------------------------+ +| list(sequence) | Converts a given sequence into a list | ++-----------------+----------------------------------------------------------------+ +| long(value [, | Converts to a long using a base if a string is given | +| base]) | | ++-----------------+----------------------------------------------------------------+ +| oct(value) | Converts  an integer to a string representing that number as | +| | an octal | ++-----------------+----------------------------------------------------------------+ +| ord(value) | Converts a character into its integer value | ++-----------------+----------------------------------------------------------------+ +| repr(value) | Converts object into an expression string. Same as enclosing | +| | expression in reverse quotes ( `x + y`).  Returns a string | +| | containing a printable and evaluable representation of the | +| | object | ++-----------------+----------------------------------------------------------------+ +| set(sequence) | Converts a sequence into a set | ++-----------------+----------------------------------------------------------------+ +| str(value) | Converts an object into a string  Returns a string | +| | containing a printable representation of the value, but not | +| | an evaluable string | ++-----------------+----------------------------------------------------------------+ +| tuple(sequence) | Converts a given sequence to a tuple | ++-----------------+----------------------------------------------------------------+ +| unichr(value) | Converts integer to a Unicode character | ++-----------------+----------------------------------------------------------------+ + + +*Listing 3-14. Conversion Function Examples*:: + + # Return the character representation of the integers + >>> chr(4) + '\x04' + >>> chr(10) + '\n' + # Convert intger to float + >>> float(8) + 8.0 + # Convert character to its integer value + >>> ord('A') + 65 + >>> ord('C') + 67 + >>> ord('z') + 122 + # Use repr() with any object + >>> repr(3.14) + '3.14' + >>> x = 40 * 5 + >>> y = 2**8 + >>> repr((x, y, ('one','two','three'))) + "(200, 256, ('one', 'two', 'three'))" + +The following is an example of using the eval() functionality as it is perhaps the one conversion function for which an example helps to understand. +Again, please note that using the eval() function can be dangerous and impose a security threat if used incorrectly. +If using the eval() function to accept text from a user, standard security precautions should be set into place to ensure that the string being evaluated is not going to compromise security. + +*Listing 3-15. Example of eval()*:: + + # Suppose keyboard input contains an expression in string format (x * y) + >>> x = 5 + >>> y = 12 + >>> keyboardInput = 'x * y' + # We should provide some security checks on the keyboard input here to + # ensure that the string is safe for evaluation. Such a task is out of scope + # for this chapter, but it is good to note that comparisons on the keyboard + # input to check for possibly dangerous code should be performed prior to + # evaluation. + >>> eval(keyboardInput) + 60 + +Using Expressions to Control Program Flow +========================================= + +As you’ve learned in previous references in this book, the statements that make up programs in Python are structured with attention to spacing, order, and technique. +Each section of code must be consistently spaced as to set each control structure apart from others. +One of the great advantages to Python’s syntax is that the consistent spacing allows for delimiters such as the curly braces {} to go away. +For instance, in Java one must use curly braces around a for loop to signify a start and an end point. +Simply spacing a for loop in Python correctly takes place of the braces. +Convention and good practice adhere to using four spaces of indentation per statement throughout the entire program. +For more information on convention, please see PEP 8, Style Guide for Python Code (www.python.org/dev/peps/pep-0008/). +Follow this convention along with some control flow and you’re sure to develop some easily maintainable software. + +if-elif-else Statement +---------------------- + +The standard Python if-elif-else conditional statement is used in order to evaluate expressions and branch program logic based upon the outcome. +An if-elif-else statement can consist of any expressions we’ve discussed previously. +The objective is to write and compare expressions in order to evaluate to a True or False outcome. +As shown in Chapter 1, the logic for an if-elif-else statement follows one path if an expression evaluates to True, or a different path if it evaluates to False. + +You can chain as many if-else expressions together as needed. +The combining if-else keyword is elif, which is used for every expression in between the first and the last expressions within a conditional statement. + +The elif portion of the statement helps to ensure better readability of program logic. +Too many if statements nested within each other can lead to programs that are difficult to maintain. +The initial if expression is evaluated, and if it evaluates to False, the next elif expression is evaluated, and if it evaluates to False then the process continues. +If any of the if or elif expressions evaluate to True then the statements within that portion of the if statement are processed. +Eventually if all of the expressions evaluate to False then the final else expression is evaluated. + +These next examples show a few ways for making use of a standard if-elif­-else statement. +Note that any expression can be evaluated in an if-elif-else construct. +These are only some simplistic examples, but the logic inside the expressions could become as complex as needed. + +*Listing 3-16. Standard if-elif-else*:: + + # terminal symbols are left out of this example so that you can see the precise indentation + pi =3.14 + x = 2.7 * 1.45 + if x == pi: + print 'The number is pi' + elif x > pi: + print 'The number is greater than pi' + else: + print 'The number is less than pi' + +Empty lists or strings will evaluate to False as well, making it easy to use them for comparison purposes in an if-elif-else statement. + +*Listing 3-17. Evaluate Empty List*:: + + # Use an if-statement to determine whether a list is empty + # Suppose mylist is going to be a list of names + >>> mylist = [] + >>> if mylist: + ...     for person in mylist: + ...         print person + ... else: + ...     print 'The list is empty' + ... + The list is empty + +while Loop +---------- + +Another construct that we touched upon in Chapter 1 was the loop. +Every programming language provides looping implementations, and Python is no different. +To recap, the Python language provides two main types of loops known as the while and the for loop. + +The while loop logic follows the same semantics as the while loop in Java. +The while loop evaluates a given expression and continues to loop through its statements until the results of the expression no longer hold true and evaluate to False. +Most while loops contain a comparison expression such as x <= y or the like, in this case the expression would evaluate to False when x becomes greater than y. +The loop will continue processing until the expression evaluates to False. +At this time the looping ends and that would be it for the Java implementation. +Python on the other hand allows an else clause which is executed when the loop is completed. + +*Listing 3-18. Python while Statement*:: + + >>> x = 0 + >>> y = 10 + >>> while x <= y: + ...     print 'The current value of x is: %d' % (x) + ...     x += 1 + ... else: + ...     print 'Processing Complete...' + ... + The current value of x is: 0 + The current value of x is: 1 + The current value of x is: 2 + The current value of x is: 3 + The current value of x is: 4 + The current value of x is: 5 + The current value of x is: 6 + The current value of x is: 7 + The current value of x is: 8 + The current value of x is: 9 + The current value of x is: 10 + Processing Complete... + +This else clause can come in handy while performing intensive processing so that we can inform the user of the completion of such tasks. +It can also be handy when debugging code, or when some sort of cleanup is required after the loop completes + +*Listing 3-19. Resetting Counter Using with-else*:: + + >>> total = 0 + >>> x = 0 + >>> y = 20 + >>> while x <= y: + ...     total += x + ...     x += 1 + ... else: + ...     print total + ...     total = 0 + ... + 210 + +continue Statement +------------------ + +The continue statement is to be used when you are within a looping construct, and you have the requirement to tell Python to continue processing past the rest of the statements in the current loop. +Once the Python interpreter sees a continue statement, it ends the current iteration of the loop and goes on to continue processing the next iteration. +The continue statement can be used with any for or while loop. + +*Listing 3-20. Continue Statement*:: + + # Iterate over range and print out only the positive numbers + >>> x = 0 + >>> while x < 10: + ...     x += 1 + ...     if x % 2 != 0: + ...         continue + ...     print x + ... + 2 + 4 + 6 + 8 + 10 + +In this example, whenever x is odd, the 'continue' causes execution to move on to the next iteration of the loop. +When x is even, it is printed out. + +break Statement +--------------- + +Much like the continue statement, the break statement can be used inside of a loop. +We use the break statement in order to stop the loop completely so that a program can move on to its next task. +This differs from continue because the continue statement only stops the current iteration of the loop and moves onto the next iteration. +Let’s check it out: + +*Listing 3-21. Break Statement*:: + + >>> x = 10 + >>> while True: + ...     if x == 0: + ...         print 'x is now equal to zero!' + ...         break + ...     if x % 2 == 0: + ...         print x + ...     x -= 1 + ... + 10 + 8 + 6 + 4 + 2 + x is now equal to zero! + +In the previous example, the loop termination condition is always True, so execution only leaves the loop when a break is encountered. +If we are working with a break statement that resides within a loop that is contained in another loop (nested loop construct), then only the inner loop will be terminated. + +for Loop +-------- + +The for loop can be used on any iterable object. +It will simply iterate through the object and perform some processing during each pass. +Both the break and continue statements can also be used within the for loop. +The for statement in Python also differs from the same statement in Java because in Python we also have the else clause with this construct. +Once again, the else clause is executed when the for loop processes to completion without any break intervention or raised exceptions. +Also, if you are familiar with pre-Java 5 for loops then you will love the Python syntax. +In Java 5, the syntax of the for statement was adjusted a bit to make it more in line with syntactically easy languages such as Python. + +*Listing 3-22. Comparing Java and Python for-loop* + +*Example of Java for-loop (pre Java 5)*: + +.. code-block:: java + + for (x = 0; x <= myList.size(); x++) { + // processing statements iterating through myList + System.out.println("The current index is: " + x); + } + +*Listing 3-23. Example of Python for-loop*:: + + my_list = [1,2,3,4,5] + >>> for value in my_list: + ... # processing statements using value as the current item in my_list + ...     print 'The current value is %s' % (value) + ... + The current value is 1 + The current value is 2 + The current value is 3 + The current value is 4 + The current value is 5 + +As you can see, the Python syntax is a little easier to understand, but it doesn’t really save too many keystrokes at this point. +We still have to manage the index (x in this case) by ourselves by incrementing it with each iteration of the loop. +However, Python does provide a built-in function that can save us some keystrokes and provides a similar functionality to that of Java with the automatically incrementing index on the for loop. +The enumerate(sequence) +function does just that. +It will provide an index for our use and automatically manage it for us. + +*Listing 3-24. Enumerate() Functionality*:: + + >>> myList = ['jython','java','python','jruby','groovy'] + >>> for index, value in enumerate(myList): + ...     print index, value + ... + 0 jython + 1 java + 2 python + 3 jruby + 4 groovy + +If we do not require the use of an index, it can be removed and the syntax can be cleaned up a bit.:: + + >>> myList = ['jython', 'java', 'python', 'jruby', 'groovy'] + >>> for item in myList: + ...     print item + ... + jython + java + python + jruby + groovy + +Now we have covered the program flow for conditionals and looping constructs in the Python language. +However, good programming practice will tell you to keep it as simple as possible or the logic will become too hard to follow. +In practicing proper coding techniques, it is also good to know that lists, dictionaries, and other containers can be iterated over just like other objects. +Iteration over containers using the for loop is a very useful strategy. +Here is an example of iterating over a dictionary object. + +*Listing 3-25. Iteration Over Containers*:: + + # Define a dictionary and then iterate over it to print each value + >>> my_dict = {'Jython':'Java', 'CPython':'C', 'IronPython':'.NET','PyPy':'Python'} + >>> for key in my_dict: + ...     print key + ... + Jython + IronPython + CPython + PyPy + +It is useful to know that we can also obtain the values of a dictionary object via each iteration by calling my_dict.values(). Example Code ------------- - -Let’s take a look at an example program that uses some of the program flow which was discussed in this chapter. The example program simply makes use of an external text file to manage a list of players on a sports team. You will see how to follow proper program structure and use spacing effectively in this example. You will also see file utilization in action, along with utiliation of the *raw_input()* function. :: - - playerDict = {} - saveFile = False - exitSystem = False - # Enter a loop to enter inforation from keyboard - while not exitSystem: - print 'Sports Team Administration App' - enterPlayer = raw_input("Would you like to create a team or manage an existing team?\n (Enter 'C' for create, 'M' for manage, 'X' to exit) ") - if enterPlayer.upper() == 'C': - exitSystem = False - # Enter a player for the team - print 'Enter a list of players on our team along with their position' - enterCont = 'Y' - # While continuing to enter new players, perform the following - while enterCont.upper() == 'Y': - name = raw_input('Enter players first name: ') - position = raw_input('Enter players position: ') - playerDict[name] = position - saveFile = True - enterCont = raw_input("Enter another player? (Press 'N' to exit or 'Y' to continue)") - else: - exitSystem = True - elif enterPlayer.upper() == 'M': - exitSystem = False - # Read values from the external file into a dictionary object - print '\n’ - print 'Manage the Team' - playerfile = open('players.txt','r') - for player in playerfile: - playerList = player.split(':') - playerDict[playerList[0]] = playerList[1] - print 'Team Listing' - print '++++++++++++' - for i, player in enumerate(playerDict): - print 'Player %s Name: %s -- Position: %s' %(i, player, playerDict[player]) - else: - exitSystem = True - else: - # Save the external file and close resources - if saveFile: - print 'Saving Team Data...' - playerfile = open('players.txt','w') - for player in playerDict: - playerfile.write(player + ':' + playerDict[player] + '\n') - playerfile.close() - +============ + +Let’s take a look at an example program that uses some of the program flow which was discussed in this chapter. +The example program simply makes use of an external text file to manage a list of players on a sports team. +You will see how to follow proper program structure and use spacing effectively in this example. +You will also see file utilization in action, along with utilization of the raw_input() function. + +*Listing 3-26. # import os module*:: + + import os + + # Create empty dictionary + player_dict = {} + # Create an empty string + enter_player = '' + + # Enter a loop to enter inforation from keyboard + while enter_player.upper() != 'X': + + print 'Sports Team Administration App' + + # If the file exists, then allow us to manage it, otherwise force creation. + if os.path.isfile('players.txt'): + enter_player = raw_input("Would you like to create a team or manage an existing team?\n (Enter 'C' for create, 'M' for manage, 'X' to exit) ") + else: + # Force creation of file if it does not yet exist. + enter_player = 'C' + + # Check to determine which action to take. C = create, M = manage, X = Exit and Save + if enter_player.upper() == 'C': + + # Enter a player for the team + print 'Enter a list of players on our team along with their position' + enter_cont = 'Y' + + # While continuing to enter new player's, perform the following + while enter_cont.upper() == 'Y': + # Capture keyboard entry into name variable + name = raw_input('Enter players first name: ') + # Capture keyboard entry into position variable + position = raw_input('Enter players position: ') + # Assign position to a dictionary key of the player name + player_dict[name] = position + enter_cont = raw_input("Enter another player? (Press 'N' to exit or 'Y' to continue)") + else: + enter_player = 'X' + + # Manage player.txt entries + elif enter_player.upper() == 'M': + + # Read values from the external file into a dictionary object + print + print 'Manage the Team' + # Open file and assign to playerfile + playerfile = open('players.txt','r') + # Use the for-loop to iterate over the entries in the file + for player in playerfile: + # Split entries into key/value pairs and add to list + playerList = player.split(':') + # Build dictionary using list values from file + player_dict[playerList[0]] = playerList[1] + # Close the file + playerfile.close() + + print 'Team Listing' + print '++++++++++++' + + # Iterate over dictionary values and print key/value pairs + for i, player in enumerate(player_dict): + print 'Player %s Name: %s -- Position: %s' %(i, player, player_dict[player]) + + else: + # Save the external file and close resources + if player_dict: + + print 'Saving Team Data...' + # Open the file + playerfile = open('players.txt','w') + # Write each dictionary element to the file + for player in player_dict: + playerfile.write('%s:%s\n' % (player.strip(),player_dict[player].strip())) + # Close file + playerfile.close() + +This example is packed full of concepts that have been discussed throughout the first three chapters of the book. +As stated previously, the concept is to create and manage a list of sport players and their relative positions. +The example starts by entering a while() loop that runs the program until the user enters the exit command. +Next, the program checks to see if the 'players.txt' file exists. +If it does, then the program prompts the user to enter a code to determine the next action to be taken. +However, if the file does not exist then the user is forced to create at least one player/position pair in the file. + +Continuing on, the program allows the user to enter as many player/position pairs as needed, or exit the program at any time. +If the user chooses to manage the player/position list, the program simply opens the 'players.txt' file, uses a for() loop to iterate over each entry within the file. +A dictionary is populated with the current player in each iteration of the loop. +Once the loop has completed, the file is closed and the dictionary is iterated and printed. +Exiting the program forces the else() clause to be invoked, which iterates over each player in the dictionary and writes them to the file. + +Unfortunately, this program is quite simplistic and some features could not be implemented without knowledge of functions (Chapter 4) or classes (Chapter 6). +A good practice would be to revisit this program once those topics have been covered and simplify as well as add additional functionality. Summary -------- - -All programs are constructed out of definitions, statements and expressions. In this chapter we covered details of creating expressions and using them. Expressions can be composed of any number of mathematical operators and comparisons. In this chapter we discussed the basics of using mathematical operators in our programs. The __future__ division topic introduced us to using features from the __future__. We then delved into comparisons and comparison operators. - -We ended this short chapter by discussing proper program flow and properly learned about the *if* statement as well as how to construct different types of loops in Python. In the next chapter you will learn how to write functions, and the use of many built-in functions will be discussed. - - - - - - - +======= +All programs are constructed out of statements and expressions. +In this chapter we covered details of creating expressions and using them. +Expressions can be composed of any number of mathematical operators and comparisons. +In this chapter we discussed the basics of using mathematical operators in our programs. +The __future__ division topic introduced us to using features from the __future__. We then delved into comparisons and comparison operators. +We ended this short chapter by discussing proper program flow and properly learned about the if statement as well as how to construct different types of loops in Python. +In the next chapter you will learn how to write functions, and the use of many built-in functions will be discussed. diff --git a/README.md b/README.md index 37ff305..5bbf01e 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,6 @@ This book is formatted for and available at https://jython.readthedocs.io/en/lat This book is licensed under CC-BY-SA http://creativecommons.org/licenses/by-sa/3.0/ . Contributions in the form of pull requests are welcome, and are covered by the same license under the "inbound=outbound" part of the github terms of service https://help.github.com/en/articles/github-terms-of-service#6-contributions-under-repository-license . More detail on the open book license can be found in the book index and preamble (index.rst). - - ## Version History @@ -21,32 +19,66 @@ This book is licensed under CC-BY-SA http://creativecommons.org/licenses/by-sa/3 | Jython 2.5 | 1.0 | Juneau, J., Baker, J., Wierzbicki, F., Muoz, L. S., Ng, V., Ng, A., & Baker, D. L. (2010). The definitive guide to Jython: Python for the Java platform. Apress. | -# Build +# How to Build the Jython Book from Source ## Install and Build -Building locally requires Python 3.5 or above. These instructions are for windows. Other platforms should be similar. +Building locally requires Python 3.5 or above. +Use of a virtual environment is recommended in order to to isolate this project’s dependencies (the tools). +All you need to begin with is an installed Python. -1. Clone into a new project directory. +### Instructions for Windows Powershell. -`git clone ` - -These instructions assume you cloned into the directory `book`. The build needs to be run from the parent of the source folder `book`: it will create sibling directory `build` to hold the generated files. +1. Create a working directory, say `dg-jython`, and `cd` into it. +There, clone this repository: +``` +PS dg-jython> git clone https://github.com/jython/book.git +``` -2. (Optional) Use virtualenv to isolate this project's dependencies +These instructions assume you cloned into the directory `book`, a sub-directory of your working directory. +Do *not* `cd` into `book`: the build runs from the current directory: it will create a sub-directory `build` to hold the generated files. +2. If you do not have `virtualenv`, install it: ``` -virtualenv venv -.\venv\Scripts\activate +PS dg-jython> python3 -m pip install virtualenv ``` +(You may need to specify ``python3`` explicitly as shown, or `py -3`, or it may just be `python` depending on your set-up.) -3. `pip install -r book\requirements.txt` +3. Now create a virtual environment, activate it and install the tools. +``` +PS dg-jython> python3 -m virtualenv venv +... +PS dg-jython> .\venv\Scripts\activate +(venv) PS dg-jython> pip install -r .\book\requirements.txt +... +``` -4. `sphinx-build -N -b html .\book build\html` +4. You can now build the book as HTML in `./build` with the command: +``` +(venv) PS dg-jython> sphinx-build -N -b html book build\html +``` +(The option `-N` suppresses output formatting that impedes reading on a PoSH console.) Open `build\html\index.html` with your browser to view the generated documentation. +### Instructions for Linux. + +On Linux, it looks like this: +``` +$ python3 -m pip install virtualenv +... +$ python3 -m virtualenv venv +Using base prefix '/usr' +... +$ source venv/bin/activate +(venv) $ pip install -r book/requirements.txt +(venv) $ sphinx-build -b html book build/html +... +``` +Open `build/html/index.html` with your browser to view the generated documentation. + + ## Edit and Build -After edits to the markdown files, rerun `sphinx-build -N -b html .\book build\html` to regenerate the documentation. +After edits to the restructured text files, rerun `sphinx-build -b html book build/html` to regenerate the documentation. diff --git a/Scripting.rst b/Scripting.rst index a7cc0ad..4e64b69 100644 --- a/Scripting.rst +++ b/Scripting.rst @@ -1,4 +1,4 @@ -Chapter 8: Scripting With Jython +Chapter 9: Scripting With Jython +++++++++++++++++++++++++++++++++ In this chapter we will look at scripting with jython. For our purposes, I diff --git a/attribution.rst b/attribution.rst index 5799740..a170d2e 100644 --- a/attribution.rst +++ b/attribution.rst @@ -1,26 +1,184 @@ -Attribution -=========== +Acknowledgment and Dedications +============================== -Throughout the process of writing this book, many individuals from the community have taken time out to help us out. -We'd like to give a special thanks to the Python and Jython community as a whole for actively participating in the -feedback and contributions for this book via the mailing lists. +Josh Juneau +----------- + +First and foremost, I would like to thank my wife Angela for standing beside me +throughout my career and writing this book. She has been my inspiration and +motivation for continuing to improve my knowledge and move my career forward. +She is my rock, and I dedicate this book to her. I also thank my wonderful +children: Katie, Jake, Matt, and our new addition Zachary, for always making me +smile and for understanding on those weekend mornings when I was writing this +book instead of playing games. I hope that one day they can read this book and +understand why I spent so much time in front of my computer. + +I’d like to thank my parents and grandparents for allowing me to follow my +ambitions throughout my childhood. My family, including my in-laws, have always +supported me throughout my career and authoring this book and I really +appreciate it. I look forward to discussing this book with my family at future +gatherings as I’m sure they will all read it soon. + +My co-workers, especially Roger Slisz, Necota Smith, and Matt Arena, who showed +me the ropes in IT. Without that knowledge I wouldn’t have ventured into +learning about Oracle and PL/SQL, which ultimately led to this! I’d like to +especially thank Roger Slisz and Kent Collins for trusting me to guide and +develop the applications for our department, and for allowing me the freedom to +manage my projects and provide the necessary time and resource toward our +applications and databases. + +I’d really like to thank Jim Baker for providing me with the opportunity to +become the lead author for this book. I appreciate that he believed in me to +provide the leadership and knowledge to make this book a reality. Jim Baker is +a great person and a scholar; without him, this book may not have been written. +Jim and I collaborated to find the other great authors that helped us write +this book. In the end, I believe that the team of authors that was chosen +provides the perfect blend of knowledge and skills that went into authoring +this book. I thank each of the authors for devoting their time and effort +towards this book; I think that it will be a great asset to the community! +Thanks for everything, I look forward to writing the second edition soon! + +I owe a huge thanks to Duncan Parkes of Apress for providing excellent support +and advice. I also wish to thank all of our technical reviewers and our Apress +project coordinator, Mary Tobin. All of their efforts helped to make this book +complete and we couldn’t have done it without you. Last, but definitely not +least, I’d like to thank the Jython developers and the community as a whole. +The developers work hard to provide us with this great technology allowing us +to write Python on the JVM. Frank Wierzbicki has done an excellent job in +leading the core of Jython developers to produce 2.5.1, and I know that he’ll +continue to do a great job leading into the future. Thanks to the community for +using Jython and providing great ideas and support via the mailing lists; +without this help I could not provide the newsletter and podcast. + + +Jim Baker +--------- + +This book is dedicated to my kids, Zack and Zoe, who are just about the best +children a dad could hope for: happy, loving, and fun to be with. Fundamentally +what I love to do is create, so it's wonderful watching you grow! + +Three years ago we had this audacious idea in reviving Jython. We would jump to +supporting the 2.5 version of the Python language. And we would focus on make +it a suitable platform for running the increasingly large apps that are being +developed. This meant a renewed focus on compatibility for Jython. Fortunately +we could leverage the new reality that developers of Python applications, +frameworks, and libraries increasingly have a committment to strong testing. +Our problem was tractable because we could use this testing to converge on a +robust implementation. + +This book documents that we in fact achieved this goal, while still preserving +the ability for you to interactively explore and script the Java platform. In +other words, Jython has grown up, but it hasn't forgotten what made it both +useful and fun in the first place. + +To my good friend Frank Wierzbicki, we made it happen; Charlie Nutter, for his +committment to collaboration; Bruce Eckel and Albert Wenger, who both convinced +me that working on Jython was important; Leslie Hawthorn of the Google Open +Source Programs Office; Dorene Beaver; John Rose, Brian Goetz, and Ted Leung at +Sun, for their support of alternative languages on the JVM; Glyph Lefkowitz, +Jacob Kaplan-Moss, Chris Perkins, and Mark Ramm, for their support of a robust +Python ecosystem; my fellow Jython developers, Alan Kennedy, Charlie Groves, +Josh Juneau, Nicholas Riley, Oti Humbel, and Phil Jenvey, not to mention many +other contributors. And especially to my Google Summer of Code students, now +also Jython committers, Leo Soto and Tobias Ivarsson: it's been wonderful +watching you grow as both developers and individuals. + + +Victor Ng +--------- -We also thank the Python and Jython developers for producing this great programming language. So much hard work -has gone into the Python language that it has become one of the most solid and widely used object oriented -programming languages available today. The Jython developers have done a tremendous job bringing the Jython -of today up-to-speed with current versions of the Python language. The Jython community seems to be working -harder than ever before at making it a viable option for programming modern Python and Java -applications alike. Special thanks to those developers who have helped out with this book and still kept Jython -advancing. +Thanks to Liz and Rosie for putting up with far too many side projects this +year. Special thanks to everyone in the Jython and Python developer community +for making life as a programmer much less painful than it could be. -The authors of The Definitive Guide to Jython would like to offer an extra special thanks to the rest of the -individuals in this section. Without your insight or contributions portions of this book may not have -been possible. +Leo Soto +-------- + +First, thanks to my family for having the patience with me for having taking yet +another challenge which decreases the amount of time I can spend with them. +Specially Eliana, my mother, who has taken a big part of that sacrifice, and +also Nicolás, my brother, who gives encouragement in his particular way. They +and Leocadio, my father, who rests in peace, forged my personality and share +credit on every goal I achieve. + +Thanks to all my friends for sharing my happiness when starting this project and +following with encouragement when it seemed too difficult to be completed. I +would have probably give up without their support and example on what to do +when you really want something. + +Speaking of encouragement, I must mention that Jim Baker is responsible for +having me on the team who wrote this book: first by mentoring me on Jython and +later by insisting that I should share part of what I have learned on this +book. He is a great person and I can only be grateful to have met him. + +Thanks to Josh Juneau, our lead author. He coordinated our numerous team and +made sure we all were on the right track. He did that while also working on a +lot of chapters and also handling the paperwork. I have no idea how he managed +to do it. All I know is that he rocks. + +Thanks to Duncan Parkes, our editor, and all the technical reviewers who worked +on this book. Not only by catching mistakes but also by suggesting those +additions that can seem obvious in hindsight but that would never occurred to +you. + +On the first half of the Django chapter I received a lot of help from Jacob +Fenwick who discovered some problems on specific platforms and offered valuable +suggestions to overcome them. Thanks to him many readers won't experience the +frustration caused when the code shown on the book doesn't work on their +environment. By the way, while working on Django integration with Jython I've +met a lot of nice people on the Django community. Special thanks to Jacob +Kaplan-Moss for his outstanding support when I was working on that area. + +And thanks to the Jython community! Starting with our leader, Frank Wierzbicki, +who has played a crucial role to move Jython forward in the last years. The +core Jython developers are also really awesome people and I'm immensely happy +to work with them on the project. And every person of the Jython community I've +talked to has been nice and even when criticizing they know how to be +constructive. I'm grateful to work with this community and hope their members +will find this book useful! + + +Frank Wierzbicki +---------------- + +First and foremost, I want to thank my wife, Jill Fitzgibbons, for all of the +support she has given through all of these years of Jython work. Most of that +work occurred on weekends, nights, while on vacation, and other times +inconvenient to my family. My daughter, Lily, who is five at the time of +writing, has also needed to show patience when her dad was working on Jython +and on this book. I want to thank my parents, who brought a Commodore 64 into +the house when I was still impressionable enough to get sucked into a life of +programming. I also want to thank all of the contributors and users of Jython. +They make my work on Jython and this book worth doing. + + +Special Thanks +============== + +Throughout the process of writing this book, many individuals from the community +have taken time out to help us out. We'd like to give a special thanks to the +Python and Jython community as a whole for actively participating in the +feedback and contributions for this book via the mailing lists. +We also thank the Python and Jython developers for producing this great +programming language. So much hard work has gone into the Python language that +it has become one of the most solid and widely used object oriented programming +languages available today. The Jython developers have done a tremendous job +bringing the Jython of today up-to-speed with current versions of the Python +language. The Jython community seems to be working harder than ever before at +making it a viable option for programming modern Python and Java applications +alike. Special thanks to those developers who have helped out with this book +and still kept Jython advancing. -**James Gardner** - Thanks to James Gardner for his help in providing us with a working toolset and knowledge to convert -from restructured text format to MS Word for the Apress editing process. The open source book was written -completely in restructured text, and converted to .doc format for the Apress drafts and editing procedures. -James offered great insight on how he used this process with The Pylons Book, and he also provided us with -a conversion utility that was used for his book. +The authors of The Definitive Guide to Jython would like to offer an extra +special thanks to the rest of the individuals in this section. Without your +insight or contributions portions of this book may not have been possible. +**James Gardner** - Thanks to James Gardner for his help in providing us with a +working toolset and knowledge to convert from restructured text format to MS +Word for the Apress editing process. The open source book was written +completely in restructured text, and converted to .doc format for the Apress +drafts and editing procedures. James offered great insight on how he used this +process with The Pylons Book, and he also provided us with a conversion utility +that was used for his book.