[Tutor] Here's something to talk about
Paul McGuire
ptmcg at austin.rr.com
Thu Apr 16 02:35:27 CEST 2009
Ronald -
I really encourage you to try to embrace some of the basic Python idioms as
part of your Java->Python journey:
1. Iterators
for item in list_of_items:
# do something with item
Is all that is needed to visit each item in a Python list. Your verbose
MoveFirst, MoveNext, if more <> None, etc. is completely subsumed into the
built-in machinery Python has for iterators. (4-space source indent is also
the norm.)
2. Static typing
Change that snippet to:
def visit_each_item(collection):
for item in collection:
# do something with item, like printing its name
And this code works for lists, tuples, and sets of items, or dicts with
items as keys (assuming an item is hashable). (The old method would accept
non-lists, too, but naming a parameter 'list_of_items' sounds like only
lists are intended.) And the items in the list/tuple/set/whatever don't
even have to be all the same type, as long as they all support the concept
of "doing something". Such as:
def print_each_items_name(collection):
for item in collection:
print item.name
The Java approach is to define an interface called Nameable (or INameable?),
with methods GetName and SetName.
You want to talk about self-maintaining code? I wrote code like this before
sets were even added to the language definition, and when this new data type
came along, my code library handled it without changing a single line! Good
thing that I didn't try to hack in some hare-brained run-time type safety
like:
if isinstance(collection,(list,tuple,dict)):
for item in collection:
... blah blah...
Or I would have to chase down all such code and add 'set' to the list.
3. Interfaces
Interfaces are there to allow compilers to verify that a static data type
will comply with an interface's requirements at runtime. Python skips this
and just does the runtime check - if the object does not have the necessary
attribute (and methods are just callable attributes), then an AttributeError
gets thrown. If you have a design that calls for inheritance from a pure
virtual abstract base class, then in Python, that base class is completely
unnecessary. Sometimes in my code I will still include such a base class,
for purposes of documentation or to help me remember later what the heck was
I thinking? But such a thing is for my benefit, not Python's.
4. Getters and Setters
This is such a fundamental dogma for Java developers that it may be
difficult for you to let go. But do so, please! Assume that rootTag in
your XMLExporter is a public variable, which you later must change to a
method call (maybe to ensure that the given tag is actually a kosher XML tag
string, and not something like "123$#!@^^!!!") - this is where the Python
property allows you to map set and get access to an attribute through a pair
of methods, while external code continues to access the property by its
public name, "rootTag". No additional refactoring or recoding or
recompiling necessary. Meanwhile, you can trim significant fat of "just in
case I need to make this a method someday" code from your classes, and just
use the attributes directly.
5. New concepts in Python
Python has some exciting features related to its built-in support for
collections that makes creating and working with them a dream. Read up on
list comprehensions, generator expressions, iterators, and generators. You
won't need them right away, but the sooner you get them, the sooner you'll
be able to dump verbose (and slow!) code like:
return_list = []
for blah in somecollection:
return_list.append(something_about(blah))
and write:
return_list = [something_about(blah) for blah in somecollection]
Not only is this more compact and concise, it also runs faster. Also, learn
about zip and itertools - these will make your programs just fly.
Please try to hold off on the Newbie's Hubris. The code that you posted
doesn't really present anything novel, or particularly awesome. Instead,
think about this:
class ApplicationClass(object):
# objects of this class have no attributes - yet!
pass
def makeExportable(obj, exporter):
obj.exporter = exporter
a = ApplicationClass()
makeExportable(a, SQLExporter)
Now I have added exportability to an instance, without changing the class at
all. This might even be a class from a 3rd party lib, whose source code I
don't even have!
Welcome to Python, but check your Java baggage at the door!
-- Paul
More information about the Tutor
mailing list