Python

Rosetta.py

# Copyright (c) 2008 Art & Logic, Inc. All Rights Reserved.

# $Id: Rosetta.py,v 1.5 2008/02/05 19:48:39 bporter Exp $ # Above: [sf02], [sf03] # a note on the stuff inside the square brackets: # Each of the codes inside brackets is a reference to the rule(s) in the # Style Guide that's being illustrated, as follows: # [sf##] - StyleGuide/SourceFiles # [cas##] - StyleGuide/ClassesAndStructures # [nr##] - StyleGuide/NamingRules # [cg##] - StyleGuide/Commenting # [fmt##] - StyleGuide/Formatting # Throughout: [fmt01]; all indentation done with space characters (0x20), # three spaces per logical tab stop. class ARosetta: """ A magical, multi-featured class that does many things in a questionable fashion. """ kSomeConstant = 64 kSomeOtherConstant = 90 def __init__(self, fileName): # [nr05] -- Class members in Python may optionally omit the f prefix, # since the language requires that they are accessed by qualifying them # with the current object's self. self.fileName = fileName self.inputFile = open(self.fileName, "r") def close(self): """ close() provided in lieu of C++'s destructor syntax. """ # [fmt32] -- Explicitly check for None, instead of "if self.inputFile" # [fmt33] -- Don't need to explicitly compare to True/False when dealing # with booleans. if self.inputFile is not None and not self.inputFile.closed: self.inputFile.close() def MemberFunctionWithMultipleWords(self): """ Demonstrates various code constructs. """ for i in range(self.kSomeConstant): for j in range(self.kSomeOtherConstant): """ !!! No pre-processor in Python. // [fmt02] -- preprocessor directives go in column zero. #ifdef qVerbose std::clog << "testing: " << i << ", " << j << std::endl; #endif """ # [nr07] -- Calls to member functions of the current object are # made through an explicit "this" keyword ("self" in Python). ok = self.Test(i, j) # [fmt33] -- No need to explicitly compare to True/False when # dealing with booleans. if not ok: print "Fatal error testing %d, %d" % (i, j) return False return True def LongLineWrapping(self): """ Demonstrates code line wrapping. """ retval = False # [fmt03] -- source lines should be less than 80 characters long. # [fmt04] -- break lines at the most logical point # 1 2 3 4 5 6 7 # 34567890123456789012345678901234567890123456789012345678901234567890123456789 retval = FunctionWithManyArguments(longArgumentName1, longArgumentName2, longArgumentName3, longArgumentName4) # alternative format #1 retval = FunctionWithManyArguments(longArgumentName1, longArgumentName2, longArgumentName3, longArgumentName4) # alternative format #2 retval = FunctionWithManyArguments( longArgumentName1, longArgumentName2, longArgumentName3, longArgumentName4) # [fmt05] -- prefer to break after a comma retval = anObject.SomeUsefulFunction(x.LeftMargin() + x.RightMargin(), x.TopMargin() + x.BottomMargin() - 1) # [fmt05] -- if that's not possible, break after an operator retval = anObject.SomeUsefulFunction(x.LeftMargin() + x.RightMargin() + anObject.HorizontalPadding(), x.TopMargin() + x.BottomMargin() - 1) return retval def Loops(self): """ Demonstrates various looping constructs. """ # !!! Python has no "for (init; test; increment)" construct. for i in xrange(self.kSomeConstant): SomeCodeHere(i) # [fmt09] while someBoolean: someBoolean = SomeFunctionCall() # [fmt09] # In Python, use pass statement to indicate an empty block. while self.SomeFuncReturningBool(): pass # $$$ Python has no "do-while" syntax. # [fmt10] -- do/while loop. # [fmt18] -- exception to the bracing rule saying that braces should # always be on a line by themselves #do #{ # // loop code here... #} while (someBoolean); # $$$ end def Test(self, firstVal, secondVal): """ Determines whether the two variables are acceptable. """ retval = True # [fmt07] -- if/else formatting if firstVal < secondVal: # [cg06] -- use '$$$' as a marker to indicate a request that the # following block of code be reviewed before a change is considered # complete # $$$ before # self.Process(secondVal) # $$$ after # Shouldn't this be processing the first value in this case? self.Process(firstVal) # $$$ end elif secondVal > self.kSomeConstant: self.Process(secondVal) else: retval = False return retval # Use two underscores to simulate private members in Python: def __Process(self, val): """ Executes a process. """ result = val # Python has no increment/precrement operators. while True: val -= 1 if 0 == val: break result *= val self.processResult = result def __Decide(self, midiEventType): """ Decides what to do with event described by midiEventType argument. """ # Python has no switch/case mechanism, so we either use if/elif/else or # build some other mechanism with dictionaries. # [fmt34] -- Place constant value on left side of equivalence tests. if kNoteOn == midiEventType: self.NoteOn(now) if duration > 0: self.NoteOff(now + duration) elif kNoteOff == midiEventType: self.NoteOff(now) elif kPolyAfter == midiEventType: after = channelValue elif kChannelAfter == midiEventType: self.AfterTouch(after) elif kPitchBend == midiEventType: pass else: assert False, "Unsupported event type!" self.LogError("Unsupported event type!")