{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Python for Everyone!
[Oregon Curriculum Network](http://4dsolutions.net/ocn/)\n",
"\n",
"## Python and JavaScript\n",
"\n",
"JavaScript has been moving [a lot closer to Python](http://worldgame.blogspot.com/2016/10/javascript-for-pythonistas.html), nowadays supporting classes, with a constructor like \\_\\_init\\_\\_ and *this* for *self* within that construct (ES has had *this* for awhile). \n",
"\n",
"Here in a Jupyter Notebook, we have a way to run both JavaScript and Python together.\n",
"\n",
"I'm using source code from [this article](https://medium.freecodecamp.com/a-gentle-introduction-to-data-structures-how-queues-work-f8b871938e64#.l2p002vqt), *A Gentle Introduction to Data Structures: How Queues Work* by Michael Olorunnisola, to show off the similarities between the two languages."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"application/javascript": [
"\n",
"class Queue {\n",
" constructor(){\n",
" this._storage = {};\n",
" this._start = -1; //replicating 0 index used for arrays\n",
" this._end = -1; //replicating 0 index used for arrays\n",
" }\n",
"\n",
" enqueue(val){\n",
" this._storage[++this._end] = val; \n",
" }\n",
"\n",
" dequeue(){\n",
" if(this.size()){ \n",
" let nextUp = this._storage[++this._start];\n",
" delete this._storage[this._start];\n",
"\n",
" if(!this.size()){ \n",
" this._start = -1;\n",
" this._end = -1; \n",
" }\n",
"\n",
" return nextUp;\n",
" }\n",
" }\n",
" \n",
" size(){\n",
" return this._end - this._start;\n",
" }\n",
"} //end Queue\n",
"\n",
"var microsoftQueue = new Queue();\n",
"\n",
"microsoftQueue.enqueue(\"{user: ILoveWindows@gmail.com}\");\n",
"microsoftQueue.enqueue(\"{user: cortanaIsMyBestFriend@hotmail.com}\");\n",
"microsoftQueue.enqueue(\"{user: InternetExplorer8Fan@outlook.com}\");\n",
"microsoftQueue.enqueue(\"{user: IThrowApplesOutMyWindow@yahoo.com}\");\n",
"\n",
"var sendTo = function(s){\n",
" element.append(s + \" gets a Surface Studio
\");\n",
"}\n",
"\n",
"//Function to send everyone their Surface Studio!\n",
"let sendSurface = recepient => {\n",
" sendTo(recepient);\n",
"}\n",
"\n",
"//When your server is ready to handle this queue, execute this:\n",
"while(microsoftQueue.size() > 0){\n",
" sendSurface(microsoftQueue.dequeue());\n",
"}"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%javascript\n",
"\n",
"class Queue {\n",
" constructor(){\n",
" this._storage = {};\n",
" this._start = -1; //replicating 0 index used for arrays\n",
" this._end = -1; //replicating 0 index used for arrays\n",
" }\n",
"\n",
" enqueue(val){\n",
" this._storage[++this._end] = val; \n",
" }\n",
"\n",
" dequeue(){\n",
" if(this.size()){ \n",
" let nextUp = this._storage[++this._start];\n",
" delete this._storage[this._start];\n",
"\n",
" if(!this.size()){ \n",
" this._start = -1;\n",
" this._end = -1; \n",
" }\n",
"\n",
" return nextUp;\n",
" }\n",
" }\n",
" \n",
" size(){\n",
" return this._end - this._start;\n",
" }\n",
"} //end Queue\n",
"\n",
"var microsoftQueue = new Queue();\n",
"\n",
"microsoftQueue.enqueue(\"{user: ILoveWindows@gmail.com}\");\n",
"microsoftQueue.enqueue(\"{user: cortanaIsMyBestFriend@hotmail.com}\");\n",
"microsoftQueue.enqueue(\"{user: InternetExplorer8Fan@outlook.com}\");\n",
"microsoftQueue.enqueue(\"{user: IThrowApplesOutMyWindow@yahoo.com}\");\n",
"\n",
"var sendTo = function(s){\n",
" element.append(s + \" gets a Surface Studio
\");\n",
"}\n",
"\n",
"//Function to send everyone their Surface Studio!\n",
"let sendSurface = recepient => {\n",
" sendTo(recepient);\n",
"}\n",
"\n",
"//When your server is ready to handle this queue, execute this:\n",
"while(microsoftQueue.size() > 0){\n",
" sendSurface(microsoftQueue.dequeue());\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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.\n",
"\n",
"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."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{user: ILoveWindows@gmail.com} gets a Surface Studio\n",
"{user: cortanaIsMyBestFriend@hotmail.com} gets a Surface Studio\n",
"{user: InternetExplorer8Fan@outlook.com} gets a Surface Studio\n",
"{user: IThrowApplesOutMyWindow@yahoo.com} gets a Surface Studio\n"
]
}
],
"source": [
"class Queue:\n",
" \n",
" def __init__(self):\n",
" self._storage = {}\n",
" self._start = -1 # replicating 0 index used for arrays\n",
" self._end = -1 # replicating 0 index used for arrays\n",
" \n",
" def size(self):\n",
" return self._end - self._start\n",
"\n",
" def enqueue(self, val):\n",
" self._end += 1\n",
" self._storage[self._end] = val\n",
"\n",
" def dequeue(self):\n",
" if self.size():\n",
" self._start += 1\n",
" nextUp = self._storage[self._start]\n",
" del self._storage[self._start]\n",
" \n",
" if not self.size(): \n",
" self._start = -1\n",
" self._end = -1\n",
" return nextUp\n",
" \n",
"microsoftQueue = Queue()\n",
"\n",
"microsoftQueue.enqueue(\"{user: ILoveWindows@gmail.com}\")\n",
"microsoftQueue.enqueue(\"{user: cortanaIsMyBestFriend@hotmail.com}\")\n",
"microsoftQueue.enqueue(\"{user: InternetExplorer8Fan@outlook.com}\")\n",
"microsoftQueue.enqueue(\"{user: IThrowApplesOutMyWindow@yahoo.com}\") \n",
"\n",
"def sendTo(recipient):\n",
" print(recipient, \"gets a Surface Studio\")\n",
"\n",
"# Function to send everyone their Surface Studio!\n",
"def sendSurface(recepient):\n",
" sendTo(recepient)\n",
"\n",
"# When your server is ready to handle this queue, execute this:\n",
"\n",
"while microsoftQueue.size() > 0:\n",
" sendSurface(microsoftQueue.dequeue())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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.\"\n",
"\n",
"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."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"application/javascript": [
"var sendTo = function(s){\n",
" element.append(s + \"
\");\n",
"}\n",
"\n",
"//Function to send everyone their Surface Studio!\n",
"let sendSurface = recepient => {\n",
" sendTo(recepient);\n",
"}\n",
"\n",
"function recipe(ingredient0, ingre1, ing2, ...more){\n",
" sendSurface(ingredient0 + \" is one ingredient.\");\n",
" sendSurface(more[1] + \" is another.\");\n",
"}\n",
"recipe(\"shrimp\", \"avocado\", \"tomato\", \"potato\", \"squash\", \"peanuts\");"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%javascript\n",
"var sendTo = function(s){\n",
" element.append(s + \"
\");\n",
"}\n",
"\n",
"//Function to send everyone their Surface Studio!\n",
"let sendSurface = recepient => {\n",
" sendTo(recepient);\n",
"}\n",
"\n",
"function recipe(ingredient0, ingre1, ing2, ...more){\n",
" sendSurface(ingredient0 + \" is one ingredient.\");\n",
" sendSurface(more[1] + \" is another.\");\n",
"}\n",
"recipe(\"shrimp\", \"avocado\", \"tomato\", \"potato\", \"squash\", \"peanuts\");"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('tomato', 'potato')\n",
"{'dessert': 'peanuts'}\n"
]
}
],
"source": [
"def recipe(ingr0, *more, ingr1, meat=\"turkey\", **others):\n",
" print(more)\n",
" print(others)\n",
" \n",
"recipe(\"avocado\", \"tomato\", \"potato\", ingr1=\"squash\", dessert=\"peanuts\", meat = \"shrimp\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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.\n",
"\n",
"You'll see the sequence parameter **\\*more** begets a tuple with its contents, whereas the dict parameter **\\*\\*others** begets a dict."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.1"
},
"widgets": {
"state": {},
"version": "1.1.2"
}
},
"nbformat": 4,
"nbformat_minor": 0
}