# Atoms in Python

Python for STEM Teachers
Oregon Curriculum Network

# Atoms R Us

``````

In [1]:

import json

series_types = ["Don't Know", "Other nonmetal", "Alkali metal",
"Alkaline earth metal", "Nobel gas", "Metalloid",
"Halogen", "Transition metal", "Post-transition metal",
"Lanthanoid", "Actinoid"]

class Element:
fields = "protons symbol long_name mass series"
repstr = ("Atom(protons={protons}, symbol='{symbol}', "
"long_name='{long_name}', "
"mass={mass}, series='{series}')")

def __init__(self, protons: int, symbol: str,
long_name: str, mass: float, series: str):

# build self.__dict__
self.protons = protons
self.symbol = symbol
self.long_name = long_name
self.__dict__['mass'] = mass # same idea
self.series = series

def __getitem__(self, idx):  # simulates collection.namedtuple behavior
return self.__dict__[self.fields[idx]]

def __repr__(self):
return self.repstr.format(**self.__dict__)

Atom = Element # synonyms

lithium = Atom(3, "Li", "Lithium", 6.941, "Alkali metal")
print(lithium)  # __str__, then __repr__
print(lithium.__dict__)
print(lithium.protons)  # print(lithium.__getattr__('protons'))

``````
``````

Atom(protons=3, symbol='Li', long_name='Lithium', mass=6.941, series='Alkali metal')
{'protons': 3, 'symbol': 'Li', 'long_name': 'Lithium', 'mass': 6.941, 'series': 'Alkali metal'}
3

``````
``````

In [2]:

import unittest

class Test_Element(unittest.TestCase):

def test_instance(self):
lithium = Atom(3, "Li", "Lithium", 6.941, "Alkali metal")
self.assertEqual(lithium.protons, 3, "Houston, we have a problem")

a = Test_Element()  # the test suite
unittest.TextTestRunner().run(suite)  # run the test suite

``````
``````

.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

Out[2]:

<unittest.runner.TextTestResult run=1 errors=0 failures=0>

``````
``````

In [5]:

class ElementEncoder(json.JSONEncoder):
"""
See:  https://docs.python.org/3.5/library/json.html
"""
def default(self, obj):
if isinstance(obj, Element):  # how to encode an Element
return [obj.protons, obj.symbol, obj.long_name, obj.mass, obj.series]
return json.JSONEncoder.default(self, obj) # just do your usual

# Element = namedtuple("Atom", "protons abbrev long_name mass")

global all_elements  # <--- will be visible to entire module
try:
the_file = "periodic_table.json"
f = open(the_file, "r") # <--- open the_file instead
except IOError:
print("Sorry, no such file!")
else:
f.close()
all_elements = {}
for symbol, data in the_dict.items():
all_elements[symbol] = Atom(*data) # "explode" data into 5 inputs

``````
``````

``````

graphic by Kenneth Snelson
``````

In [6]:

def print_periodic_table(sortby=1):
"""
sort all_elements by number of protons, ordered_elements local only
Sort Order:
1. protons
2. symbol
3. series
"""
print("Selected:", sortby)

if sortby == 1:
ordered_elements = sorted(all_elements.values(), key = lambda k: k.protons)
elif sortby == 2:
ordered_elements = sorted(all_elements.values(), key = lambda k: k.symbol)
elif sortby == 3:
ordered_elements = sorted(all_elements.values(), key = lambda k: k.series)

print("PERIODIC TABLE OF THE ELEMENTS")
print("-" * 70)
print("Symbol |Long Name             |Protons |Mass   |Series  " )
print("-" * 70)

for the_atom in ordered_elements:
print("{:6} | {:20} | {:6} | {:5.2f} | {:15}".format(the_atom.symbol,
the_atom.long_name,
the_atom.protons,
the_atom.mass,
the_atom.series))

print_periodic_table()  # do it for real

``````
``````

Selected: 1
PERIODIC TABLE OF THE ELEMENTS
----------------------------------------------------------------------
Symbol |Long Name             |Protons |Mass   |Series
----------------------------------------------------------------------
H      | Hydrogen             |      1 |  1.01 | Other nonmetal
He     | Helium               |      2 |  4.00 | Nobel gas
Li     | Lithium              |      3 |  6.94 | Alkali metal
Be     | Beryllium            |      4 |  9.01 | Alkaline earth metal
B      | Boron                |      5 | 10.81 | Metalloid
C      | Carbon               |      6 | 12.01 | Noble gas
N      | Nitrogen             |      7 | 14.01 | Other nonmetal
O      | Oxygen               |      8 | 16.00 | Other nonmetal
F      | Fluorine             |      9 | 19.00 | Metalloid
Ne     | Neon                 |     10 | 20.18 | Noble gas
Na     | Sodium               |     11 | 22.99 | Alkali metal
Mg     | Magnesium            |     12 | 24.30 | Alkaline earth metal
Al     | Aluminum             |     13 | 26.98 | Post-transition metal
Si     | Silicon              |     14 | 28.09 | Metalloid
P      | Phosphorous          |     15 | 30.97 | Other nonmetal
S      | Sulfur               |     16 | 32.06 | Other nonmetal
Cl     | Chlorine             |     17 | 35.45 | Halogen
Ar     | Argon                |     18 | 39.95 | Nobel gas
K      | Potassium            |     19 | 39.10 | Alkali metal

``````

by Kenneth Snelson