{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Python for STEM Teachers
[Oregon Curriculum Network](http://4dsolutions.net/ocn/)\n", "\n", "# Atoms R Us\n", "\n", "![Periodic Table](http://www.chemicool.com/images/periodic-table.png)\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Atom(protons=3, symbol='Li', long_name='Lithium', mass=6.941, series='Alkali metal')\n", "{'protons': 3, 'symbol': 'Li', 'long_name': 'Lithium', 'mass': 6.941, 'series': 'Alkali metal'}\n", "3\n" ] } ], "source": [ "import json\n", "\n", "series_types = [\"Don't Know\", \"Other nonmetal\", \"Alkali metal\", \n", " \"Alkaline earth metal\", \"Nobel gas\", \"Metalloid\", \n", " \"Halogen\", \"Transition metal\", \"Post-transition metal\", \n", " \"Lanthanoid\", \"Actinoid\"]\n", " \n", "class Element:\n", " fields = \"protons symbol long_name mass series\"\n", " repstr = (\"Atom(protons={protons}, symbol='{symbol}', \"\n", " \"long_name='{long_name}', \"\n", " \"mass={mass}, series='{series}')\")\n", " \n", " def __init__(self, protons: int, symbol: str,\n", " long_name: str, mass: float, series: str):\n", "\n", " # build self.__dict__ \n", " self.protons = protons\n", " self.symbol = symbol\n", " self.long_name = long_name\n", " self.__dict__['mass'] = mass # same idea\n", " self.series = series\n", " \n", " def __getitem__(self, idx): # simulates collection.namedtuple behavior\n", " return self.__dict__[self.fields[idx]]\n", " \n", " def __repr__(self):\n", " return self.repstr.format(**self.__dict__)\n", "\n", "Atom = Element # synonyms\n", "\n", "lithium = Atom(3, \"Li\", \"Lithium\", 6.941, \"Alkali metal\")\n", "print(lithium) # __str__, then __repr__\n", "print(lithium.__dict__)\n", "print(lithium.protons) # print(lithium.__getattr__('protons'))" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ ".\n", "----------------------------------------------------------------------\n", "Ran 1 test in 0.002s\n", "\n", "OK\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import unittest\n", "\n", "class Test_Element(unittest.TestCase):\n", " \n", " def test_instance(self):\n", " lithium = Atom(3, \"Li\", \"Lithium\", 6.941, \"Alkali metal\")\n", " self.assertEqual(lithium.protons, 3, \"Houston, we have a problem\")\n", "\n", "a = Test_Element() # the test suite\n", "suite = unittest.TestLoader().loadTestsFromModule(a) # fancy boilerplate\n", "unittest.TextTestRunner().run(suite) # run the test suite" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File: periodic_table.json loaded.\n" ] } ], "source": [ "class ElementEncoder(json.JSONEncoder):\n", " \"\"\"\n", " See: https://docs.python.org/3.5/library/json.html\n", " \"\"\"\n", " def default(self, obj):\n", " if isinstance(obj, Element): # how to encode an Element\n", " return [obj.protons, obj.symbol, obj.long_name, obj.mass, obj.series]\n", " return json.JSONEncoder.default(self, obj) # just do your usual\n", " \n", "# Element = namedtuple(\"Atom\", \"protons abbrev long_name mass\")\n", "\n", "def load_elements():\n", " global all_elements # <--- will be visible to entire module\n", " try:\n", " the_file = \"periodic_table.json\"\n", " f = open(the_file, \"r\") # <--- open the_file instead\n", " except IOError:\n", " print(\"Sorry, no such file!\")\n", " else:\n", " the_dict = json.load(f)\n", " f.close()\n", " all_elements = {}\n", " for symbol, data in the_dict.items():\n", " all_elements[symbol] = Atom(*data) # \"explode\" data into 5 inputs\n", " print(\"File:\", the_file, 'loaded.')\n", "\n", "load_elements() # actually do it" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![by Kenneth Snelson](http://www.kennethsnelson.net/atom/6-deBrogAtm.jpg)\n", "
graphic by Kenneth Snelson
" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Selected: 1\n", "PERIODIC TABLE OF THE ELEMENTS\n", "----------------------------------------------------------------------\n", "Symbol |Long Name |Protons |Mass |Series \n", "----------------------------------------------------------------------\n", "H | Hydrogen | 1 | 1.01 | Other nonmetal \n", "He | Helium | 2 | 4.00 | Nobel gas \n", "Li | Lithium | 3 | 6.94 | Alkali metal \n", "Be | Beryllium | 4 | 9.01 | Alkaline earth metal\n", "B | Boron | 5 | 10.81 | Metalloid \n", "C | Carbon | 6 | 12.01 | Noble gas \n", "N | Nitrogen | 7 | 14.01 | Other nonmetal \n", "O | Oxygen | 8 | 16.00 | Other nonmetal \n", "F | Fluorine | 9 | 19.00 | Metalloid \n", "Ne | Neon | 10 | 20.18 | Noble gas \n", "Na | Sodium | 11 | 22.99 | Alkali metal \n", "Mg | Magnesium | 12 | 24.30 | Alkaline earth metal\n", "Al | Aluminum | 13 | 26.98 | Post-transition metal\n", "Si | Silicon | 14 | 28.09 | Metalloid \n", "P | Phosphorous | 15 | 30.97 | Other nonmetal \n", "S | Sulfur | 16 | 32.06 | Other nonmetal \n", "Cl | Chlorine | 17 | 35.45 | Halogen \n", "Ar | Argon | 18 | 39.95 | Nobel gas \n", "K | Potassium | 19 | 39.10 | Alkali metal \n" ] } ], "source": [ "def print_periodic_table(sortby=1):\n", " \"\"\"\n", " sort all_elements by number of protons, ordered_elements local only\n", " What about series?\n", " Sort Order:\n", " 1. protons\n", " 2. symbol\n", " 3. series\n", " \"\"\"\n", " print(\"Selected:\", sortby)\n", " \n", " if sortby == 1:\n", " ordered_elements = sorted(all_elements.values(), key = lambda k: k.protons)\n", " elif sortby == 2:\n", " ordered_elements = sorted(all_elements.values(), key = lambda k: k.symbol) \n", " elif sortby == 3:\n", " ordered_elements = sorted(all_elements.values(), key = lambda k: k.series)\n", " \n", " print(\"PERIODIC TABLE OF THE ELEMENTS\")\n", " print(\"-\" * 70)\n", " print(\"Symbol |Long Name |Protons |Mass |Series \" )\n", " print(\"-\" * 70)\n", " \n", " for the_atom in ordered_elements:\n", " print(\"{:6} | {:20} | {:6} | {:5.2f} | {:15}\".format(the_atom.symbol,\n", " the_atom.long_name,\n", " the_atom.protons,\n", " the_atom.mass,\n", " the_atom.series))\n", "\n", "print_periodic_table() # do it for real" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![by Kenneth Snelson](http://www.kennethsnelson.net/atom/3-Atom.jpg)\n", "
by Kenneth Snelson
" ] } ], "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.6.4" } }, "nbformat": 4, "nbformat_minor": 1 }