A class defintion creates an object of type class. By convention, class names are in CapitalCase (see PEP 8: Style Guide for Python Code)
class MachineZero: # body of class indented
A def statement created an object of type function or method.
def get_state(self): # body of function or method
self.current_state = 'A'
A list object is of type list, and it is a mutable sequence. A sequence can be iterated (used in a for construct, e.g.)
self.states = ['A','B'] self.start_state = self.states[0] # if by default 0th state is the start state
if message == 'a': # body of the if statement
return self.current_state
The indented block is run repeatedly, each time with the variable bound to the next value provided by the sequence object. A list is sequence object, and it provides in turn the elements in the list, in index order. A string is a sequence object, of type str. It provides a sequence of length one strings, the "characters" in the string in index order. (There is no character type in Python)
for m in test_string: # body of the for statement
It uses parenthesis and comma separated elements for initialization. A one element tuple uses a comma following the only element to distinguish it from simply an token enclosed (gratuitously) in parenthesis.
# a list of tuples to represent case, in the language (True) and not in # language for various strings [('',False), ('01',True), ('10',False)]
It shares the syntax of a list for access and update. It uses braces for initialization, and a comma separated sequence of key:value pairs, where the colon character is appears literally.
# a dictionary gives the transition function for a DFA {('A','a'):'A', ('A','b'):'B', ('B','a'):'B', ('B','b'):'B'} # it can be accessed by creating a state-letter pair, and using brackets # to index into the transitions dictionary self.current_state = self.transitions[(self.current_state,letter)]
Recall that in is also used, without evident relationship, in the syntax of the for construct.
# using the in keyword to see if the current state is one of the # final states, and return True or False accordingly return self.current_state in self.accept_states
Among the following blocks introduced with the except keyword, followed optionally by a type name, that block will be activated if there is a type match between the mentioned type and the type of the exception. Only one except block will be activated, and it will be the first matching block in the order that the blocks are positioned in the code.
If no except block matches, the exception is unhandled and will cause the program to terminate.
An else block is introduced with keyword else and must follow all except blocks. It is run only if there is no exception raised. It can be differentiated from placing the else block code inside the try block, in that it is not controlled by the try. It can be differentiated from placing the eles block code following the entire try construct in that is is not run if an exception is raised.
A finally block introduced with keyword finally is always run after the try, any exception or else blocks.
try: # if an exception is raised while inside this code block, # go immediately to an except clause to handle the exception tm = TestMachine(dfa_md[i]) if tm.run(dfa_test[i]): correct += 1 except Exception as exception: # run this block on exception. Afterwards continue # on with the code. # The type of the exception will give a good idea of what was # the problem. For instance, class 'KeyError' means indeed the # transition function was faulty. print("\n*** exception thrown:", str(type(exception)))
A set and frozenset do not support any sequence operations, however it is iterable, i.e. can be used in a for construct, with an unspecified order of the elements. While the elements must be hashable, a set is not hashable. A frozen set is hashable.
A set is created either with the set constructor, which takes a single argument, that can be a list, or using curly braces listing comma separated elements, or using the comprehension construct, enclosed in curly braces.
A frozenset must use the frozenset() constructor.
Sets are useful in that they support the tradition set operations, among them:
A set, but not a frozen set, also supports updates including such things as &=, &hat;=, add, remove, etc.
I make a lot of use of asserts in all my code. In production code, the asserts need to be removed. In C the assert is a macro and can be removed by recompiling with the assert macro no-op'ed. In Python, the exception can be caught.
For the purposes of classroom work, however, it provides a quick way to double check one's logic, to document cases of work to-do, or work that seems out of scope of the project aim, without producing code that is complacently incorrect.
author: burton rosenberg
created: 26 jan 2021
update: 19 feb 2021