RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Introducing IronPython : Page 2

IronPython is an easy-to-learn yet surprisingly powerful language for .NET development. Find out how it differs from C# and Visual Basic while still leveraging your existing .NET knowledge.

Dynamic Typing
While significant whitespace is the most obvious difference between Python and C#/VB, the biggest difference between them lies in the type system. Python shares many high-level concepts with these .NET languages, such as imperative code, functions, classes, and objects. However, C# and VB are statically typed, which means that these languages fix the capabilities of individual types at compile time. After you determine the fields, properties, and methods of your type and run the code through the compiler, those capabilities can never change, ever. If you need to change them, your only option is to throw away your original compiled binary and recompile a new one.

Dynamic typing, on the other hand, does not fix type capabilities at compile time. Rather, types are completely mutable and you can manipulate them at run time in much the same way that you have manipulated type instances in the past. For example, at runtime, you can create new types, add fields or methods to a type, remove fields or methods from a type, add fields or methods to a specific instance of a type, or even change the inheritance hierarchy of a type.

If you come from a static type language background, the idea of being able to manipulate types at run-time may seem strange, or even dangerous. Static advocates typically highlight type safety as one of the primary benefits of using static typing. When using static types, the compiler can do quite a bit of validation to ensure that the types you create and the methods you call all exist, that the fields and parameters are of the right types, etc. We've all had to fix compiler errors because we misspelled a method or type name. But that's not possible in dynamic languages; instead, In Python, such errors become run-time exceptions.

However, I'd like to put this type safety benefit in perspective. In any system of significant scale, there are essentially an infinite number of ways the application can be wrong. Type safe languages eliminate just one of this infinite number of ways. But that still means that a static language compiler won't catch the overwhelming majority of errors and bugs you might make when developing your system. If it could, then all successfully-compiled applications would automatically be bug free! The fact is, you need some other mechanism to catch these other errors, typically automated unit tests. So while it's true that static types do provide a safety net, it's just not a very big one.

This isn't to say type safe languages are bad. Rather, I look at it as a tradeoff of static type safety vs. dynamic type flexibility. There is no universally right decision—only the right decision for you and your project. The good news is that with the addition of dynamic languages like IronPython to Microsoft's language stable, you can make that tradeoff decision while still staying in the .NET realm.

Refreshing Simplicity
One somewhat frustrating aspect of C# is the amount of structure that gets forced on the developer. Some of this structure is related to static typing, such as specifying variable types and casting operators. However, there are also no stand-alone functions in C#, much less just a bunch of code in a simple script. All functions have to be attached to an object, meaning the simplest possible implementation of "Hello, World!" in C# looks like this:

   class Program
     static void Main()
         System.Console.WriteLine("Hello, World");
Contrast that with the Python version:

   print "Hello, World"
Obviously, you don't judge a language completely by its implementation of "Hello, World," but the real point is that Python scales well with complexity. If you need only a simple script, you don't have to add unneeded class and function constructs for the code to live inside. If you want to make a function, it can stand alone; you don't need to find a class to attach it to (such as the bubble_sort example above). If you really need classes and objects, you can build them, but you don't have to take on that complexity unless you really need it.

Polymorphic Mallards
Polymorphism—the ability to treat different types the same way—is a staple of object-oriented programming. Statically typed languages have a variety of mechanisms designed to enable polymorphism, including inheritance, interfaces and generics. Because Python is dynamically typed, it doesn't need any of these mechanisms to provide polymorphism. (Python does support inheritance, but not to enable polymorphism.) Instead, Python determines type compatibility at run time based on the type's capabilities rather than on the declared types (a process commonly known as "duck typing"). This feature enables code that's more flexible and reusable in a wider variety of situations.

To see this in action, revisit the bubble_sort function shown earlier. It takes a single parameter, ar, which represents the collection to sort. A closer look shows that there the object instance ar must have three capabilities to be compatible with the bubble_sort function:

  1. You must be able to ask the ar object for its length.
  2. You must be able to get items in the ar object by numeric index.
  3. You must be able to set items in the ar object by numeric index.
To write the equivalent bubble sort method in C#, you would have had to declare the ar parameter as a specific type—either an interface or a base class—that implements the capabilities listed above. The C# compiler would validate that any code that called bubble sort would pass a parameter that implements that parameter type. Passing any other type as a parameter would result in a compile error, even if the type in question implemented all the required capabilities.

Because Python does all the type checking at run time, so if the type instance passed in as the ar parameter is missing an implementation of one of the three methods listed above, Python will throw a TypeError when it executes the bubble sort code. For the bubble sort code, the three required methods have special names: __len__ returns the length of the collection, while __getitem__ and __setitem__ get and set values by index, respectively. Python defines quite a few special names useful in a variety of circumstances.

Here's an example of a custom linked list class that implements these methods and is thus compatible with the bubble sort code above.

   class linked_list(object):
   class node(object):
   def __init__(self,value):
       self.data = value
       self.next = None
   def __init__(self):
       self.head = None
   def insert(self, value):
       n = linked_list.node(value)
       n.next = self.head
       self.head = n
   def __iter__(self):
       cur = self.head
   while cur != None:
       yield cur
       cur = cur.next
   def __len__(self):
       count = 0
   for n in self:
       count += 1
   return count
   def find_node(self, key):
       cur = self.head
   for x in range(key):
       cur = cur.next
   return cur
   def __getitem__(self, key):
   return self.find_node(key).data
   def __setitem__(self, key, value):
       self.find_node(key).data = value
Of course, linked lists don't usually provide indexed access to their members. But the point is that because this custom class implements __len__, __getitem__ and __setitem__, you can pass an instance of this class to the bubble_sort function without any changes at all.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date