Author Topic: Coding and Scripting > Learning Python  (Read 7944 times)

Offline Neal ManBear

  • Administrator
  • Super Villain
  • *****
  • Posts: 15845
  • LXDE! Coffee, Bacon and Cheesecake!
Re: Coding and Scripting > Learning Python
« Reply #15 on: December 04, 2009, 02:09:44 AM »
Neptune,
Thank you! That is an excellent start.


Neptune

  • Guest
Re: Coding and Scripting > Learning Python
« Reply #16 on: December 04, 2009, 06:06:40 AM »
Ok, glad you liked it, Neal, and welcome to critter and hola to musonio...

Now - has anybody had any brilliant ideas as to how to tell when the bulk of the class has absorbed one installment and is comfortable moving on? For now, I'm going to assume everyone has no problems so far, and post another installment today, but there may be a better way of ensuring the quickest kid in the class doesn't run away with the coursework.

musonio

  • Guest
Re: Coding and Scripting > Learning Python
« Reply #17 on: December 04, 2009, 06:14:55 AM »
How about opening another thread for questions so that this one does not get clogged?

Neptune

  • Guest
Re: Coding and Scripting > Learning Python
« Reply #18 on: December 04, 2009, 08:14:33 PM »
Recap:
We know how to start and exit the Python interactive shell. We know that Python constants and variables are dynamically typed, automatically at execution time. We know that Python is a strongly-typed language, i.e., it will gripe if you use the wrong type of object. We've learned a couple of operators, + and *, and that those operators are "overloaded", i.e. behave differently depending on their operands. We know how to assign constants to a variable, and how to explicitly re-cast a constant or variable to a different type.

Today, we're going to build on that foundation, dip our toes into the murky waters of modules and functions, and maybe even write our first Python program.

I see a couple of you eager beavers have already opened your python interpreter. A+ for effort. Now, CTRL-d out of it and lets make a new home for some of our projects. You more cautious types who haven't even opened a terminal window should do so now.

I'm going to recommend putting our new home in your home directory. If you have a good reason for putting it in another directory, please cd there now - otherwise, type cd ~ and press enter.

Now, copy and paste the following command into your terminal window, then press enter.
Code: [Select]

mkdir -p pyedu/{lesson01/notes,lesson02/notes,lesson03/notes,lesson04/notes,lesson05/notes}


Yes, I'm a lazy sod who won't type 'mkdir' ten times when once will do. BTW - the number of folders is not a commitment to fill them, nor an indication that we won't overflow them. If we need more, we'll make more, and if we don't, no loss.

Now, type cd pyedu/lesson01 and press enter.

Start up the python interpreter shell (as always, your input is in green):

[zccw01@LapNix lesson01]$ python
Python 2.5.2 (r252:60911, Jun 28 2008, 14:11:09)
[GCC 4.1.1 20060724 (prerelease) (4.1.1-4pclos2007)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>


We touched very briefly on several variable types in the last installment. Let's dig a little deeper into one of those types, the string. Python considers strings to be immutable sequential objects. Immutable means they can't be altered. So we can skip trying to alter them. Sequential means they are ordered, indexable, sliceable, have length, and can be iterated over. Ordered is a pretty obvious attribute - after all, if you entered a customer name like 'Mr. James Smythe', and it came out as "yMams m. tJeshre", you'd properly consider that to be a fairly useless data type. So the next attribute is indexable - let's do some indexing. In your python interpreter shell, type the following lines, pressing enter after each one:


'abcde'[ 0 ]
'abcde'[ 3 ]
'abcde'[ 9 ]

Here's what I got:

>>> 'abcde'[ 0 ]
'a'
>>> 'abcde'[ 3 ]
'd'
>>> 'abcde'[ 9 ]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range
>>>   


So, what do we now know? To index a sequential object, you append the index enclosed in square brackets, as [n]. We know that the first element of a sequential object is 0. And, we know that Python gets mad when your index goes off the end of the object.

I can hear the wheels turning now. So, you're thinking, if zero is the lowest index of the object, and the highest index can never be greater than the length of the object minus 1... What about negative indices? As it turns out, negative indices are fine with Python, and are fairly useful. Try the following, pressing enter after each line:

'abcde'[-1]
'abcde'[-3]
'abcde'[-9]
'abcde'[-0]


You should see something like this:

>>> 'abcde'[-1]
'e'
>>> 'abcde'[-3]
'c'
>>> 'abcde'[-9]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range
>>> 'abcde'[-0]
'a'
>>>


When you feed Python a negative index, it makes the assumption that you want to work backwards from the end of the sequential object. This is actually quite useful, and it's very common to see string[-1] as a means of examining the last character of a string, which may be a null, or carriage return, or line feed, or... This notation is not symmetrical; 'abcde'[-5] will return 'a' where 'abcde'[5] will fail with an 'index out of range' error. This is a necessary evil, since -0 and 0 are equivalent in most languages.

So, that's indexing of a sequential object. What about slicing? A slice is simply a beginning and an ending index separated by a colon, enclosed in square brackets. If the beginning index is blank, it is assumed to be the first element of the object. If the ending index is blank, it is assumed to be the last element of the object. So let's slice:

'abcde'[2:4]
'abcde'[:3]
'abcde'[3:]
'abcde'[:]
'abcde'[4:99]


You should have:

>>> 'abcde'[2:4]
'cd'
>>> 'abcde'[:3]
'abc'
>>> 'abcde'[3:]
'de'
>>> 'abcde'[:]
'abcde'
>>> 'abcde'[4:99]
'e'
>>>


Note that in the last example, the out-of-range index did not cause an error. Slice notation is a little more forgiving than index notation. In this case, Python simply set the out-of-range ending index back to the end of the string.

Python is also fairly forgiving about invalid starting indices. Try:

'abcde'[45:99]
'abcde'[4:2]

 
Both of them return an empty, or null string, ''. In the first case, the starting index was out of range, in the second case, the starting index was greater than the ending index.

So, are negative indices valid in slice notation? You bet:

'abcde'[1:-1]  # everthing except the first and last character
'abcde'[-2:]   # just the last two characters
'abcde'[-3:4]  # the third from last through the fourth character

We've covered indexing and slicing - what about iteration? Iteration is a common programming task, where you walk, stepwise, through an object or group of objects. To demonstrate classical iteration, we're going to need a couple of functions, len(), and range().

The len() function is fairly self-explanatory It returns an integer representing the length of its argument. Try entering the following:

len('A String')
len('A Longer String')
len('')


The results are much as you'd expect. No surprises here:

>>> len('A String')
8
>>> len('A Longer String')
15
>>> len('')
0
>>>     


The range() function is a little trickier. In its simplest form, range(n), where n is an integer, range(n) will return a list of integers, beginning with zero, and up to, but not including n.

Give it a try:

>>> range(5)
[0, 1, 2, 3, 4]
>>> range(9)
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>>

The list that range() returns is a new data type, and one that we'll explore later, but for now, the important attribute of a list is that it is a sequential data type - which means we can iterate it. So now, all we need is an iterator statement, and the classic iterator statement in many languages is the for statement.

Lets put some pieces together. As usual, press enter after each line, noting that before the print() line you will need to press the space three times, and press enter twice after:

>>> my_str='Python'
>>> l=len(my_str)
>>> r=range(l)
>>> for x in r:
...    print(my_str[ x ])
...
P
y
t
h
o
n
>>>


There are a couple of new things here. First, the for statement. The for statement is a type of flow control statement known as a loop. All of the statements we've seen up til now will execute, then proceed to the next statement in line. Flow control statements allow you to conditionally execute code blocks, skip code blocks, or repeat code blocks. If you've worked in other languages, you may have seen a for statement something like this:

for (i=1;i<10,i++)

In other words for (initialize;loop-test;increment)

Not with Python. The Python for statement is an iterator, pure and simple, and it starts at one end of an iterable and works its way to the end, at each pass assigning the next iterable element to the target variable.

for target in iterable-object:

So in our example, where the iterable was a list of integers returned from the range() function, on the first pass, x will be assigned a value of 0, on the next pass, a value of 1, and so forth til the end of the list is reached.

To illustrate better, try the following, remembering that the print statement must be indented by three spaces, and you must press enter twice after.

>>> for x in ['spam', 'Spam', 'SPAM', 'rat', 42]:
...    print(x)
...
spam
Spam
SPAM
rat
42
>>>


So, back to our "Python" string iteration - can we make it better? Sure. Since everything in Python is an object, it's permissible to pass the return from one function directly to another, like this:

>>> my_str='Python'
>>> for x in range(len(my_str)):
...    print(my_str[ x ])
...
P
y
t
h
o
n
>>>


But if we're going to use Python functionality, let's go all the way. Remember when I said this was a classical iteration example? Well, since we know that strings are sequential objects, and we know that all sequential objects are iterable, maybe we can dispense with the classical iteration trappings, and just iterate directly on the string. And so we can:

>>> for x in 'Python':
...    print(x)
...
P
y
t
h
o
n
>>>


With these tools tucked firmly in our workbelt, let's solve a family problem. It seems our dear sister, Dolly, suffers from a bizarre form of dyslexia. Apparently, she can only read backward. Since spelling backward is such a royal pain, poor Dolly never gets any mail from her family.

CTRL-d to close the python interpreter shell.

Enter the following in your terminal window and press enter:

touch text_utils.py

Then, substituting your favorite programmer's editor for kwrite, enter the following:

kwrite text_utils.py &

Enter the following code into your text_utils.py file and save it. Don't close the editor window yet, we'll be needing it shortly. Note that each level of indentation is a multiple of three spaces - this matters. If you just copy-paste the whole body of code, it should align correctly. Don't be tempted to format with tabs - we'll find out why later.
Code: [Select]

def flip_txt(message):
   rvs_msg = ""
   for x in message:
      rvs_msg = x + rvs_msg
   return rvs_msg
There you go. Your first module, text_utils, and your first function, flip_txt(). So lets send Dolly a message.

Be sure you've saved text_utils.py, then, back in your terminal window, restart the Python interpreter:

[zccw01@LapNix lesson01]$ python
Python 2.5.2 (r252:60911, Jun 28 2008, 14:11:09)
[GCC 4.1.1 20060724 (prerelease) (4.1.1-4pclos2007)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

Enter the following statement:

>>> import text_utils
>>>


Notice that nothing happened, except that you got another >>> prompt. That's Python for you. You screw up and it yells at you, you get it right, and there's just silence. You'll have to get your positive reinforcement elsewhere. So, how do we send Dolly a message? Easy:

>>> text_utils.flip_txt("Dear Dolly. I hope you are doing well. Yours Truly.")
'.ylurT sruoY .llew gniod era uoy epoh I .ylloD raeD'
>>>


When you import a module, you bring it into your current scope, or namespace. At that point, all of its public objects and methods are accessible using the '.' notation. There is a variant of the import statement. If you hate the idea of typing text_utils.whatever(), you can import module as name, for example, import textutils as tu. Then we could say tu.flip_txt(). That can save on typing, but it's generally not a good idea to alias module names if you're working with a number of people who have to read your code, and are expecting known modules.

The final variant of the import statement, which is seriously, seriously not recommended, is; from module import x. x may be an asterisk, in which case everything from that module gets dragged into your namespace, or it may be specific, as in from text_utils import flip_txt. At that point, the objects may be directly invoked just as any other object in your code, i.e. instead of text_utils.flip_txt(), we could just issue flip_txt() directly. The reason this form is strongly discouraged is that with a large module you stand a fairly good chance of having name collisions with your code, with unpredictable results. It also obscures the source of the objects you are referencing, and we don't like obscurity.

Finally, let's go back to the editor window which has text_utils.py. Notice the beautifully indented format? Remember how I've been banging on about "three spaces"? Well, I've been lying. Not about the need to indent, but about three spaces - that part is totally arbitrary. You can indent one space, or ten spaces. It's completely up to you. But the indentation has to be consistent for every line of the code block. That's because whitespace is literally part of the Python syntax. C programmers hate this, and here's why. Below is a sample C++ program.

int  main  ()
{
   cout  << "Hello World!";
   return  0:
}

Notice that it's nicely indented? But that's just a matter of preference. I've seen a variety of styles, like:

int  main  () {
              cout  << "Hello World!";
              return  0:
              }

You could even, as one of our classmates that I shamelessly ripped off demonstrated, write it as:

int  main  () { cout  << "Hello World!"; return  0: }

C, and many other languages use special characters to delimit lines and code blocks, but leave the formatting totally at the programmer's discretion. And that's the problem. Programmers have no discretion. I swear on a stack of holy books that if you put five C programmers on a project, they will have six different indentation styles, and by the end of the project, they will be spending 90% of their time reformatting each others code to match their indentation quirks.

Worse, I've seen C programmers get tangled up for hours on something like this:

if (something)
        if (something else)
                do_stuff(stuff_params);
else
        this_blows(something wrong);

It's not immediately obvious even in this small example what went wrong in the above code, and when you're dealing with much larger functions, with many lines of code it can drive you crazy. The problem, of course, is that the indentation does not match what the code is actually doing - the else clause should be lined up under the second if statement, and its code block similarly indented. Python simply can't have these problems.

Python takes the position that indenting code blocks is the right way to do things, and by making it part of the syntax, the language is also able to get rid of most of the semantic delimiter clutter, like squirelly braces and hemi-colons.

Python has retained a colon at the end of a flow control statements to designate the beginning of a new code block. You see two colons in our flip_txt() function; one at the end of the function declaration, and one at the end of the for statement. In both cases, that's your cue to indent another level. Notice also that it's easy to see the end of a code block - the indentation takes a step to the left. The for statement in our example controls a code block of one line, and you can see at a glance where the indentation, hence, the code block ends.

Which is why I cautioned you about tabs above. Let me emphasize that. Tabs are evil. Tabs display at different widths on different systems and editors, they sometimes get translated in strange ways during copy/paste operations, and the absolute worst is tabs and spaces mixed together. The behavior of spaces, on the other hand, is consistent and safe across all platforms and editors. I strongly suggest configuring your editor to convert all tabs to spaces, and to produce a set number of spaces instead of a tab character when the tab key is pressed.

Meanwhile, back to our text_utils.py. There are only two really new things here. The function declaration, which is the keyword def, followed by the function name with any expected parameters in parenthesis, followed by a colon. The other new statement is the return statement. The return statement ends the execution of the function, yields control back to the caller, and optionally, returns any Python object (or, as we'll see later, combination of objects) to the caller.

Other than that, with a bit of thought, it should be possible to puzzle out just how the text is getting reversed. Scream loudly if not.

Well, that should keep some of you scratching your heads for a few minutes.

Next up: There's methods to my madness.


Offline Bald Brick

  • PCLinuxOS Tester
  • Hero Member
  • *******
  • Posts: 6372
  • I'm going South
Re: Coding and Scripting > Learning Python
« Reply #19 on: December 04, 2009, 08:50:12 PM »
A very good lesson. The first one seemed clear but a bit obvious. This one was as clear and taught me a lot. Thank you. Looking forward to the next one.

(By the way, the "~" in "cd ~" is redundant. "cd" without any directory specified will take you to your home directory.)
« Last Edit: December 05, 2009, 09:48:37 AM by blackbird »
Feed the trolls!
They need it!

AMD Athlon 7450 Dual-Core Processor, 7.80 GiB RAM, Nvidia GeForce GT 120/PCIe/SSE2, OpenGL/ES-version: 3.3 0 NVIDIA 295.40, SBx00 Azalia (Intel HDA) soundcard, ‎Logitech B500 webcam, SAA7146 DVB card, HDDs: Seagate 250824AS, Western Digital WD10EAVS-00D

Offline The Chief

  • Hero Member
  • *****
  • Posts: 2229
Re: Coding and Scripting > Learning Python
« Reply #20 on: December 05, 2009, 09:39:40 AM »
Python takes the position that indenting code blocks is the right way to do things, and by making it part of the syntax, the language is also able to get rid of most of the semantic delimiter clutter, like squirelly braces and hemi-colons.

You would have hated Coral  ;D  ;D - it simply ignored whitespace, line feeds and carriage returns.

"The last count of items" was fine as a variable name (without the quotes - those were reserved for keywords).   And it didn't matter if you left out some spaces, added some in, or doubled up on some, or used some tabs - as long as the characters Thelastcountofitems were all present and in the right order, it referred to the same variable.

Oh, and BTW, excellent lesson!  Great job! :-* :-*

Retired Senior Chief, Retired Software Engineer, Active GrandPa

Offline Crow

  • Hero Member
  • *****
  • Posts: 8746
  • OBJECTS IN MIRROR... ARE LOSING
Re: Coding and Scripting > Learning Python
« Reply #21 on: December 05, 2009, 10:00:53 AM »
Half last night and I'm working on it right now, some exercises to be sure I understand.

I think I will make my first mind map (my brain welcome every help)

You have a gift in making this seem simple, thank you.
I shall pass this way but once;
any good therefore that I can do,
or any kindness that I can show
let me not defer nor neglect it,
for I shall not pass this way again.

Linux User #330412

Offline Andy Axnot

  • Hero Member
  • *****
  • Posts: 694
Re: Coding and Scripting > Learning Python
« Reply #22 on: December 05, 2009, 10:43:44 AM »
Thanks, this is great!  I want to review and make some notes (helps retention better than rereading) and such, but I'm still with you.

I did notice that I wound up with an "extra" file in 'lesson01':  'text_utils.pyc', file type Python Bytecode.  It's easy enough to see what this is, more or less, but do we want to know anything about it at this point? 

Andy
Greetings from beautiful downtown Brooklyn, NY   USA
  Still searching for a replacement for KDE3; E17 is looking good; LXDE, too

"all will be fine soon, once kde3 is back on the main repos" - Titus T6us    :o

Offline gseaman

  • PCLinuxOS Tester
  • Hero Member
  • *******
  • Posts: 3789
Re: Coding and Scripting > Learning Python
« Reply #23 on: December 05, 2009, 04:37:02 PM »
Great lesson! There was a lot to it, but it was very understandable. Thanks.

Galen

Neptune

  • Guest
Re: Coding and Scripting > Learning Python
« Reply #24 on: December 07, 2009, 11:58:52 PM »
Not a lesson - well, maybe not a lesson.

I haven't vanished, but I got a customer call doing their year-end reports. They wanted to know why a product that was introduced in November was showing up in sales reports as far back as July. I tried congratulating them on their time-traveling sales force, but they weren't having it.

I suspect that some of my clever SQL got a bit more clever than its creator.

So maybe there is a Python (or programming in general) lesson here, after all.

I think it was Brian Kernighan who cautioned against clever programming. "Debugging", he said, "is at least twice as hard as programming. Therefore, if you have been as clever as you possibly can writing the code, you will never be able to debug it." Something to keep in mind as we go forward.

The next installment is done, except for the bits that aren't done (yep, I had a contractor tell me those exact words once), and I'll get it wrapped up and posted within the next day.

Cheers - Neptune.

Offline gseaman

  • PCLinuxOS Tester
  • Hero Member
  • *******
  • Posts: 3789
Re: Coding and Scripting > Learning Python
« Reply #25 on: December 08, 2009, 12:26:39 AM »
I'm looking forward to it.
galen

Offline Bald Brick

  • PCLinuxOS Tester
  • Hero Member
  • *******
  • Posts: 6372
  • I'm going South
Re: Coding and Scripting > Learning Python
« Reply #26 on: December 08, 2009, 12:31:47 AM »
So am I. (But don't kill yourself. We aren't worth it. Well, most of us ...)
Feed the trolls!
They need it!

AMD Athlon 7450 Dual-Core Processor, 7.80 GiB RAM, Nvidia GeForce GT 120/PCIe/SSE2, OpenGL/ES-version: 3.3 0 NVIDIA 295.40, SBx00 Azalia (Intel HDA) soundcard, ‎Logitech B500 webcam, SAA7146 DVB card, HDDs: Seagate 250824AS, Western Digital WD10EAVS-00D

Offline Andy Axnot

  • Hero Member
  • *****
  • Posts: 694
Re: Coding and Scripting > Learning Python
« Reply #27 on: December 08, 2009, 07:11:10 AM »
I, too, am looking forward to the next lesson, but I understand that you have a life and have other things to concern yourself with.  Actually, we all do, and maybe it's not a bad idea to go at measured pace which will give everyone, instructor and students, time enough to do the tutorial without pressure.

We never seem to have enough time these days for all the good things.   :(

Andy
Greetings from beautiful downtown Brooklyn, NY   USA
  Still searching for a replacement for KDE3; E17 is looking good; LXDE, too

"all will be fine soon, once kde3 is back on the main repos" - Titus T6us    :o

Neptune

  • Guest
Re: Coding and Scripting > Learning Python
« Reply #28 on: December 10, 2009, 02:54:25 AM »
Recap:
In our last segment, we created a module which included a function, and learned how to load and use that module. We introduced a new variable type, the list, and discussed some of the characteristics of a couple of variable types, and the use of indexing and slicing with sequence-type variables. We touched on our first flow control statement, "for" and learned that whitespace is an integral part of the Python syntax. We also moved away from the single-letter variable names we had been using in the examples, which is as good a time as any to speak a bit on variable names.

Einstein was a genius - but in a programming class, he'd have been marked down for his variable names.
E=mc2 - really? What does that mean?
To a mathemetician, "E", or "e", might mean Euler's Number - which is a big deal in the math world. To a chemist, "m" might represent molar mass. The point is, in programming, your variable naming is part of the documentation. While compact, and easy to type, single-letter variable names are seldom descriptive. In general, use of single-letter variable names, like x, where the variables are temporary, and are only used in a small block of code, like a short loop, is ok - but for the bulk of your actual programming it's a good idea to be a bit more descriptive, as in our flip_txt() example function from the last segment.

As in all things programming, there are guidelines and rules. Python variables may contain letters, numbers and the underscore. Python names may not begin with a number. Python names are case-sensitive; q4_sales_sum and Q4_Sales_Sum are two different variables. In addition, Python has kept a handful of names for itself - don't use the following:

Code: [Select]
and, assert, break, class, continue,
def, del, elif, else, except, exec,
finally, for, from, global, if, import,
in, is, lambda, not, or, pass, print,
raise, return, try, while, yield

Finally, there are a few names which you can use - but you'll be sorry if you do, like "True", "False", and "None" These are all predefined by Python, and Python programmers who use these will curse your great-grandchildren if you re-define them.

So, in the last segment I teased the idea of methods. If you'll remember from our first segment, I gave the object-oriented perspective of a car as having methods such as accelerate, turn, and brake. In Python, the role of methods is played by functions, but the important object-oriented concept here is that many Python objects, like cars, have their own methods that they carry around with them like portable tool kits.

At this point, open your terminal window, and go to our current working folder, cd ~/pyedu/lesson01 (unless you opted not to use your home folder, in which case substitute out the "~"), and start the python interpreter:

[zccw01@LapNix lesson01]$ python
Python 2.5.2 (r252:60911, Jun 28 2008, 14:11:09)
[GCC 4.1.1 20060724 (prerelease) (4.1.1-4pclos2007)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>


As mentioned above, in the last segment we introduced a new variable type, the list. A list is denoted by square brackets, as shown in the last installment's examples. So what methods does a list variable have? Lets ask Python. The dir() function returns a sorted list of names defined for an object. Simply place the object in the parenthesis, as in the following example where we want to know about a list variable, which is the square brackets:

>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>>     


In general, the names bracketed by double underscores are used by other functions - the names we are interested in (for now) are those without the double-underscores.

So what are these names, like append, count, extend, etc.?

Again, let's revisit the concept of object types, and ask Python.

>>> type([].append)
<type 'builtin_function_or_method'>
>>>

Great - so we now know that ['this', 'is', 'a', 'list'].append() is a function - but what does it do?

You guessed it - let's ask Python (note the double underscores before and after "doc"):

>>> print([].append.__doc__)
L.append(object) -- append object to end
>>>


So, knowing this, we can try the following:

>>> my_list = [1,4,3.14159]
>>> my_list.append("Guido")
>>> print(my_list)
[1, 4, 3.1415899999999999, 'Guido']
>>>


By now, you're beginning to suspect something about lists - they don't care what their content is. You can have a list of integers, a list of strings, even a list of lists - or any combination of the above. You can even have a list of functions, which can be a very useful method of dispatching various functions based on a variable or condition.

The other thing I hope you're beginning to suspect is that it's pretty cool that Python documents itself so well. Hey, it's a language that's happy to share with you. The .__doc__ attribute isn't a substitute for a complete Python reference - but it's a very handy memory jogger when all you need is a reminder.

So does this dir() function work on modules? Why not - they're an obect, too, right? Try the following in your Python interpreter:

>>> import math
>>> dir(math)
['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
>>> type(math.pi)
<type 'float'>
>>> math.pi
3.1415926535897931
>>> type(math.sin)
<type 'builtin_function_or_method'>
>>> print(math.sin.__doc__)
sin(x)

Return the sine of x (measured in radians).
>>>


So let's introduce one more flow-control statement and try to solve a vacation challenge. The new flow control statement is the if statement, and its syntax is:

if condition:
elif:
elif:
else:

You may have zero elif clauses, which are just syntactic shorthand for else: if, and the else clause is also optional.

The if statement operates on conditions, the result of which may be either True, or False. Conditions usually involve comparisons of some sort, and Python is no exception. Conditional operators include:
Code: [Select]

> (Greater Than)
< (Less Than)
== (Equal To)
!= (Not Equal To)
<> (Not Equal To - Deprecated - use !=)

In addition, Python considers 0, and null or empty variables to be False, and non-zero, and non-empty variables to be True.

Similarly, functions that return variables may be used for the condition with the same rules as variables.

Finally, complex conditions may be used, and combined with and or or, and the results of any condition may be reversed with not.

Remember - because if, elif and else are related to flow control, they are always followed by a colon, and a code block of one or more indented lines.


So lets see the if statement in action.

CTRL-d out of your python interpreter, and edit our text_utils.py module from our previous segment:

[zccw01@LapNix lesson01]$ kwrite text_utils.py &

(you may, by the way, as one of our sharp-eyed members has already observed, see a text_utils.pyc file. This is a nose hair. You can pluck it out, but it will grow back. Python byte-compiles its modules at run time to make things a little quicker the next time around, and names the byte-compiled modules with a .pyc extension. Ignore it - it's part of Python.)

Now, let's solve our travel problem. You've noticed a poster at the travel agent with great rates to visit the exotic, sun-drenched beaches of Orwaynay. You decide that's just the ticket to cure your winter doldrums, and decide to book a vacation. The only problem is the language. The Orwaynayans speak English, but they learned it from a Jesuit they rescued from the sea, who had been driven just a little bit bonkers by weeks stranded in a crippled boat with nothing but communion wafers to eat. But, no worries - the rules of the language are simple, and Python is easily up to the challenge.

Copy/paste the following into text_utils.py, at the bottom, after the flip_txt function:

Code: [Select]
def splitter(a_word):
   if not len(a_word):
      return('','')
   if not a_word.isalpha():
      return('','')
   if a_word[0].lower() in 'aeiou':
      return('',a_word)
   if a_word[:2].lower()=='qu':
      return(a_word[:2], a_word[2:])
   for i in range(len(a_word)):
      if a_word[i].lower() in 'aeiou':
         return(a_word[:i],a_word[i:])

def xlate_it(sentence):
   out_sentence=''
   for a_word in sentence.split():
      pref,suf=splitter(a_word)
      if pref:
         if pref[0].upper()==pref[0]:
            suf=suf[0].upper()+suf[1:]
         pref=pref.lower()
      if pref=='' and suf[-1:]in 'aeiou':
         suf += 'yay'
      else:
         suf += pref+'ay'
      out_sentence+=suf+' '
   return(out_sentence)
(some of you exerienced programmers may be bristling up - don't worry, we'll deal with it.)

Now, let's fire up the Python interpreter, and try:

>>> import text_utils

We need to start building our list of important Orwaynayan phrases, so:

>>> text_utils.xlate_it("Please direct me to the nearest bail bondsman")
'Easeplay irectday emay otay ethay earestnay ailbay ondsmanbay '

And, if dear reverse-dyslexia sister Dolly comes along, there's no need to leave her out:

>>> text_utils.flip_txt(text_utils.xlate_it("Please direct me to the nearest bail bondsman"))
' yabnamsdno yablia yantserae yahte yato yame yadtceri yalpesaE'
>>>


We're going to break this segment into two installations. While we're waiting for part II, walk through the code, and try some of the tricks we've learned today to gain insight as to what it's doing - we'll break it down stepwise in the next installment and see how close you got.

Offline Crow

  • Hero Member
  • *****
  • Posts: 8746
  • OBJECTS IN MIRROR... ARE LOSING
Re: Coding and Scripting > Learning Python
« Reply #29 on: December 10, 2009, 08:11:04 AM »
AAArrgghh will look at this until Monday, today is my last day at work but have some things to do Friday to Sunday.

And next comes CHRISTMAS VACATIONS
Looks great.
I shall pass this way but once;
any good therefore that I can do,
or any kindness that I can show
let me not defer nor neglect it,
for I shall not pass this way again.

Linux User #330412