Python Language

[ LiB ]

A language is considered interpreted if it doesn't create binary files containing machine code. Keeping your programs in machine code limits you to running them on a single processor architecture; your Windows programs obviously won't run on a Macintosh, because the compiled programs don't speak the same machine code.

Interpreted language programs usually have two components : the program and an interpreter. Figure 17.1 shows you how an interpreted language system works.

Figure 17.1. With an interpreted language, there is no need to compile the language for different systems, because the interpreter program does the conversion from the language into machine code.

graphic/17fig01.gif


The major benefit of such a system is that you can run it on any system that has an interpreter installed. Even better, you can tell an interpreter to dynamically reload programs when they change (which is the main argument for implementing a scripting system in the BetterMUD).

The downside, of course, is the extra layer of abstraction. It takes work to translate the instructions into a native machine format. Processors, however, are so fast these days that the translation of instruction is rarely a concern, which explains why interpreted languages are quickly gaining popularity in the computing world.

Installing Python

If you're on Windows, you probably don't have Python installed. If you're on Linux, you probably have at least version 2.2 installed (at the time of this writing, Python is at version 2.3, which is much faster than Python 2.2). If you don't have Python installed on your Linux machine, please ask your administrator to install it for you, so you can play around with it.

NOTE

For this book, I am using Python 2.2. Even though Python 2.3 is much faster and less buggy , it was released too late for me to switch everything over and test it completely. Feel free to use Python 2.3 if you wish. I've included it on the CD.

I have included the distributions for Python on the CD in the directory /goodies/ python. The Windows version of Python 2.2 is located at /goodies/python/windows/ Python-2.2.3.exe, and the Linux version at / goodies /python/linux/Python-2.2.3.tgz.

Snake Charming

Once you've installed Python on your system, you can jump right into it and start programming right away. The Python distribution comes with an interactive interpreter program. This should be named something like Python2.2 on Linux, and python.exe on Windows.

Once you have the interpreter running, you will see something like the output shown in Figure 17.2.

Figure 17.2. The Python interactive interpreter allows you to type Python code that it runs for you on the spot.

graphic/17fig02.gif


Python allows you to type in code, and as soon as you press Enter, the program executes the code you entered. For your first Python program, type in print "Hello World!" , and press Enter. The output should look like this:

 >>> print "Hello World!" Hello World! 

Wow! Even BASIC isn't this easy.

Variables

Python has datatypes, but variables are dynamically bound to their types. This means that a variable can change what type it is, while a program is running! If you're used to static-typed languages like C++, this concept may boggle your mind (it sure boggled mine for a few hours!).

NOTE

Do not show Python to an aged Assembly Code Guru. His mind will either terminally shut down, or promptly explode.

Try it out. Type this code into Python:

 x = 42 x = "YOU'RE SUPPOSED TO BE AN INT!" 

Here's some sample output that I got from that code:

 >>> x = 42 >>> x 42 >>> x = "YOU'RE SUPPPOSED TO BE AN INT!" >>> x "YOU'RE SUPPPOSED TO BE AN INT!" 

You may experience any of these reactions :

  1. Whoa! How cool!

  2. THAT'S NOT POSSIBLE!

  3. *brain explodes*

I really hope your reaction was #1, because you're going to have to get used to Python if you ever want to do anything interesting in the BetterMUD.

Types

Python has built-in types, but you really don't care much about the types of your data. There's a built-in function to determine the type of something called type . Look at the following interpreter interaction:

 >>> type( 5 ) <type 'int'> >>> type ("pies" ) <type 'str'> >>> type( 3.1415926535897932384626433832795 ) <type 'float'> >>> type( 123456789000000000 ) <type 'long'> 

Those are the four types you'll be using most often. Python has other built-in types (such as Booleans in 2.3 and complex/imaginary numbers ), but you won't be using those as much.

Integers

Python has two types of integers. One is a standard 32-bit type that you're familiar with, and the other is a very cool flexible integer format.

Ints

Python int s are standard signed 32 bits, representing numbers from -2,147,483,648 to 2,147,483,647. The really awesome thing, however, is that ints never overflow. Look at this code:

 >>> x = 2147483647 >>> type(x) <type 'int'> >>> x = x + 1 >>> type(x)     <type 'long'> >>> x 2147483648L 

Python automatically converts ints to longs whenever it overflows.

Longs

Python's long datatype is completely different from the long type of C++'s, however. C++ longs are usually 32 bits (depending on the compiler), but Python's longs are special integers that can have huge values. Look at this code for a moment, continuing from earlier:

 >>> x 2147483658L >>> x = x * x * x * x * x * x >>> x 98079717355732488831849278277916776199747448861145121344L 

That's a long number! Maybe that's where the name came from. Here, try it again:

 >>> x = x * x * x * x * x * x >>> x 890174673224950989224344909339850580102383540379533865907262500120651 398303359571312924055596951783353543195046215952854460786132127336962 202329058079176489889535289368883996834478628657762318330221731693433 323501333648123820496784420013400992680124611633700193823222168845171 934806058016485705467286157362404278885621815714812637741056L 

HOLY CRAP! I love Python. You literally don't have to worry about integer overflows, ever (unless you try passing numbers like this back into C++). I could keep going, but the results could easily be longer than an entire page. I continued playing around, and eventually got a number that overflowed my command window's buffer (11 pages worth, or 25,531 digits), so I can't really say how large the number was, except that it was larger than 25,531 digits.

Floats

Floats in Python are the same as standard 64-bit double s in C++. Because of this, you can represent numbers as large as 2.22507 x 10 308 , or numbers as small as 4.94066 x 10 -324 . Unfortunately, floats do over/underflow. Here's an example of overflow:

 >>> x = 10000000000.0 >>> x = x * x * x * x * x * x * x * x >>> x 1.0000000000000001e+080 >>> x = x * x * x * x * x * x * x * x >>> x 1.#INF 

And underflow:

 >>> x = 1.0 >>> x /= 1e200 >>> x 9.9999999999999998e-201 >>> x /= 1e200 >>> x 0.0 

So be careful if you know you're dealing with floats.

Strings

Strings are very easy to use in Python, as shown by the following code:

 >>> x = "HELLO!" >>> x[3] 'L' >>> x[:3] 'HEL' >>> x[2:] 'LLO!' >>> x[1:4] 'ELL' 

As in C++, you can use the square- bracket operator to access individual characters , but you can use it to do more than that. If you put a colon in front of an index, as in x[:3] , you're telling it to return the first three characters of the string. On the other hand, x[2:] tells it to return every character after index 2 ( assuming indexing starts at 0). Or you could combine the two, and use x[1:4] to return every character from index 1 (inclusive) to index 4 (exclusive). Unfortunately, you can't use this method to change the characters within a string. Instead, you need to re-assign the string.

For example, you can change the character at index 3 like this:

 >>> x = "HELLO!" >>> x = x[:3] + "g" + x[4:] >>> x 'HELgO!' 

It's a little inefficient, but it gets the job done after all. There's an important reason why inline modification of strings isn't allowed. All Python objects are references. If you run this code

 x = "Rutabagas" y = x 

that means that both x and y are pointing to the same string in memory. Modifying one would cause all references to change, and that is a bad thing ¢ . So, you should modify strings by re-assigning them.

Lists

I'm going to keep this section short, since lists aren't used that much when interfacing with the BetterMUD, but you should be aware that they exist. Look at this example:

 >>> x = [ 10, 20, 30, 15 ] >>> x [10, 20, 30, 15] >>> type( x ) <type 'list'> 

In this code snippet x is now a list, which you can use just like a string:

 >>> x[2] 30 >>> x[:2] [10, 20] >>> x[2:] [30, 15] >>> x[1:3] [20, 30] 

It makes sense, doesn't it? A string is really just a list of characters.

But wait, there's more!

 >>> x = [10, "pies", 3.1415926535897932384626433832795] >>> x [10, 'pies', 3.1415926535897931] 

Lists can contain many different kinds of items; they don't have to be homogenous like C++ lists. Using this knowledge, you can easily create tree-like structures:

 >>> x = [ [10,20], [30,40] ] >>> x [[10, 20], [30, 40]] >>> x[0] [10, 20] >>> x[1] [30, 40] 

Pretty cool, huh? The top list contains two lists!

Libraries

Python has a whole slew of built-in libraries called modules that you can use. A module is basically any collection of code within its own .py file.

In order to use a module, you must first import it, like this:

 import math 

And once that's in, you can do things with the contents of the module:

 >>> import math >>> math <module 'math' (built-in)> >>> math.pi 3.1415926535897931 >>> math.e 2.7182818284590451 >>> math.pi + math.e 5.8598744820488378 

Or call functions:

 >>> math.cos( 1 ) 0.54030230586813977 >>> math.cos( math.pi ) -1.0 

There are built-in modules for almost any function you would want to do, ranging from threading, to sockets (so you don't have to build a Socket Library that sucks from scratch), strings, checksums, e-mail (send e-mail from Python! How cool!), compression, file access, random numbers, timers... ah, you know what? Python has almost everythingtoo many modules to list.

Functions

Python supports user -defined functions, and it's really simple syntax. For example, here's a function that computes the Cartesian length of a 3D vector:

 import math def length( x, y, z ):     return math.sqrt( x * x + y * y + z * z ) 

Now you can use it:

 >>> x = length( 2, 2, 1 )  >>> x  3.0 

It's that simple.

Python and Coding Standards

You have to be very careful when using Python. Most other languages use brackets of some sort to tell the compiler about the beginning and end of functions and classes. Python doesn't do that. Instead, Python relies on line indentation. This may seem a little weird at first, but you get used to it, and eventually learn to like it, because it enforces a really clean way of displaying your code.

Look at the following code:

 x = 10 y = 20 if x == 10:     print x     print y x = 30 

The Python language knows that the if-block starting on line 3 ends after print y , because the indenting resets back to the level of the if-statement. If any of the lines inside the block is indented differently, you'll get a syntax error (unless the line is within another nested-block structure).

Try typing this into Python:

 if x == 10:     print x         print y 

You're going to get something that looks like this:

 >>> if x == 10: ...     print x ...         print y   File "<stdin>", line 3     print y     ^ SyntaxError: invalid syntax 

So you need to be very careful about your indenting habits. It works out for the best though. I find myself admiring my Python code for how much better it looks than it would in C++ (blasphemy!). Don't worry, I still love C++. Both languages have their advantages and disadvantages; syntax in C++ just happens to be a downside.

Classes

Python is a pseudo-object-oriented language. It supports objects and inheritance, and on the outside, those features look and act like the C++ concepts of the same kind. Classes exist in Python not because of a special effort on the part of the Python developers, but because the overall design of the language happens to support the idea.

Creating a Class

For starters, let me show you a very simple class:

 class foobar:     x = 10 

And now play around with it:

 >>> y = foobar() >>> y <__main__.foobar instance at 0x008E7020> >>> y.x 10 >>> y.x = 20 >>> y.x 20 

The first line creates a new instance of foobar , and then you toy with its x variable.

Class Variables

What appears to be happening in the preceding code, isn't actually happening ! I'll explain this in a bit, but first let me show you something (assume you execute this code segment after the previous code):

 >>> foobar.x 10 >>> foobar.x = 30 >>> foobar.x 30 >>> y.x 20 

What the heck is going on here?! Isn't foobar a class? How can you access foobar.x , and when you change it, why does y.x remain at 20? This is madness! Madness I tell you!

Okay, it's not that difficult, actually. Look at Figure 17.3.

Figure 17.3. The process of creating an instance and changing the x variable for y and foobar .

graphic/17fig03.gif


When you create a class in Python using the class keyword, it actually creates a new class object , representing that class. When I typed this line into the class definition:

 x = 10 

I was actually saying "this class object, foobar , will have x , an integer that is 10". I wasn't saying "all instances of foobar will have x ". So in the middle panel of Figure 17.3, when you say y.x = 20 , you are trying to assign 20 to the x variable of y , but y doesn't have that! So, when you execute the statement, the program gives y a new variable named x , and sets it to 20.

This brings up a few questions. When you say y.x before you give y an x object, why does it return foobar.x ? The designers of Python wanted to give Python capabilities that are similar to C++'s static variables, so when you do something like this

 class foobar:     x = 10 

you're saying that foobar has a static variable named x , which is equal to 10. When you say y.x (before you accidentally give y an x object), you're telling y to see if it has x . The instance sees that it doesn't have x , so it determines which class it is an instance of, and if that class has an x , it is returned. Look at this code (executed after you accidentally give y an x object):

 >>> y.x 20 >>> y.__class__.x 30 

Ah-ha! We found the x variable of foobar !

Instance Variables

The question remains, however: "How do I give instances their own variables?" There are many ways to do that, and you've already seen one of them, by accidentally giving an instance a variable. There are other ways though. The most common way is to provide the class with an __init__ function (that's four underscores, by the waytwo in front, and two in back):

 >>> class pie: ...     def __init__( self ): ...         self.kind = "Apple" ... >>> p = pie() >>> p.kind 'Apple' 

What the heck is this business of self ?

Think of how C++ class functions work internallythey always pass a pointer to the actual class object into the function. For example

 foo.bar( 10 ); 

is actually interpreted by the compiler as this:

 bar( &foo, 10 ); 

C++ hides the compiler interpretation from you, but Python doesn't bother. The first parameter passed into any Python class function is a reference to the class on which the function is being used.

In C++, you can do something like this:

 void init() {     kind = "Apple"; } 

And the compiler automatically knows that you're referring this->kind . Python does it a little differently, though. If the initialization function looked like this instead

 def __init__( self ):     kind = "Apple" 

Python would think you're creating a new local variable named kind , which would be discarded the moment the function was finished. Later, when you're trying to determine the class of pie, you get an error:

 >>> class pie: ...     def __init__(self): ...         kind = "Apple" ... >>> p = pie() >>> p.kind Traceback (most recent call last):   File "<stdin>", line 1, in ? AttributeError: pie instance has no attribute 'kind' 

Inheritance

The fact that Python classes can inherit from other classes makes your life easier in the long run. The syntax for inheritance is relatively simple as well:

 >>> class superpie( pie ): ...     def isawesome( self ): ...         return "YES!" ... >>> s = superpie() >>> s.isawesome() 'YES!' >>> s.kind 'Apple' 

This example assumes I'm using the non-broken version of the class pie . See how easy it is?

Exceptions

Python has an effective exception system built-in, much like that of C++. It uses classes as exceptions. Here's a simple example of catching an exception:

 >>> try: ...     y = thisdoesntexist ... except: ...     print "EXCEPTION!!!" ... EXCEPTION!!! 

The try block attempts to execute some code, and the except block catches all exceptions.

You can also do specific exception catching:

 >>> try: ...     y = thisdoesntexist ... except OverflowError: ...     print "Overflow Error!" ... except NameError: ...     print "Name Error!" ... Name Error! 

Or you can even grab an instance of the exception object that was thrown:

 >>> try: ...     y = thisdoesntexist ... except Exception, inst: ...     print inst ... name 'thisdoesntexist' is not defined 

Whenever you print an exception instance, it prints a description of what was thrown.

You can also raise your own exceptions:

 >>> try: ...     raise Exception ... except: ...     print "EXCEPTION THROWN!" ... EXCEPTION THROWN 

Packages

Python, by default, looks for .py files from within the directory in your global path . This can get annoying, because you may need a hierarchy of Python scripts in order to have your programs organized in an efficient manner. Because of this, Python has introduced the idea of packages .

Essentially, to create a package of related files, you need to place a bunch of Python scripts into a subdirectory, and place an empty file named __init__.py into that directory.

For example, if I want to create a package named "data", I create a directory named "data", and put a file named __init__.py into it. Once I do that, I can put other .py files such as characters.py in there, and I'll be able to import that module from within Python like this:

NOTE

Python 2.3 even supports putting packages into .zip files.

 import data.characters 

You can recursively apply the same idea to even more subdirectories if you want to, giving you a cool, flexible hierarchy system.

[ LiB ]


MUD Game Programming
MUD Game Programming (Premier Press Game Development)
ISBN: 1592000908
EAN: 2147483647
Year: 2003
Pages: 147
Authors: Ron Penton

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net