Skip to content

Latest commit

 

History

History
91 lines (73 loc) · 7.88 KB

robot-simulator.md

File metadata and controls

91 lines (73 loc) · 7.88 KB

Concepts of robot-simulator

Example implementation

From the current example.py:

NORTH, EAST, SOUTH, WEST = range(4)


class Compass:
    compass = [NORTH, EAST, SOUTH, WEST]

    def __init__(self, direction=NORTH):
        self.direction = direction

    def left(self):
        self.direction = self.compass[self.direction - 1]

    def right(self):
        self.direction = self.compass[(self.direction + 1) % 4]


class Robot:
    def __init__(self, direction=NORTH, x=0, y=0):
        self.compass = Compass(direction)
        self.x = x
        self.y = y

    def advance(self):
        if self.direction == NORTH:
            self.y += 1
        elif self.direction == SOUTH:
            self.y -= 1
        elif self.direction == EAST:
            self.x += 1
        elif self.direction == WEST:
            self.x -= 1

    def turn_left(self):
        self.compass.left()

    def turn_right(self):
        self.compass.right()

    def move(self, commands):
        instructions = {'A': self.advance,
                        'R': self.turn_right,
                        'L': self.turn_left}
        for cmd in commands:
            if cmd in instructions:
                instructions[cmd]()

    @property
    def direction(self):
        return self.compass.direction

    @property
    def coordinates(self):
        return (self.x, self.y)

Concepts

  • [Constants][constants]: are not enforced by the runtime, but are used via the convention of UPPER_CASE to signal that these values are expected to remain unchanged. Preferably, constants are defined at a module level. The example solution uses the UPPER_CASE convention to define NORTH, SOUTH, EAST, and WEST constants.
  • [Multiple Assignment][multiple-assignment]: Python allows multiple assignment, assigning the items on the left of = in order to the values on the right of = by forming tuples and then "unpacking" them. This exercise solution uses multiple assignment for the constant values NORTH, EAST, SOUTH, WEST.
  • [Range][range]: the range() built-in type represents an immutable sequence of numbers (or any object that implements the __index__ dunder method). Used in the example to represent the values from zero to 3 as assigned to NORTH, EAST, SOUTH, WEST.
  • [Class][class]: the exercise objective is to define a robot type. Tested methods are linked to a robot class.
  • [Instantiation][instantiation]: creating different instances of the robot class with different data representing different starting positions and bearing are tested.
  • [Initialization][initialization]: customizing object instantiation with actions and persisting data. The example uses __init__ to persist a compass object and x, y coordinates assigned to instance attributes.
  • [Return Value][return-value]: knowing that functions need not have explicit return statements or values but will return None if return is not specified. Except for the two @property-decorated functions, all of the functions in the example omit an explicit return statement and all return None.
  • [Implicit Argument][implicit-argument]: the example uses self for methods and properties linked to a specific instance of the class.
  • [Namespaces][namespaces]: knowing to use self.<propertyname> for instance attributes and self as first argument to instance methods in a class. Additionally, the example uses self.<methodname>() to call a previously stored method name.
  • [Instance Methods][instance-methods]: tests for this exercises require one or more instance methods that will take in a set of starting coordinates and a bearing and then accept a series of instructions that "move" the instance to a new set of coordinates and bearing.
  • [Function Decorator][function-decorator]: a higher-order function that takes another function as an argument. The "decorating" function extends the behavior of the "decorated" function without explicitly modifying it (i.e. it wraps or decorates it). Called in python by using the @ symbol and the function name ahead of the function being decorated. The example uses pythons built-in property() as a decorator (@property) to return a "compound" read-only instance property made up of two separate instance attributes.
  • [Higher-Order Function][higher-order-function]: a function that takes one or more other functions as arguments, returning a function as its return value. The example uses the built-in property() as a higher-order function through @property.
  • [Property][property]: the property() built-in is a function that returns a property attribute. When used as a decorator, this transforms the passed-in method into a getter method for read-only attribute with the same name and docstring.
  • [Assignment][assignment]: the example uses assignment for all the instance properties and instructions dictionary.
  • [Instance Attributes][instance-attributes]: this exercise requires one or more instance attributes to persist passed in data.
  • [Mutability][mutability]: in the example, knowing there are no protected or private properties in python and so consciously mutating self.x, self.y and self.compass through the called instance methods.
  • [Method Parameters][method-parameters]: the example __init__ method has self, direction, x, and y (coordinates) as parameters. It also uses self and commands (a string) for parameters of the move() method.
  • [Default Arguments][default-arguments]: pre-setting function arguments to protect against them not being passed by a caller. The example uses direction = NORTH and x=0, y=0 to ensure those values for a robot even if they are not initially passed.
  • [Dictionary][dictionary]: the example uses a dictionary to map passed in move arguments to methods that perform the moves. The example also uses a dictionary/mapping created by calling str.maketrans().
  • [Indexing][indexing]: finding a value by key in a dictionary using <dictionary name>[<key name>] The example uses passed in move arguments as keys to look up corresponding values (method names) for moving the robot in the instructions dictionary.
  • [Iteration][iteration]: the example uses a for loop to iterate through the letters of the passed-in commands string and looks up the corresponding values in a dictionary, so that the appropriate methods can be called to move the robot.
  • [Composition][composition]: adding functionality from a class by incorporating an instance of that class in a class you are creating. The example creates a robot by instantiating a compass and assigning it to the self.compass attribute of robot.
  • [Modular Division][modular-division]: the example uses the modulus operator to calculate the appropriate compass setting when calling the right compass method
  • [Lists][lists]: the example stores compass direction constants in a list
  • [Call Semantics][call-semantics]: knowing that appending () to the name of an instance method calls it, since instance methods are callable.
  • [Equality Operator][equality-operator]: the == operator calls the dunder method __eq__(). By default, objects of different types are never considered equal to each other unless they are numerical types (ie int, float) or have otherwise overloaded the default implementation of the __eq__ dunder method. == is always defined, but for some object types (like class objects) it is equivalent to calling is. See [__eq__](https: //docs.python.org/3/reference/datamodel.html#object.eq) for additional details. This exercise uses the equality operator to test that the self.direction attribute is equal to one of the constant values defined.
  • [Dunder Methods][dunder-methods]: The example uses __init__ as a constructor for the class, which also calls __new__. In addition, the example uses __call__() via the appending of () to instance method names, and __eq__() (rich compairison) via the use of ==