{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction to Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This page demonstrates some basic Python concepts and essentials. See the Python Tutorial and Reference for more exhaustive resources.\n", "

This page provides a brief introduction to:

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Displaying results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following command simply prints \"Hello world!\". Run it, and then re-evaluate with a different string." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.504002Z", "iopub.status.busy": "2025-08-18T03:35:52.503855Z", "iopub.status.idle": "2025-08-18T03:35:52.511507Z", "shell.execute_reply": "2025-08-18T03:35:52.511129Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello world!\n" ] } ], "source": [ "print(\"Hello world!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here print is a function that displays its input on the screen." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use a string's format method with {} placeholders to substitute calculated values into the output in specific locations; for example:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.576248Z", "iopub.status.busy": "2025-08-18T03:35:52.576052Z", "iopub.status.idle": "2025-08-18T03:35:52.582094Z", "shell.execute_reply": "2025-08-18T03:35:52.581678Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3 + 4 = 7. Amazing!\n" ] } ], "source": [ "print(\"3 + 4 = {}. Amazing!\".format(3 + 4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiple values can be substituted:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.583566Z", "iopub.status.busy": "2025-08-18T03:35:52.583422Z", "iopub.status.idle": "2025-08-18T03:35:52.588501Z", "shell.execute_reply": "2025-08-18T03:35:52.588140Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The length of the apical dendrite is 100 microns.\n" ] } ], "source": [ "print(\"The length of the {} is {} microns.\".format(\"apical dendrite\", 100))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are more sophisticated ways of using format\n", "(see examples on the Python website)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Variables: Strings, numbers, and dynamic type casting" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variables are easily assigned:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.590019Z", "iopub.status.busy": "2025-08-18T03:35:52.589879Z", "iopub.status.idle": "2025-08-18T03:35:52.593472Z", "shell.execute_reply": "2025-08-18T03:35:52.593131Z" } }, "outputs": [], "source": [ "my_name = \"Tom\"\n", "my_age = 45" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let’s work with these variables." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.596011Z", "iopub.status.busy": "2025-08-18T03:35:52.595866Z", "iopub.status.idle": "2025-08-18T03:35:52.601426Z", "shell.execute_reply": "2025-08-18T03:35:52.599141Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tom\n" ] } ], "source": [ "print(my_name)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.603060Z", "iopub.status.busy": "2025-08-18T03:35:52.602904Z", "iopub.status.idle": "2025-08-18T03:35:52.605970Z", "shell.execute_reply": "2025-08-18T03:35:52.605628Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "45\n" ] } ], "source": [ "print(my_age)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Strings can be combined with the + operator." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.608935Z", "iopub.status.busy": "2025-08-18T03:35:52.608792Z", "iopub.status.idle": "2025-08-18T03:35:52.613505Z", "shell.execute_reply": "2025-08-18T03:35:52.613137Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, Tom\n" ] } ], "source": [ "greeting = \"Hello, \" + my_name\n", "print(greeting)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let’s move on to numbers." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.615165Z", "iopub.status.busy": "2025-08-18T03:35:52.615022Z", "iopub.status.idle": "2025-08-18T03:35:52.619360Z", "shell.execute_reply": "2025-08-18T03:35:52.619011Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "45\n" ] } ], "source": [ "print(my_age)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you try using the + operator on my_name and my_age:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "print(my_name + my_age)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

You will get a TypeError. What is wrong?

\n", "

my_name is a string and my_age is a number. Adding in this context does not make any sense.

\n", "

We can determine an object’s type with the type() function.

" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.621177Z", "iopub.status.busy": "2025-08-18T03:35:52.621032Z", "iopub.status.idle": "2025-08-18T03:35:52.631640Z", "shell.execute_reply": "2025-08-18T03:35:52.631287Z" } }, "outputs": [ { "data": { "text/plain": [ "str" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(my_name)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.633144Z", "iopub.status.busy": "2025-08-18T03:35:52.633000Z", "iopub.status.idle": "2025-08-18T03:35:52.638509Z", "shell.execute_reply": "2025-08-18T03:35:52.638202Z" } }, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(my_age)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The function isinstance() is typically more useful than comparing variable types as it allows handling subclasses:

" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.640281Z", "iopub.status.busy": "2025-08-18T03:35:52.640138Z", "iopub.status.idle": "2025-08-18T03:35:52.646848Z", "shell.execute_reply": "2025-08-18T03:35:52.646503Z" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "isinstance(my_name, str)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.648918Z", "iopub.status.busy": "2025-08-18T03:35:52.648325Z", "iopub.status.idle": "2025-08-18T03:35:52.654463Z", "shell.execute_reply": "2025-08-18T03:35:52.654125Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The variable is None!\n" ] } ], "source": [ "my_valid_var = None\n", "if my_valid_var is not None:\n", " print(my_valid_var)\n", "else:\n", " print(\"The variable is None!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Arithmetic: +, -, *, /, **, % and comparisons" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.656037Z", "iopub.status.busy": "2025-08-18T03:35:52.655899Z", "iopub.status.idle": "2025-08-18T03:35:52.660836Z", "shell.execute_reply": "2025-08-18T03:35:52.660494Z" } }, "outputs": [ { "data": { "text/plain": [ "12" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 * 6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check for equality using two equal signs:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.662264Z", "iopub.status.busy": "2025-08-18T03:35:52.662124Z", "iopub.status.idle": "2025-08-18T03:35:52.669749Z", "shell.execute_reply": "2025-08-18T03:35:52.669409Z" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 * 6 == 4 * 3" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.673050Z", "iopub.status.busy": "2025-08-18T03:35:52.672905Z", "iopub.status.idle": "2025-08-18T03:35:52.682676Z", "shell.execute_reply": "2025-08-18T03:35:52.680529Z" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 < 2" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.688836Z", "iopub.status.busy": "2025-08-18T03:35:52.685904Z", "iopub.status.idle": "2025-08-18T03:35:52.695634Z", "shell.execute_reply": "2025-08-18T03:35:52.695297Z" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 < 2 or 3 < 5" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.701333Z", "iopub.status.busy": "2025-08-18T03:35:52.700764Z", "iopub.status.idle": "2025-08-18T03:35:52.708623Z", "shell.execute_reply": "2025-08-18T03:35:52.708286Z" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 < 2 and 3 < 5" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.713841Z", "iopub.status.busy": "2025-08-18T03:35:52.713700Z", "iopub.status.idle": "2025-08-18T03:35:52.722514Z", "shell.execute_reply": "2025-08-18T03:35:52.721043Z" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 * 3 != 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "% is the modulus operator. It returns the remainder from doing a division." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.728492Z", "iopub.status.busy": "2025-08-18T03:35:52.726009Z", "iopub.status.idle": "2025-08-18T03:35:52.735427Z", "shell.execute_reply": "2025-08-18T03:35:52.735103Z" } }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 % 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above is because 5 / 3 is 1 with a remainder of 2." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In decimal, that is:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.740906Z", "iopub.status.busy": "2025-08-18T03:35:52.740755Z", "iopub.status.idle": "2025-08-18T03:35:52.749594Z", "shell.execute_reply": "2025-08-18T03:35:52.748114Z" } }, "outputs": [ { "data": { "text/plain": [ "1.6666666666666667" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 / 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "

Warning

\n", "

In older versions of Python (prior to 3.0), the / operator when used on integers performed integer division; i.e. 3/2 returned 1, but 3/2.0 returned 1.5. Beginning with Python 3.0, the / operator returns a float if integers do not divide evenly; i.e. 3/2 returns 1.5. Integer division is still available using the // operator, i.e. 3 // 2 evaluates to 1.

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Making choices: if, else" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.755483Z", "iopub.status.busy": "2025-08-18T03:35:52.752914Z", "iopub.status.idle": "2025-08-18T03:35:52.762447Z", "shell.execute_reply": "2025-08-18T03:35:52.760950Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "working on the soma\n" ] } ], "source": [ "section = \"soma\"\n", "if section == \"soma\":\n", " print(\"working on the soma\")\n", "else:\n", " print(\"not working on the soma\")" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.766053Z", "iopub.status.busy": "2025-08-18T03:35:52.765910Z", "iopub.status.idle": "2025-08-18T03:35:52.773254Z", "shell.execute_reply": "2025-08-18T03:35:52.772928Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "not statistically significant\n" ] } ], "source": [ "p = 0.06\n", "if p < 0.05:\n", " print(\"statistically significant\")\n", "else:\n", " print(\"not statistically significant\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that here we used a single quote instead of a double quote to indicate the beginning and end of a string. Either way is fine, as long as the beginning and end of a string match." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python also has a special object called None. This is one way you can specify whether or not an object is valid. When doing comparisons with None, it is generally recommended to use is and is not:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.778601Z", "iopub.status.busy": "2025-08-18T03:35:52.777995Z", "iopub.status.idle": "2025-08-18T03:35:52.786589Z", "shell.execute_reply": "2025-08-18T03:35:52.784802Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No postsynaptic cell to connect to\n" ] } ], "source": [ "postsynaptic_cell = None\n", "if postsynaptic_cell is not None:\n", " print(\"Connecting to postsynaptic cell\")\n", "else:\n", " print(\"No postsynaptic cell to connect to\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists are comma-separated values surrounded by square brackets:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.793081Z", "iopub.status.busy": "2025-08-18T03:35:52.790522Z", "iopub.status.idle": "2025-08-18T03:35:52.800500Z", "shell.execute_reply": "2025-08-18T03:35:52.800171Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 3, 5, 8, 13]\n" ] } ], "source": [ "my_list = [1, 3, 5, 8, 13]\n", "print(my_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists are zero-indexed. That is, the first element is 0." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.804050Z", "iopub.status.busy": "2025-08-18T03:35:52.803907Z", "iopub.status.idle": "2025-08-18T03:35:52.812628Z", "shell.execute_reply": "2025-08-18T03:35:52.812292Z" } }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_list[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You may often find yourself wanting to know how many items are in a list." ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.818496Z", "iopub.status.busy": "2025-08-18T03:35:52.817220Z", "iopub.status.idle": "2025-08-18T03:35:52.827471Z", "shell.execute_reply": "2025-08-18T03:35:52.825279Z" } }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(my_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python interprets negative indices as counting backwards from the end of the list. That is, the -1 index refers to the last item, the -2 index refers to the second-to-last item, etc." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.830834Z", "iopub.status.busy": "2025-08-18T03:35:52.830685Z", "iopub.status.idle": "2025-08-18T03:35:52.837980Z", "shell.execute_reply": "2025-08-18T03:35:52.837652Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 3, 5, 8, 13]\n", "13\n" ] } ], "source": [ "print(my_list)\n", "print(my_list[-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "“Slicing” is extracting particular sub-elements from the list in a particular range. However, notice that the right-side is excluded, and the left is included." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.845710Z", "iopub.status.busy": "2025-08-18T03:35:52.842767Z", "iopub.status.idle": "2025-08-18T03:35:52.852731Z", "shell.execute_reply": "2025-08-18T03:35:52.852402Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 3, 5, 8, 13]\n", "[5, 8]\n", "[5, 8]\n", "[1, 3]\n", "[5, 8, 13]\n" ] } ], "source": [ "print(my_list)\n", "print(my_list[2:4]) # Includes the range from index 2 to 3\n", "print(my_list[2:-1]) # Includes the range from index 2 to the element before -1\n", "print(my_list[:2]) # Includes everything before index 2\n", "print(my_list[2:]) # Includes everything from index 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can check if our list contains a given value using the in operator:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.855846Z", "iopub.status.busy": "2025-08-18T03:35:52.855703Z", "iopub.status.idle": "2025-08-18T03:35:52.864861Z", "shell.execute_reply": "2025-08-18T03:35:52.864507Z" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "42 in my_list" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.868974Z", "iopub.status.busy": "2025-08-18T03:35:52.868826Z", "iopub.status.idle": "2025-08-18T03:35:52.872602Z", "shell.execute_reply": "2025-08-18T03:35:52.872250Z" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 in my_list" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can append an element to a list using the append method:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.874313Z", "iopub.status.busy": "2025-08-18T03:35:52.874173Z", "iopub.status.idle": "2025-08-18T03:35:52.881470Z", "shell.execute_reply": "2025-08-18T03:35:52.881122Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 3, 5, 8, 13, 42]\n" ] } ], "source": [ "my_list.append(42)\n", "print(my_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To make a variable equal to a copy of a list, set it equal to list(the_old_list). For example:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.883096Z", "iopub.status.busy": "2025-08-18T03:35:52.882750Z", "iopub.status.idle": "2025-08-18T03:35:52.887530Z", "shell.execute_reply": "2025-08-18T03:35:52.887171Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "list_a = [1, 3, 5, 8, 13]\n", "list_b = [13, 8, 5, 3, 1]\n" ] } ], "source": [ "list_a = [1, 3, 5, 8, 13]\n", "list_b = list(list_a)\n", "list_b.reverse()\n", "print(\"list_a = \" + str(list_a))\n", "print(\"list_b = \" + str(list_b))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In particular, note that assigning one list to another variable does not make a copy. Instead, it just gives another way of accessing the same list." ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.889209Z", "iopub.status.busy": "2025-08-18T03:35:52.889074Z", "iopub.status.idle": "2025-08-18T03:35:52.894324Z", "shell.execute_reply": "2025-08-18T03:35:52.893994Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "initial: list_a[0] = 1\n", "final: list_a[0] = 42\n" ] } ], "source": [ "print(\"initial: list_a[0] = %g\" % list_a[0])\n", "foo = list_a\n", "foo[0] = 42\n", "print(\"final: list_a[0] = %g\" % list_a[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

If the second line in the previous example was replaced with list_b = list_a, then what would happen?

\n", "

In that case, list_b is the same list as list_a (as opposed to a copy), so when list_b was reversed so is list_a (since list_b is list_a).

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can sort a list and get a new list using the sorted function. e.g." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.896002Z", "iopub.status.busy": "2025-08-18T03:35:52.895862Z", "iopub.status.idle": "2025-08-18T03:35:52.902716Z", "shell.execute_reply": "2025-08-18T03:35:52.902405Z" } }, "outputs": [ { "data": { "text/plain": [ "['apical', 'axon', 'basal', 'obliques', 'soma']" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted([\"soma\", \"basal\", \"apical\", \"axon\", \"obliques\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we have sorted by alphabetical order. If our list had only numbers, it would by default sort by numerical order:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.904458Z", "iopub.status.busy": "2025-08-18T03:35:52.904301Z", "iopub.status.idle": "2025-08-18T03:35:52.909910Z", "shell.execute_reply": "2025-08-18T03:35:52.909505Z" } }, "outputs": [ { "data": { "text/plain": [ "[1, 1.51, 4, 6, 165]" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted([6, 1, 165, 1.51, 4])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we wanted to sort by another attribute, we can specify a function that returns that attribute value as the optional key keyword argument. For example, to sort our list of neuron parts by the length of the name (returned by the function len):" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.911545Z", "iopub.status.busy": "2025-08-18T03:35:52.911404Z", "iopub.status.idle": "2025-08-18T03:35:52.916905Z", "shell.execute_reply": "2025-08-18T03:35:52.916494Z" } }, "outputs": [ { "data": { "text/plain": [ "['soma', 'axon', 'basal', 'apical', 'obliques']" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted([\"soma\", \"basal\", \"apical\", \"axon\", \"obliques\"], key=len)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Lists can contain arbitrary data types, but if you find yourself doing this, you should probably consider making classes or dictionaries (described below).

" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.921502Z", "iopub.status.busy": "2025-08-18T03:35:52.918505Z", "iopub.status.idle": "2025-08-18T03:35:52.923796Z", "shell.execute_reply": "2025-08-18T03:35:52.923260Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['abc', 1.0, 2, 'another string']\n", "another string\n" ] } ], "source": [ "confusing_list = [\"abc\", 1.0, 2, \"another string\"]\n", "print(confusing_list)\n", "print(confusing_list[3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is sometimes convenient to assign the elements of a list with a known length to an equivalent number of variables:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.925327Z", "iopub.status.busy": "2025-08-18T03:35:52.925187Z", "iopub.status.idle": "2025-08-18T03:35:52.931524Z", "shell.execute_reply": "2025-08-18T03:35:52.931175Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "35\n" ] } ], "source": [ "first, second, third = [42, 35, 25]\n", "print(second)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The range function can be used to create a list-like object (prior to Python 3.0, it generated lists; beginning with 3.0, it generates a more memory efficient structure) of evenly spaced integers; a list can be produced from this using the list function. With one argument, range produces integers from 0 to the argument, with two integer arguments, it produces integers between the two values, and with three arguments, the third specifies the interval between the first two. The ending value is not included." ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.935053Z", "iopub.status.busy": "2025-08-18T03:35:52.934901Z", "iopub.status.idle": "2025-08-18T03:35:52.938034Z", "shell.execute_reply": "2025-08-18T03:35:52.937693Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n" ] } ], "source": [ "print(list(range(10))) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.940971Z", "iopub.status.busy": "2025-08-18T03:35:52.939580Z", "iopub.status.idle": "2025-08-18T03:35:52.944452Z", "shell.execute_reply": "2025-08-18T03:35:52.944121Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n" ] } ], "source": [ "print(list(range(0, 10))) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.947959Z", "iopub.status.busy": "2025-08-18T03:35:52.947815Z", "iopub.status.idle": "2025-08-18T03:35:52.953447Z", "shell.execute_reply": "2025-08-18T03:35:52.953126Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3, 4, 5, 6, 7, 8, 9]\n" ] } ], "source": [ "print(list(range(3, 10))) # [3, 4, 5, 6, 7, 8, 9]" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.955114Z", "iopub.status.busy": "2025-08-18T03:35:52.954966Z", "iopub.status.idle": "2025-08-18T03:35:52.959211Z", "shell.execute_reply": "2025-08-18T03:35:52.958868Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 2, 4, 6, 8]\n" ] } ], "source": [ "print(list(range(0, 10, 2))) # [0, 2, 4, 6, 8]" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.961951Z", "iopub.status.busy": "2025-08-18T03:35:52.961807Z", "iopub.status.idle": "2025-08-18T03:35:52.967485Z", "shell.execute_reply": "2025-08-18T03:35:52.967126Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[]\n" ] } ], "source": [ "print(list(range(0, -10))) # []" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.969036Z", "iopub.status.busy": "2025-08-18T03:35:52.968898Z", "iopub.status.idle": "2025-08-18T03:35:52.973318Z", "shell.execute_reply": "2025-08-18T03:35:52.972989Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]\n" ] } ], "source": [ "print(list(range(0, -10, -1))) # [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.976685Z", "iopub.status.busy": "2025-08-18T03:35:52.976536Z", "iopub.status.idle": "2025-08-18T03:35:52.978735Z", "shell.execute_reply": "2025-08-18T03:35:52.978401Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, -2, -4, -6, -8]\n" ] } ], "source": [ "print(list(range(0, -10, -2))) # [0, -2, -4, -6, -8]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For non-integer ranges, use numpy.arange from the numpy module." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### List comprehensions (set theory)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "List comprehensions provide a rule for building a list from another list (or any other Python iterable).\n", "\n", "For example, the list of all integers from 0 to 9 inclusive is range(10) as shown above. We can get a list of the squares of all those integers via:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.983713Z", "iopub.status.busy": "2025-08-18T03:35:52.983045Z", "iopub.status.idle": "2025-08-18T03:35:52.989568Z", "shell.execute_reply": "2025-08-18T03:35:52.989209Z" } }, "outputs": [ { "data": { "text/plain": [ "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[x**2 for x in range(10)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Including an if condition allows us to filter the list:\n", "\n", "What are all the integers x between 0 and 29 inclusive that satisfy (x - 3) * (x - 10) == 0?" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.992548Z", "iopub.status.busy": "2025-08-18T03:35:52.991162Z", "iopub.status.idle": "2025-08-18T03:35:52.997853Z", "shell.execute_reply": "2025-08-18T03:35:52.997507Z" } }, "outputs": [ { "data": { "text/plain": [ "[3, 10]" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[x for x in range(30) if (x - 3) * (x - 10) == 0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## For loops and iterators" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can iterate over elements in a list by following the format: for element in list: Notice that indentation is important in Python! After a colon, the block needs to be indented. (Any consistent indentation will work, but the Python standard is 4 spaces)." ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:52.999529Z", "iopub.status.busy": "2025-08-18T03:35:52.999179Z", "iopub.status.idle": "2025-08-18T03:35:53.004839Z", "shell.execute_reply": "2025-08-18T03:35:53.004482Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "soma\n", "axon\n", "dendrites\n" ] } ], "source": [ "cell_parts = [\"soma\", \"axon\", \"dendrites\"]\n", "for part in cell_parts:\n", " print(part)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that we are iterating over the elements of a list; much of the time, the index of the items is irrelevant. If, on the other hand, we need to know the index as well, we can use enumerate:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.006998Z", "iopub.status.busy": "2025-08-18T03:35:53.006330Z", "iopub.status.idle": "2025-08-18T03:35:53.011506Z", "shell.execute_reply": "2025-08-18T03:35:53.011143Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 soma\n", "1 axon\n", "2 dendrites\n" ] } ], "source": [ "cell_parts = [\"soma\", \"axon\", \"dendrites\"]\n", "for part_num, part in enumerate(cell_parts):\n", " print(\"%d %s\" % (part_num, part))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiple aligned lists (such as occurs with time series data) can be looped over simultaneously using zip:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.015691Z", "iopub.status.busy": "2025-08-18T03:35:53.015541Z", "iopub.status.idle": "2025-08-18T03:35:53.017952Z", "shell.execute_reply": "2025-08-18T03:35:53.017611Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " soma 20\n", " axon 2\n", " dendrites 3\n" ] } ], "source": [ "cell_parts = [\"soma\", \"axon\", \"dendrites\"]\n", "diams = [20, 2, 3]\n", "for diam, part in zip(diams, cell_parts):\n", " print(\"%10s %g\" % (part, diam))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another example:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.019731Z", "iopub.status.busy": "2025-08-18T03:35:53.019589Z", "iopub.status.idle": "2025-08-18T03:35:53.027552Z", "shell.execute_reply": "2025-08-18T03:35:53.024106Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x = [0, 1, 2, 3, 4]\n", "y = ['a', 'b', 'c', 'd', 'e']\n", "[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')]\n" ] } ], "source": [ "y = [\"a\", \"b\", \"c\", \"d\", \"e\"]\n", "x = list(range(len(y)))\n", "print(\"x = {}\".format(x))\n", "print(\"y = {}\".format(y))\n", "print(list(zip(x, y)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a list of tuples. Given a list of tuples, then we iterate with each tuple." ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.029057Z", "iopub.status.busy": "2025-08-18T03:35:53.028914Z", "iopub.status.idle": "2025-08-18T03:35:53.034435Z", "shell.execute_reply": "2025-08-18T03:35:53.034085Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "index 0: a\n", "index 1: b\n", "index 2: c\n", "index 3: d\n", "index 4: e\n" ] } ], "source": [ "for x_val, y_val in zip(x, y):\n", " print(\"index {}: {}\".format(x_val, y_val))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tuples are similar to lists, except they are immutable (cannot be changed). You can retrieve individual elements of a tuple, but once they are set upon creation, you cannot change them. Also, you cannot add or remove elements of a tuple." ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.036239Z", "iopub.status.busy": "2025-08-18T03:35:53.035948Z", "iopub.status.idle": "2025-08-18T03:35:53.040865Z", "shell.execute_reply": "2025-08-18T03:35:53.040528Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 'two', 3)\n", "two\n" ] } ], "source": [ "my_tuple = (1, \"two\", 3)\n", "print(my_tuple)\n", "print(my_tuple[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Attempting to modify a tuple, e.g." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "my_tuple[1] = 2\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "will cause a TypeError." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because you cannot modify an element in a tuple, or add or remove individual elements of it, it can operate in Python more efficiently than a list. A tuple can even serve as a key to a dictionary." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dictionaries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A dictionary (also called a dict or hash table) is a set of (key, value) pairs, denoted by curly brackets:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.042689Z", "iopub.status.busy": "2025-08-18T03:35:53.042547Z", "iopub.status.idle": "2025-08-18T03:35:53.047494Z", "shell.execute_reply": "2025-08-18T03:35:53.047145Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'name': 'Tom', 'age': 45, 'height': \"5'8\"}\n" ] } ], "source": [ "about_me = {\"name\": my_name, \"age\": my_age, \"height\": \"5'8\"}\n", "print(about_me)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can obtain values by referencing the key:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.049010Z", "iopub.status.busy": "2025-08-18T03:35:53.048868Z", "iopub.status.idle": "2025-08-18T03:35:53.053348Z", "shell.execute_reply": "2025-08-18T03:35:53.053036Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5'8\n" ] } ], "source": [ "print(about_me[\"height\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, we can modify existing values by referencing the key." ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.055553Z", "iopub.status.busy": "2025-08-18T03:35:53.054941Z", "iopub.status.idle": "2025-08-18T03:35:53.059728Z", "shell.execute_reply": "2025-08-18T03:35:53.059404Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'name': 'Thomas', 'age': 45, 'height': \"5'8\"}\n" ] } ], "source": [ "about_me[\"name\"] = \"Thomas\"\n", "print(about_me)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can even add new values." ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.061412Z", "iopub.status.busy": "2025-08-18T03:35:53.061258Z", "iopub.status.idle": "2025-08-18T03:35:53.066446Z", "shell.execute_reply": "2025-08-18T03:35:53.066111Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'name': 'Thomas', 'age': 45, 'height': \"5'8\", 'eye_color': 'brown'}\n" ] } ], "source": [ "about_me[\"eye_color\"] = \"brown\"\n", "print(about_me)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use curly braces with keys to indicate dictionary fields when using format. e.g." ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.069950Z", "iopub.status.busy": "2025-08-18T03:35:53.069807Z", "iopub.status.idle": "2025-08-18T03:35:53.072898Z", "shell.execute_reply": "2025-08-18T03:35:53.072567Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I am a 45 year old person named Thomas. Again, my name is Thomas.\n" ] } ], "source": [ "print(\n", " \"I am a {age} year old person named {name}. Again, my name is {name}.\".format(\n", " **about_me\n", " )\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Important: note the use of the ** inside the format call." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can iterate keys (.keys()), values (.values()) or key-value value pairs (.items())in the dict. Here is an example of key-value pairs." ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.074601Z", "iopub.status.busy": "2025-08-18T03:35:53.074274Z", "iopub.status.idle": "2025-08-18T03:35:53.080947Z", "shell.execute_reply": "2025-08-18T03:35:53.080588Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "key = name val = Thomas\n", "key = age val = 45\n", "key = height val = 5'8\n", "key = eye_color val = brown\n" ] } ], "source": [ "for k, v in about_me.items():\n", " print(\"key = {:10s} val = {}\".format(k, v))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To test for the presence of a key in a dict, we just ask:" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.082642Z", "iopub.status.busy": "2025-08-18T03:35:53.082497Z", "iopub.status.idle": "2025-08-18T03:35:53.085758Z", "shell.execute_reply": "2025-08-18T03:35:53.085420Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No. 'hair_color' is NOT a key in the dict\n" ] } ], "source": [ "if \"hair_color\" in about_me:\n", " print(\"Yes. 'hair_color' is a key in the dict\")\n", "else:\n", " print(\"No. 'hair_color' is NOT a key in the dict\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dictionaries can be nested, e.g." ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.088951Z", "iopub.status.busy": "2025-08-18T03:35:53.088810Z", "iopub.status.idle": "2025-08-18T03:35:53.094465Z", "shell.execute_reply": "2025-08-18T03:35:53.092622Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "cerebellum" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "neurons = {\n", " \"purkinje cells\": {\"location\": \"cerebellum\", \"role\": \"motor movement\"},\n", " \"ca1 pyramidal cells\": {\"location\": \"hippocampus\", \"role\": \"learning and memory\"},\n", "}\n", "print(neurons[\"purkinje cells\"][\"location\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions are defined with a “def” keyword in front of them, end with a colon, and the next line is indented. Indentation of 4-spaces (again, any non-zero consistent amount will do) demarcates functional blocks." ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.098209Z", "iopub.status.busy": "2025-08-18T03:35:53.098063Z", "iopub.status.idle": "2025-08-18T03:35:53.102418Z", "shell.execute_reply": "2025-08-18T03:35:53.100413Z" } }, "outputs": [], "source": [ "def print_hello():\n", " print(\"Hello\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's call our function." ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.105050Z", "iopub.status.busy": "2025-08-18T03:35:53.104906Z", "iopub.status.idle": "2025-08-18T03:35:53.110480Z", "shell.execute_reply": "2025-08-18T03:35:53.110138Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello\n" ] } ], "source": [ "print_hello()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also pass in an argument." ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.112175Z", "iopub.status.busy": "2025-08-18T03:35:53.112037Z", "iopub.status.idle": "2025-08-18T03:35:53.115589Z", "shell.execute_reply": "2025-08-18T03:35:53.114302Z" } }, "outputs": [], "source": [ "def my_print(the_arg):\n", " print(the_arg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now try passing various things to the my_print() function." ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.118504Z", "iopub.status.busy": "2025-08-18T03:35:53.116951Z", "iopub.status.idle": "2025-08-18T03:35:53.122469Z", "shell.execute_reply": "2025-08-18T03:35:53.122097Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello\n" ] } ], "source": [ "my_print(\"Hello\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can even make default arguments." ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.125957Z", "iopub.status.busy": "2025-08-18T03:35:53.125810Z", "iopub.status.idle": "2025-08-18T03:35:53.129166Z", "shell.execute_reply": "2025-08-18T03:35:53.128832Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello\n", "[0, 1, 2, 3]\n" ] } ], "source": [ "def my_print(message=\"Hello\"):\n", " print(message)\n", "\n", "\n", "my_print()\n", "my_print(list(range(4)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And we can also return values." ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.132693Z", "iopub.status.busy": "2025-08-18T03:35:53.132544Z", "iopub.status.idle": "2025-08-18T03:35:53.137469Z", "shell.execute_reply": "2025-08-18T03:35:53.135738Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 1, 2, 3]\n" ] } ], "source": [ "def fib(n=5):\n", " \"\"\"Get a Fibonacci series up to n.\"\"\"\n", " a, b = 0, 1\n", " series = [a]\n", " while b < n:\n", " a, b = b, a + b\n", " series.append(a)\n", " return series\n", "\n", "\n", "print(fib())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note the assignment line for a and b inside the while loop. That line says that a becomes the old value of b and that b becomes the old value of a plus the old value of b. The ability to calculate multiple values before assigning them allows Python to do things like swapping the values of two variables in one line while many other programming languages would require the introduction of a temporary variable.\n", "\n", "When a function begins with a string as in the above, that string is known as a doc string, and is shown whenever help is invoked on the function (this, by the way, is a way to learn more about Python's many functions):" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.139651Z", "iopub.status.busy": "2025-08-18T03:35:53.139053Z", "iopub.status.idle": "2025-08-18T03:35:53.144757Z", "shell.execute_reply": "2025-08-18T03:35:53.144416Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function fib in module __main__:\n", "\n", "fib(n=5)\n", " Get a Fibonacci series up to n.\n", "\n" ] } ], "source": [ "help(fib)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You may have noticed the string beginning the fib function was triple-quoted. This enables a string to span multiple lines." ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.146325Z", "iopub.status.busy": "2025-08-18T03:35:53.146186Z", "iopub.status.idle": "2025-08-18T03:35:53.151831Z", "shell.execute_reply": "2025-08-18T03:35:53.151130Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is the first line\n", "This is the second,\n", "and a third.\n" ] } ], "source": [ "multi_line_str = \"\"\"This is the first line\n", "This is the second,\n", "and a third.\"\"\"\n", "\n", "print(multi_line_str)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Classes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Objects are instances of a class. They are useful for encapsulating ideas, and mostly for having multiple instances of a structure. (In NEURON, for example, one might use a class to represent a neuron type and create many instances.) Usually you will have an __init__() method. Also note that every method of the class will have self as the first argument. While self has to be listed in the argument list of a class's method, you do not pass a self argument when calling any of the class’s methods; instead, you refer to those methods as self.method_name." ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.154018Z", "iopub.status.busy": "2025-08-18T03:35:53.153361Z", "iopub.status.idle": "2025-08-18T03:35:53.160664Z", "shell.execute_reply": "2025-08-18T03:35:53.160292Z" } }, "outputs": [], "source": [ "class Contact(object):\n", " \"\"\"A given person for my database of friends.\"\"\"\n", "\n", " def __init__(self, first_name=None, last_name=None, email=None, phone=None):\n", " self.first_name = first_name\n", " self.last_name = last_name\n", " self.email = email\n", " self.phone = phone\n", "\n", " def print_info(self):\n", " \"\"\"Print all of the information of this contact.\"\"\"\n", " my_str = \"Contact info:\"\n", " if self.first_name:\n", " my_str += \" \" + self.first_name\n", " if self.last_name:\n", " my_str += \" \" + self.last_name\n", " if self.email:\n", " my_str += \" \" + self.email\n", " if self.phone:\n", " my_str += \" \" + self.phone\n", " print(my_str)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By convention, the first letter of a class name is capitalized. Notice in the class definition above that the object can contain fields, which are used within the class as self.field. This field can be another method in the class, or another object of another class." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's make a couple instances of Contact." ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.162494Z", "iopub.status.busy": "2025-08-18T03:35:53.162003Z", "iopub.status.idle": "2025-08-18T03:35:53.166143Z", "shell.execute_reply": "2025-08-18T03:35:53.165794Z" } }, "outputs": [], "source": [ "bob = Contact(\"Bob\", \"Smith\")\n", "joe = Contact(email=\"someone@somewhere.com\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that in the first case, if we are filling each argument, we do not need to explicitly denote “first_name” and “last_name”. However, in the second case, since “first” and “last” are omitted, the first parameter passed in would be assigned to the first_name field so we have to explicitly set it to “email”." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let’s set a field." ] }, { "cell_type": "code", "execution_count": 72, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.169433Z", "iopub.status.busy": "2025-08-18T03:35:53.168823Z", "iopub.status.idle": "2025-08-18T03:35:53.174008Z", "shell.execute_reply": "2025-08-18T03:35:53.173684Z" } }, "outputs": [], "source": [ "joe.first_name = \"Joe\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, we can retrieve fields from the object." ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.179523Z", "iopub.status.busy": "2025-08-18T03:35:53.175540Z", "iopub.status.idle": "2025-08-18T03:35:53.182586Z", "shell.execute_reply": "2025-08-18T03:35:53.182220Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Joe\n" ] } ], "source": [ "the_name = joe.first_name\n", "print(the_name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And we call methods of the object using the format instance.method()." ] }, { "cell_type": "code", "execution_count": 74, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.184108Z", "iopub.status.busy": "2025-08-18T03:35:53.183969Z", "iopub.status.idle": "2025-08-18T03:35:53.190432Z", "shell.execute_reply": "2025-08-18T03:35:53.190056Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Contact info: Joe someone@somewhere.com\n" ] } ], "source": [ "joe.print_info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remember the importance of docstrings!" ] }, { "cell_type": "code", "execution_count": 75, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.193502Z", "iopub.status.busy": "2025-08-18T03:35:53.191867Z", "iopub.status.idle": "2025-08-18T03:35:53.198511Z", "shell.execute_reply": "2025-08-18T03:35:53.198142Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class Contact in module __main__:\n", "\n", "class Contact(builtins.object)\n", " | Contact(first_name=None, last_name=None, email=None, phone=None)\n", " |\n", " | A given person for my database of friends.\n", " |\n", " | Methods defined here:\n", " |\n", " | __init__(self, first_name=None, last_name=None, email=None, phone=None)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " |\n", " | print_info(self)\n", " | Print all of the information of this contact.\n", " |\n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " |\n", " | __dict__\n", " | dictionary for instance variables\n", " |\n", " | __weakref__\n", " | list of weak references to the object\n", "\n" ] } ], "source": [ "help(Contact)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Importing modules" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Extensions to core Python are made by importing modules, which may contain more variables, objects, methods, and functions. Many modules come with Python, but are not part of its core. Other packages and modules have to be installed.\n", "\n", "The numpy module contains a function called arange() that is similar to Python’s range() function, but permits non-integer steps." ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.200218Z", "iopub.status.busy": "2025-08-18T03:35:53.200076Z", "iopub.status.idle": "2025-08-18T03:35:53.311500Z", "shell.execute_reply": "2025-08-18T03:35:53.311096Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "import numpy\n", "\n", "my_vec = numpy.arange(0, 1, 0.1)\n", "print(my_vec)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note: numpy is available in many distributions of Python, but it is not part of Python itself. If the import numpy line gave an error message, you either do not have numpy installed or Python cannot find it for some reason. You should resolve this issue before proceeding because we will use numpy in some of the examples in other parts of the tutorial. The standard tool for installing Python modules is called pip; other options may be available depending on your platform." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can get 20 evenly spaced values between 0 and $\\pi$ using numpy.linspace:" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.315916Z", "iopub.status.busy": "2025-08-18T03:35:53.312977Z", "iopub.status.idle": "2025-08-18T03:35:53.320091Z", "shell.execute_reply": "2025-08-18T03:35:53.319714Z" } }, "outputs": [], "source": [ "x = numpy.linspace(0, numpy.pi, 20)" ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.323553Z", "iopub.status.busy": "2025-08-18T03:35:53.321554Z", "iopub.status.idle": "2025-08-18T03:35:53.328179Z", "shell.execute_reply": "2025-08-18T03:35:53.327579Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0.16534698 0.33069396 0.49604095 0.66138793 0.82673491\n", " 0.99208189 1.15742887 1.32277585 1.48812284 1.65346982 1.8188168\n", " 1.98416378 2.14951076 2.31485774 2.48020473 2.64555171 2.81089869\n", " 2.97624567 3.14159265]\n" ] } ], "source": [ "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NumPy provides vectorized trig (and other) functions. For example, we can get another array with the sines of all those x values via:" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.330486Z", "iopub.status.busy": "2025-08-18T03:35:53.329664Z", "iopub.status.idle": "2025-08-18T03:35:53.334682Z", "shell.execute_reply": "2025-08-18T03:35:53.334297Z" } }, "outputs": [], "source": [ "y = numpy.sin(x)" ] }, { "cell_type": "code", "execution_count": 80, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.336358Z", "iopub.status.busy": "2025-08-18T03:35:53.336106Z", "iopub.status.idle": "2025-08-18T03:35:53.342520Z", "shell.execute_reply": "2025-08-18T03:35:53.340983Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.00000000e+00 1.64594590e-01 3.24699469e-01 4.75947393e-01\n", " 6.14212713e-01 7.35723911e-01 8.37166478e-01 9.15773327e-01\n", " 9.69400266e-01 9.96584493e-01 9.96584493e-01 9.69400266e-01\n", " 9.15773327e-01 8.37166478e-01 7.35723911e-01 6.14212713e-01\n", " 4.75947393e-01 3.24699469e-01 1.64594590e-01 1.22464680e-16]\n" ] } ], "source": [ "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The bokeh module is one way to plot graphics that works especially well in a Jupyter notebook environment. To use this library in a Jupyter notebook, we first load it and tell it to display in the notebook:" ] }, { "cell_type": "code", "execution_count": 81, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.345870Z", "iopub.status.busy": "2025-08-18T03:35:53.343815Z", "iopub.status.idle": "2025-08-18T03:35:53.877012Z", "shell.execute_reply": "2025-08-18T03:35:53.876117Z" } }, "outputs": [ { "data": { "text/html": [ " \n", "
\n", " \n", " Loading BokehJS ...\n", "
\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "'use strict';\n", "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " const force = true;\n", "\n", " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", " root._bokeh_onload_callbacks = [];\n", " root._bokeh_is_loading = undefined;\n", " }\n", "\n", "const JS_MIME_TYPE = 'application/javascript';\n", " const HTML_MIME_TYPE = 'text/html';\n", " const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n", " const CLASS_NAME = 'output_bokeh rendered_html';\n", "\n", " /**\n", " * Render data to the DOM node\n", " */\n", " function render(props, node) {\n", " const script = document.createElement(\"script\");\n", " node.appendChild(script);\n", " }\n", "\n", " /**\n", " * Handle when an output is cleared or removed\n", " */\n", " function handleClearOutput(event, handle) {\n", " function drop(id) {\n", " const view = Bokeh.index.get_by_id(id)\n", " if (view != null) {\n", " view.model.document.clear()\n", " Bokeh.index.delete(view)\n", " }\n", " }\n", "\n", " const cell = handle.cell;\n", "\n", " const id = cell.output_area._bokeh_element_id;\n", " const server_id = cell.output_area._bokeh_server_id;\n", "\n", " // Clean up Bokeh references\n", " if (id != null) {\n", " drop(id)\n", " }\n", "\n", " if (server_id !== undefined) {\n", " // Clean up Bokeh references\n", " const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n", " cell.notebook.kernel.execute(cmd_clean, {\n", " iopub: {\n", " output: function(msg) {\n", " const id = msg.content.text.trim()\n", " drop(id)\n", " }\n", " }\n", " });\n", " // Destroy server and session\n", " const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n", " cell.notebook.kernel.execute(cmd_destroy);\n", " }\n", " }\n", "\n", " /**\n", " * Handle when a new output is added\n", " */\n", " function handleAddOutput(event, handle) {\n", " const output_area = handle.output_area;\n", " const output = handle.output;\n", "\n", " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n", " if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n", " return\n", " }\n", "\n", " const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", "\n", " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n", " toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n", " // store reference to embed id on output_area\n", " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " }\n", " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " const bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " const script_attrs = bk_div.children[0].attributes;\n", " for (let i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", " }\n", "\n", " function register_renderer(events, OutputArea) {\n", "\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " const toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[toinsert.length - 1]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " /* Handle when an output is cleared or removed */\n", " events.on('clear_output.CodeCell', handleClearOutput);\n", " events.on('delete.Cell', handleClearOutput);\n", "\n", " /* Handle when a new output is added */\n", " events.on('output_added.OutputArea', handleAddOutput);\n", "\n", " /**\n", " * Register the mime type and append_mime function with output_area\n", " */\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " /* Is output safe? */\n", " safe: true,\n", " /* Index of renderer in `output_area.display_order` */\n", " index: 0\n", " });\n", " }\n", "\n", " // register the mime type if in Jupyter Notebook environment and previously unregistered\n", " if (root.Jupyter !== undefined) {\n", " const events = require('base/js/events');\n", " const OutputArea = require('notebook/js/outputarea').OutputArea;\n", "\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " }\n", " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " const NB_LOAD_WARNING = {'data': {'text/html':\n", " \"
\\n\"+\n", " \"

\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"

\\n\"+\n", " \"
    \\n\"+\n", " \"
  • re-rerun `output_notebook()` to attempt to load from CDN again, or
  • \\n\"+\n", " \"
  • use INLINE resources instead, as so:
  • \\n\"+\n", " \"
\\n\"+\n", " \"\\n\"+\n", " \"from bokeh.resources import INLINE\\n\"+\n", " \"output_notebook(resources=INLINE)\\n\"+\n", " \"\\n\"+\n", " \"
\"}};\n", "\n", " function display_loaded(error = null) {\n", " const el = document.getElementById(\"fa95bedc-b771-4af6-8570-f52d25468e66\");\n", " if (el != null) {\n", " const html = (() => {\n", " if (typeof root.Bokeh === \"undefined\") {\n", " if (error == null) {\n", " return \"BokehJS is loading ...\";\n", " } else {\n", " return \"BokehJS failed to load.\";\n", " }\n", " } else {\n", " const prefix = `BokehJS ${root.Bokeh.version}`;\n", " if (error == null) {\n", " return `${prefix} successfully loaded.`;\n", " } else {\n", " return `${prefix} encountered errors while loading and may not function as expected.`;\n", " }\n", " }\n", " })();\n", " el.innerHTML = html;\n", "\n", " if (error != null) {\n", " const wrapper = document.createElement(\"div\");\n", " wrapper.style.overflow = \"auto\";\n", " wrapper.style.height = \"5em\";\n", " wrapper.style.resize = \"vertical\";\n", " const content = document.createElement(\"div\");\n", " content.style.fontFamily = \"monospace\";\n", " content.style.whiteSpace = \"pre-wrap\";\n", " content.style.backgroundColor = \"rgb(255, 221, 221)\";\n", " content.textContent = error.stack ?? error.toString();\n", " wrapper.append(content);\n", " el.append(wrapper);\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(() => display_loaded(error), 100);\n", " }\n", " }\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", " if (root._bokeh_is_loading > 0) {\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " }\n", " if (js_urls == null || js_urls.length === 0) {\n", " run_callbacks();\n", " return null;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", "\n", " function on_error(url) {\n", " console.error(\"failed to load \" + url);\n", " }\n", "\n", " for (let i = 0; i < css_urls.length; i++) {\n", " const url = css_urls[i];\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error.bind(null, url);\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " }\n", "\n", " for (let i = 0; i < js_urls.length; i++) {\n", " const url = js_urls[i];\n", " const element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error.bind(null, url);\n", " element.async = false;\n", " element.src = url;\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.7.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.7.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.7.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.7.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.7.2.min.js\"];\n", " const css_urls = [];\n", "\n", " const inline_js = [ function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", "function(Bokeh) {\n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " if (root.Bokeh !== undefined || force === true) {\n", " try {\n", " for (let i = 0; i < inline_js.length; i++) {\n", " inline_js[i].call(root, root.Bokeh);\n", " }\n", "\n", " } catch (error) {display_loaded(error);throw error;\n", " }if (force === true) {\n", " display_loaded();\n", " }} else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " } else if (force !== true) {\n", " const cell = $(document.getElementById(\"fa95bedc-b771-4af6-8570-f52d25468e66\")).parents('.cell').data().cell;\n", " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", " }\n", " }\n", "\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(css_urls, js_urls, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", "}(window));" ], "application/vnd.bokehjs_load.v0+json": "'use strict';\n(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n const NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"
    \\n\"+\n \"
  • re-rerun `output_notebook()` to attempt to load from CDN again, or
  • \\n\"+\n \"
  • use INLINE resources instead, as so:
  • \\n\"+\n \"
\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded(error = null) {\n const el = document.getElementById(\"fa95bedc-b771-4af6-8570-f52d25468e66\");\n if (el != null) {\n const html = (() => {\n if (typeof root.Bokeh === \"undefined\") {\n if (error == null) {\n return \"BokehJS is loading ...\";\n } else {\n return \"BokehJS failed to load.\";\n }\n } else {\n const prefix = `BokehJS ${root.Bokeh.version}`;\n if (error == null) {\n return `${prefix} successfully loaded.`;\n } else {\n return `${prefix} encountered errors while loading and may not function as expected.`;\n }\n }\n })();\n el.innerHTML = html;\n\n if (error != null) {\n const wrapper = document.createElement(\"div\");\n wrapper.style.overflow = \"auto\";\n wrapper.style.height = \"5em\";\n wrapper.style.resize = \"vertical\";\n const content = document.createElement(\"div\");\n content.style.fontFamily = \"monospace\";\n content.style.whiteSpace = \"pre-wrap\";\n content.style.backgroundColor = \"rgb(255, 221, 221)\";\n content.textContent = error.stack ?? error.toString();\n wrapper.append(content);\n el.append(wrapper);\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(() => display_loaded(error), 100);\n }\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.7.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.7.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.7.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.7.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.7.2.min.js\"];\n const css_urls = [];\n\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {\n }\n ];\n\n function run_inline_js() {\n if (root.Bokeh !== undefined || force === true) {\n try {\n for (let i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n\n } catch (error) {display_loaded(error);throw error;\n }if (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n const cell = $(document.getElementById(\"fa95bedc-b771-4af6-8570-f52d25468e66\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bokeh.io import output_notebook\n", "import bokeh.plotting as plt\n", "\n", "output_notebook() # skip this line if not working in Jupyter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we plot y = sin(x) vs x:" ] }, { "cell_type": "code", "execution_count": 82, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:53.880567Z", "iopub.status.busy": "2025-08-18T03:35:53.880346Z", "iopub.status.idle": "2025-08-18T03:35:54.315191Z", "shell.execute_reply": "2025-08-18T03:35:54.314775Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function embed_document(root) {\n", " const docs_json = {\"eb22bba9-bdf2-40d6-b7ef-5094f78e3ee3\":{\"version\":\"3.7.2\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1001\",\"attributes\":{\"x_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"p1002\"},\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"p1003\"},\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1010\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1011\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1008\"},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1041\",\"attributes\":{\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1035\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1036\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1037\"},\"data\":{\"type\":\"map\",\"entries\":[[\"x\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAvupcDFyrFPy+6lwMXKtU/RpdjhSK/3z8vupcDFyrlP7uofcScdOo/RpdjhSK/7z/pwiQj1ITyPy+6lwMXKvU/dbEK5FnP9z+7qH3EnHT6PwGg8KTfGf0/RpdjhSK//z9GR+uyMjIBQOnCJCPUhAJAjD5ek3XXA0AvupcDFyoFQNI10XO4fAZAdbEK5FnPB0AYLURU+yEJQA==\"},\"shape\":[20],\"dtype\":\"float64\",\"order\":\"little\"}],[\"y\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAADFWC1/bxHFP6nPUEjgx9Q/7XvtDex13j8jRDlroafjPw8+594Mi+c/5D2uWhHK6j8ICxHdA07tPxgu3rRTBe8/qkKlKQXk7z+qQqUpBeTvPxgu3rRTBe8/CQsR3QNO7T/lPa5aEcrqPxE+594Mi+c/JEQ5a6Gn4z/we+0N7HXeP6zPUEjgx9Q/ylgtf28RxT8HXBQzJqahPA==\"},\"shape\":[20],\"dtype\":\"float64\",\"order\":\"little\"}]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1042\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1043\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1038\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"y\":{\"type\":\"field\",\"field\":\"y\"},\"line_color\":\"#1f77b4\",\"line_width\":2}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1039\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"y\":{\"type\":\"field\",\"field\":\"y\"},\"line_color\":\"#1f77b4\",\"line_alpha\":0.1,\"line_width\":2}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1040\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"y\":{\"type\":\"field\",\"field\":\"y\"},\"line_color\":\"#1f77b4\",\"line_alpha\":0.2,\"line_width\":2}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1009\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1022\"},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1023\",\"attributes\":{\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1024\",\"attributes\":{\"dimensions\":\"both\",\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1025\",\"attributes\":{\"syncable\":false,\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5,\"level\":\"overlay\",\"visible\":false,\"left\":{\"type\":\"number\",\"value\":\"nan\"},\"right\":{\"type\":\"number\",\"value\":\"nan\"},\"top\":{\"type\":\"number\",\"value\":\"nan\"},\"bottom\":{\"type\":\"number\",\"value\":\"nan\"},\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"bottom_units\":\"canvas\",\"handles\":{\"type\":\"object\",\"name\":\"BoxInteractionHandles\",\"id\":\"p1031\",\"attributes\":{\"all\":{\"type\":\"object\",\"name\":\"AreaVisuals\",\"id\":\"p1030\",\"attributes\":{\"fill_color\":\"white\",\"hover_fill_color\":\"lightgray\"}}}}}}}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1032\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1033\"},{\"type\":\"object\",\"name\":\"HelpTool\",\"id\":\"p1034\"}]}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1017\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1018\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1019\"},\"axis_label\":\"sin(x)\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1020\"}}}],\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1012\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1013\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1014\"},\"axis_label\":\"x\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1015\"}}}],\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1016\",\"attributes\":{\"axis\":{\"id\":\"p1012\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1021\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"p1017\"}}}]}}]}};\n", " const render_items = [{\"docid\":\"eb22bba9-bdf2-40d6-b7ef-5094f78e3ee3\",\"roots\":{\"p1001\":\"f9439cac-0d1d-43a9-b1ae-63605894f22b\"},\"root_ids\":[\"p1001\"]}];\n", " void root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", " }\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " } else {\n", " let attempts = 0;\n", " const timer = setInterval(function(root) {\n", " if (root.Bokeh !== undefined) {\n", " clearInterval(timer);\n", " embed_document(root);\n", " } else {\n", " attempts++;\n", " if (attempts > 100) {\n", " clearInterval(timer);\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", " }\n", " }\n", " }, 10, root)\n", " }\n", "})(window);" ], "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { "application/vnd.bokehjs_exec.v0+json": { "id": "p1001" } }, "output_type": "display_data" } ], "source": [ "f = plt.figure(x_axis_label=\"x\", y_axis_label=\"sin(x)\")\n", "f.line(x, y, line_width=2)\n", "plt.show(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pickling objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are various file io operations in Python, but one of the easiest is “Pickling”, which attempts to save a Python object to a file for later restoration with the load command." ] }, { "cell_type": "code", "execution_count": 83, "metadata": { "execution": { "iopub.execute_input": "2025-08-18T03:35:54.325572Z", "iopub.status.busy": "2025-08-18T03:35:54.323780Z", "iopub.status.idle": "2025-08-18T03:35:54.331398Z", "shell.execute_reply": "2025-08-18T03:35:54.331024Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Contact info: Joe someone@somewhere.com\n", "Contact info: Bob Smith\n" ] } ], "source": [ "import pickle\n", "\n", "contacts = [joe, bob] # Make a list of contacts\n", "\n", "with open(\"contacts.p\", \"wb\") as pickle_file: # Make a new file\n", " pickle.dump(contacts, pickle_file) # Write contact list\n", "\n", "with open(\"contacts.p\", \"rb\") as pickle_file: # Open the file for reading\n", " contacts2 = pickle.load(pickle_file) # Load the pickled contents\n", "\n", "for elem in contacts2:\n", " elem.print_info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The next part of this tutorial introduces basic NEURON commands." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.12.10" } }, "nbformat": 4, "nbformat_minor": 2 }