I'm new to programming, especially Python (started in python3) and I want to ask if this piece of code is good enough or not. This is part of my personal project, that is, to make a personal library on chemistry. Also, if this is allowed, I want to ask if, for the following code, lookup is better than calculation.
This is a function that can give either the full or compact electron configuration given the number of electrons (electrons
). In this function, the full configuration depends on the compact configuration.
To get the compact configuration, the greatest number of electrons in the inert elements less than the given number of electrons is found (inert_number
). The 'position' of the writer with respect to the subshells is determined based on inert_number
(subshell_index
). From subshell_index
, the number of electrons per subshells is given (base
). Subtracting inert_number
from electrons
, we have copy
. A loop will start which will end if base >= copy
. The result will be a list starting with the atomic symbol of the element in square brackets (inert_head
), followed by the remaining electrons in subshells. The exceptions to this are the elements with unusual configurations where their configurations are found through a lookup and the first two elements whose compact configurations do not start with an atomic symbol.
To get the full configuration, the compact configuration will be taken first. While the first element of the configuration is an atomic symbol, the process will be recursive. The first element will be taken, making a lookup to get the atomic number and the compact configuration will be found. The results of this will be appended to get the full configuration.
inerts_number = [2, 10, 18, 36, 54, 86, 118]
inerts_config_index = [1, 3, 5, 8, 11, 15, 19]
atomic_symbols = [
"H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne",
"Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca",
"Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn",
"Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr",
"Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn",
"Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd",
"Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb",
"Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg",
"Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th",
"Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm",
"Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds",
"Rg", "Cn", "Nh", "Fl", "Mc", "Lv", "Ts", "Og"]
elems_with_odd_configs = [
24, 29, 41, 42, 44,
45, 46, 47, 57, 58,
64, 78, 79, 89, 90,
91, 92, 93, 96]
configs_of_odds = [
["[Ar]", 1, 5],
["[Ar]", 1, 10],
["[Kr]", 1, 4],
["[Kr]", 1, 5],
["[Kr]", 1, 7],
["[Kr]", 1, 8],
["[Kr]", 0, 10],
["[Kr]", 1, 10],
["[Xe]", 2, 0, 1],
["[Xe]", 2, 1, 1],
["[Xe]", 2, 7, 1],
["[Xe]", 1, 14, 9],
["[Xe]", 1, 14, 10],
["[Rn]", 2, 0, 1],
["[Rn]", 2, 0, 2],
["[Rn]", 2, 2, 1],
["[Rn]", 2, 3, 1],
["[Rn]", 2, 4, 1],
["[Rn]", 2, 7, 1]]
subshell_value = [
2, 2, 6, 2, 6,
2, 10, 6, 2, 10,
6, 2, 14, 10, 6,
2, 14, 10, 6]
def electron_config(electrons: int, config_type: str = 'compact') -> list:
def __compact_config(electrons: int) -> list:
electron_config = []
inert_number = 0
subshell_index = 0
if electrons > 2:
inert_number = max([x for x in inerts_number if x < electrons])
subshell_index = inerts_config_index[inerts_number.index(inert_number)]
inert_head = f'[{atomic_symbols[inert_number - 1]}]'
electron_config.append(inert_head)
else:
inert_number = 0
if electrons in elems_with_odd_configs:
return configs_of_odds[elems_with_odd_configs.index(electrons)]
else:
copy = electrons - inert_number
if electrons > 2:
index = subshell_index
else:
copy = electrons
index = 0
while True:
base = subshell_value[index]
if base < copy:
electron_config.append(base)
copy -= base
index += 1
else:
if copy > 0:
electron_config.append(copy)
break
return electron_config
def __full_config(electrons: int) -> list:
temp_config = []
compact_config = __compact_config(electrons)
inert_elem = ''
if electrons > 2:
inert_elem = str(compact_config[0]).removeprefix('[').removesuffix(']')
inert_electrons = atomic_symbols.index(inert_elem) + 1
if inert_elem in ['He', 'Ne', 'Ar', 'Kr', 'Xe', 'Rn']:
temp_config = __full_config(inert_electrons) + compact_config[1:]
else:
temp_config = __compact_config(electrons)
return temp_config
if config_type == 'compact':
return __compact_config(electrons)
elif config_type == 'full':
return __full_config(electrons)
else:
raise ValueError(f'Expected \'compact\' or \'full\', received {config_type} instead')
An alternative way I did was to add inert_number
and subshell_index
as optional parameters to __compact_config
with None
as default values. If both are None
, proceed as usual. Then, to get the full configuration, __compact_config
will be called and inert_number = 0
, subshell_index
= 0. This will be the changes:
...
def __compact_config(electrons: int, inert_number: int = None, subshell_index: int = None) -> list:
...
if inert_number is None and subshell_index is None:
if electrons > 2:
inert_number = max([x for x in inerts_number if x < electrons])
subshell_index = inerts_config_index[inerts_number.index(inert_number)]
inert_head = f'[{atomic_symbols[inert_number - 1]}]'
electron_config.append(inert_head)
else:
inert_number = 0
...
def __full_config(electrons: int) -> list:
return __compact_config(electrons, inert_number = 0, subshell_index = 0)
In __full_config
, is it better to use the recursive way to show what the 'usual' way is when finding the electron configuration, or start from the first subshell using the writer from __compact_config
?