Python for Everyone!
Oregon Curriculum Network

Python and JavaScript

JavaScript has been moving a lot closer to Python, nowadays supporting classes, with a constructor like __init__ and this for self within that construct (ES has had this for awhile).

Here in a Jupyter Notebook, we have a way to run both JavaScript and Python together.

I'm using source code from this article, A Gentle Introduction to Data Structures: How Queues Work by Michael Olorunnisola, to show off the similarities between the two languages.


In [4]:
%%javascript

class Queue {
  constructor(){
    this._storage = {};
    this._start = -1; //replicating 0 index used for arrays
    this._end = -1; //replicating 0 index used for arrays
  }

  enqueue(val){
    this._storage[++this._end] = val; 
  }

  dequeue(){
    if(this.size()){ 
      let nextUp = this._storage[++this._start];
      delete this._storage[this._start];

      if(!this.size()){ 
        this._start = -1;
        this._end = -1; 
      }

      return nextUp;
    }
  }
        
  size(){
   return this._end - this._start;
  }
} //end Queue

var microsoftQueue = new Queue();

microsoftQueue.enqueue("{user: ILoveWindows@gmail.com}");
microsoftQueue.enqueue("{user: cortanaIsMyBestFriend@hotmail.com}");
microsoftQueue.enqueue("{user: InternetExplorer8Fan@outlook.com}");
microsoftQueue.enqueue("{user: IThrowApplesOutMyWindow@yahoo.com}");

var sendTo = function(s){
    element.append(s + " gets a Surface Studio<br />");
}

//Function to send everyone their Surface Studio!
let sendSurface = recepient => {
   sendTo(recepient);
}

//When your server is ready to handle this queue, execute this:
while(microsoftQueue.size() > 0){
  sendSurface(microsoftQueue.dequeue());
}


If you don't see four lines of output above, you might be rendering this on Github. If you want to see the output, same as the Python output below, cut and paste the Github URL to nbviewer.jupyter.org, which will do a more thorough rendering job.

Now lets do the same thing in Python. Yes, Python has it's own collections.deque or we could use a list object as a queue, but the point here is to show off similarities, so lets stick with a dict-based implementation, mirroring the JavaScript.


In [2]:
class Queue:
    
    def __init__(self):
        self._storage = {}
        self._start = -1   # replicating 0 index used for arrays
        self._end = -1     # replicating 0 index used for arrays
        
    def size(self):
        return self._end - self._start

    def enqueue(self, val):
        self._end += 1
        self._storage[self._end] = val

    def dequeue(self):
        if self.size():
            self._start += 1
            nextUp = self._storage[self._start]
            del self._storage[self._start]
    
            if not self.size(): 
                self._start = -1
                self._end = -1
            return nextUp
        
microsoftQueue = Queue()

microsoftQueue.enqueue("{user: ILoveWindows@gmail.com}")
microsoftQueue.enqueue("{user: cortanaIsMyBestFriend@hotmail.com}")
microsoftQueue.enqueue("{user: InternetExplorer8Fan@outlook.com}")
microsoftQueue.enqueue("{user: IThrowApplesOutMyWindow@yahoo.com}") 

def sendTo(recipient):
    print(recipient, "gets a Surface Studio")

# Function to send everyone their Surface Studio!
def sendSurface(recepient):
   sendTo(recepient)

# When your server is ready to handle this queue, execute this:

while microsoftQueue.size() > 0:
  sendSurface(microsoftQueue.dequeue())


{user: ILoveWindows@gmail.com} gets a Surface Studio
{user: cortanaIsMyBestFriend@hotmail.com} gets a Surface Studio
{user: InternetExplorer8Fan@outlook.com} gets a Surface Studio
{user: IThrowApplesOutMyWindow@yahoo.com} gets a Surface Studio

Another example of features JavaScript is acquiring with ES6 (Sixth Edition we might call it), are rest and default parameters. A "rest" parameter has nothing to do with RESTful, and everything to do with "the rest" as in "whatever is left over."

For example, in the function below, we pass in more ingredients than some recipe requires, yet because of the rest argument, which has to be the last, the extra ingredients are kept. Pre ES6, JavaScript had no simple mechanism for allowing parameters to "rise to the occasion." Instead they would match up, or stay undefined.


In [12]:
%%javascript
var sendTo = function(s){
    element.append(s + "<br />");
}

//Function to send everyone their Surface Studio!
let sendSurface = recepient => {
   sendTo(recepient);
}

function recipe(ingredient0, ingre1, ing2, ...more){
    sendSurface(ingredient0 + " is one ingredient.");
    sendSurface(more[1] + " is another.");
}
recipe("shrimp", "avocado", "tomato", "potato", "squash", "peanuts");


In Python we have both sequence and dictionary parameters, which we could say are both rest parameters, one for scooping up positionals, the other for gathering the named. Here's how that looks:


In [18]:
def recipe(ingr0, *more, ingr1, meat="turkey", **others):
    print(more)
    print(others)
    
recipe("avocado", "tomato", "potato", ingr1="squash", dessert="peanuts", meat = "shrimp")


('tomato', 'potato')
{'dessert': 'peanuts'}

Thanks to *more being a sequence parameter, the parameter ingr1 may only be reached with a named argument, yet need have no default value. **others scoops up anything named that doesn't match anything explicitly required as such.

You'll see the sequence parameter *more begets a tuple with its contents, whereas the dict parameter **others begets a dict.