【发布时间】:2021-12-14 07:21:14
【问题描述】:
我正在学习 Python,我正在尝试遍历在用户键入化学式时创建的化合物列表。例如,如果一个水分子的化学式是 H2O,那么化合物列表将是:
list = [
['H', 2],
['O', 1]
]
如果化合物葡萄糖的化学式为 C6H12O6,则化合物列表将为:
list = [
['C', 6],
['H', 12],
['O', 6]
]
我想遍历整个化合物列表并计算列表中每个元素的质量百分比并将它们显示给用户,无论用户输入多少元素。我的代码遇到的问题是当我尝试计算复合列表中每个元素的质量百分比时,它只提取列表中的最后一个元素并仅针对该元素执行计算。因此,当我为葡萄糖输入 C6H12O6 时,它只会对 O 或 Oxygen 执行计算,但我也想对 Carbon 和 Hydrogen 执行其他计算。我的函数计算质量百分比执行计算,但我不确定它是否适用于我想要完成的任务。我需要在函数中完成这一切,而其他函数必须保持原样。我也无法更改包含所有元素及其相关原子质量在函数 make 周期表中的非常长的字典。我真正可以更改的唯一函数是我的计算质量百分比函数以及它在 main() 函数中的调用方式。
这是我从化学式计算元素质量百分比的方法。在这个例子中,我得到了葡萄糖中碳的质量百分比。
将公式中每个元素的原子数求和为葡萄糖:
6 carbon atoms
12 hydrogen atoms
6 oxygen atoms
求每个元素的原子质量: 符号名称 原子质量
C Carbon 12.0107
H Hydrogen 1.00794
O Oxygen 15.9994
将原子数乘以它们的原子质量:
6 × 12.0107 = 72.0642
12 × 1.00794 = 12.09528
6 × 15.9994 = 95.9964
将乘法的结果相加得到葡萄糖的摩尔质量:
72.0642 + 12.09528 + 95.9964 = 180.15588 grams/mole
现在我们将得到葡萄糖中碳的质量百分比,而不是葡萄糖样品中的摩尔数:
72.0642 / 180.15588 = 0.40001026 or 40%
因此,碳占葡萄糖质量的 40%。
这是我的程序代码。顺便说一句,我只知道如何用 Python 编写代码。非常感谢任何帮助。
ELEMENT_SYMBOL = 0
ATOMS = 1
def main():
# Get a chemical formula for a molecule from the user.
chemical_formula = input("Enter the molecular formula of the sample: ").title()
# Get a mass in grams from the user.
mass = float(input("Enter the mass in grams of the sample: "))
# Call the make_periodic_table function and
# store the periodic table in a variable.
dictionary = make_periodic_table()
# Call the parse_formula function to convert the
# chemical formula given by the user to a compound
# list that stores element symbols and the quantity
# of atoms of each element in the molecule.
element_group = parse_formula(chemical_formula, dictionary)
# Call the compute_molar_mass function to compute the
# molar mass of the molecule from the compound list.
molar_mass = compute_molar_mass(element_group, dictionary)
# Call the compute_mass_percentage function to compute the
# mass percentage of the molecule from the compound list.
mass_percent = compute_mass_percentage(element_group, dictionary)
# Compute the number of moles of the sample.
moles = mass / molar_mass
# Print the molar mass.
print(f"{molar_mass:.5f} grams/mole")
# Print the number of moles.
print(f"{moles:.5f} moles")
print(parse_formula(chemical_formula, dictionary))
print(f"{mass_percent}")
def make_periodic_table():
table = {
"Ac": ["Actinium", 227],
"Ag": ["Silver", 107.8682],
"Al": ["Aluminum", 26.9815386],
"Am": ["Americium", 243],
"Ar": ["Argon", 39.948],
"As": ["Arsenic", 74.9216],
"At": ["Astatine", 210],
"Au": ["Gold", 196.966569],
"B": ["Boron", 10.811],
"Ba": ["Barium", 137.327],
"Be": ["Beryllium", 9.012182],
"Bh": ["Bohrium", 272],
"Bi": ["Bismuth", 208.9804],
"Bk": ["Berkelium", 247],
"Br": ["Bromine", 79.904],
"C": ["Carbon", 12.0107],
"Ca": ["Calcium", 40.078],
"Cd": ["Cadmium", 112.411],
"Ce": ["Cerium", 140.116],
"Cf": ["Californium", 251],
"Cl": ["Chlorine", 35.453],
"Cm": ["Curium", 247],
"Cn": ["Copernicium", 285],
"Co": ["Cobalt", 58.933195],
"Cr": ["Chromium", 51.9961],
"Cs": ["Cesium", 132.9054519],
"Cu": ["Copper", 63.546],
"Db": ["Dubnium", 268],
"Ds": ["Darmstadtium", 281],
"Dy": ["Dysprosium", 162.5],
"Er": ["Erbium", 167.2590],
"Es": ["Einsteinium", 252],
"Eu": ["Europium", 151.964],
"F": ["Fluorine", 18.9984032],
"Fe": ["Iron", 55.845],
"Fl": ["Flerovium", 289],
"Fm": ["Fermium", 257],
"Fr": ["Francium", 223],
"Ga": ["Gallium", 69.723],
"Gd": ["Gadolinium", 157.25],
"Ge": ["Germanium", 72.64],
"H": ["Hydrogen", 1.00794],
"He": ["Helium", 4.002602],
"Hf": ["Hafnium", 178.49],
"Hg": ["Mercury", 200.59],
"Ho": ["Holmium", 164.93032],
"Hs": ["Hassium", 270],
"I": ["Iodine", 126.90447],
"In": ["Indium", 114.818],
"Ir": ["Iridium", 192.217],
"K": ["Potassium", 39.0983],
"Kr": ["Krypton", 83.798],
"La": ["Lanthanum", 138.90547],
"Li": ["Lithium", 6.941],
"Lr": ["Lawrencium", 262],
"Lu": ["Lutetium", 174.9668],
"Lv": ["Livermorium", 293],
"Mc": ["Moscovium", 288],
"Md": ["Mendelevium", 258],
"Mg": ["Magnesium", 24.305],
"Mn": ["Manganese", 54.938045],
"Mo": ["Molybdenum", 95.96],
"Mt": ["Meitnerium", 276],
"N": ["Nitrogen", 14.0067],
"Na": ["Sodium", 22.98976928],
"Nb": ["Niobium", 92.90638],
"Nd": ["Neodymium", 144.242],
"Ne": ["Neon", 20.1797],
"Nh": ["Nihonium", 284],
"Ni": ["Nickel", 58.6934],
"No": ["Nobelium", 259],
"Np": ["Neptunium", 237],
"O": ["Oxygen", 15.9994],
"Og": ["Oganesson", 294],
"Os": ["Osmium", 190.23],
"P": ["Phosphorus", 30.973762],
"Pa": ["Protactinium", 231.03588],
"Pb": ["Lead", 207.2],
"Pd": ["Palladium", 106.42],
"Pm": ["Promethium", 145],
"Po": ["Polonium", 209],
"Pr": ["Praseodymium", 140.90765],
"Pt": ["Platinum", 195.084],
"Pu": ["Plutonium", 244],
"Ra": ["Radium", 226],
"Rb": ["Rubidium", 85.4678],
"Re": ["Rhenium", 186.207],
"Rf": ["Rutherfordium", 267],
"Rg": ["Roentgenium", 280],
"Rh": ["Rhodium", 102.9055],
"Rn": ["Radon", 222],
"Ru": ["Ruthenium", 101.07],
"S": ["Sulfur", 32.065],
"Sb": ["Antimony", 121.76],
"Sc": ["Scandium", 44.955912],
"Se": ["Selenium", 78.96],
"Sg": ["Seaborgium", 271],
"Si": ["Silicon", 28.0855],
"Sm": ["Samarium", 150.36],
"Sn": ["Tin", 118.71],
"Sr": ["Strontium", 87.62],
"Ta": ["Tantalum", 180.94788],
"Tb": ["Terbium", 158.92535],
"Tc": ["Technetium", 98],
"Te": ["Tellurium", 127.6],
"Th": ["Thorium", 232.03806],
"Ti": ["Titanium", 47.867],
"Tl": ["Thallium", 204.3833],
"Tm": ["Thulium", 168.93421],
"Ts": ["Tennessine", 294],
"U": ["Uranium", 238.02891],
"V": ["Vanadium", 50.9415],
"W": ["Tungsten", 183.84],
"Xe": ["Xenon", 131.293],
"Y": ["Yttrium", 88.90585],
"Yb": ["Ytterbium", 173.054],
"Zn": ["Zinc", 65.38],
"Zr": ["Zirconium", 91.224]
}
return table
class FormulaError(ValueError):
"""FormulaError is the type of error that
parse_formula will raise if a formula is invalid.
"""
pass
def parse_formula(formula, periodic_table_dict):
"""Convert a chemical formula for a molecule into a compound list
that stores the quantity of atoms of each element in the molecule.
For example, this function will convert "H2O" to [["H", 2], ["O", 1]]
and "PO4H2(CH2)12CH3" to [["P", 1], ["O", 4], ["H", 29], ["C", 13]]
"""
def parse_quant(formula, index):
quant = 1
if index < len(formula) and formula[index].isdecimal():
start = index
index += 1
while index < len(formula) and formula[index].isdecimal():
index += 1
quant = int(formula[start:index])
return quant, index
def get_quant(elems, symbol):
return 0 if symbol not in elems else elems[symbol]
def parse_r(formula, index, level):
start_index = index
start_level = level
elem_dict = {}
while index < len(formula):
ch = formula[index]
if ch == "(":
group_dict, index = parse_r(formula, index+1, level+1)
quant, index = parse_quant(formula, index)
for symbol in group_dict:
prev = get_quant(elem_dict, symbol)
elem_dict[symbol] = prev + group_dict[symbol] * quant
elif ch.isalpha():
symbol = formula[index:index+2]
if symbol in periodic_table_dict:
index += 2
else:
symbol = formula[index:index+1]
if symbol in periodic_table_dict:
index += 1
else:
raise FormulaError(
"invalid formula, unknown element symbol:",
formula, index)
quant, index = parse_quant(formula, index)
prev = get_quant(elem_dict, symbol)
elem_dict[symbol] = prev + quant
elif ch == ")":
if level == 0:
raise FormulaError(
"invalid formula, unmatched close parenthesis:",
formula, index)
level -= 1
index += 1
break
else:
if ch.isdecimal():
# Decimal digit not preceded by an
# element symbol or close parenthesis
message = "invalid formula:"
else:
# Illegal character: [^()0-9a-zA-Z]
message = "invalid formula, illegal character:"
raise FormulaError(message, formula, index)
if level > 0 and level >= start_level:
raise FormulaError(
"invalid formula, unmatched open parenthesis:",
formula, start_index - 1)
return elem_dict, index
# Return the compound list of element symbols and
# quantities. Each element in the compound list
# will be a list in this form: ["symbol", quantity]
elem_dict, _ = parse_r(formula, 0, 0)
return list(elem_dict.items())
# These are the indexes of the
# elements in the periodic table.
NAME_INDEX = 0
ATOMIC_MASS_INDEX = 1
def compute_molar_mass(symbol_quantity_list, periodic_table_dict):
"""Compute and return the total molar mass of all the
elements listed in symbol_quantity_list. Each element in
symbol_quantity_list is a list in the form: ["symbol", quantity].
As an example, if symbol_quantity_list is [["H", 2], ["O", 1]],
this function will calculate and return
atomic_mass("H") * 2 + atomic_mass("O") * 1
1.00794 * 2 + 15.9994 * 1
18.01528
"""
total_mass = 0.0
for element in symbol_quantity_list:
symbol = element[ELEMENT_SYMBOL]
quantity = element[ATOMS]
atomic_mass = periodic_table_dict[symbol][ATOMIC_MASS_INDEX]
total_mass += atomic_mass * quantity
return total_mass
# For each element in the symbol_quantity_list:
# Split the element into symbol and quantity.
# Get the atomic mass for the symbol.
# Multiply the atomic mass by the quantity.
# Add the product into the total mass.
def compute_mass_percentage(symbol_quantity_list, periodic_table_dict):
total_mass = 0.0
mass_percent = 0.0
for element in symbol_quantity_list:
symbol = element[ELEMENT_SYMBOL]
quantity = element[ATOMS]
atomic_mass = periodic_table_dict[symbol][ATOMIC_MASS_INDEX]
element_mass = quantity * atomic_mass
total_mass += atomic_mass * quantity
mass_percent = element_mass / total_mass
return mass_percent
if __name__ == "__main__":
main()
【问题讨论】:
-
请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。
标签: python-3.x dictionary for-loop iteration nested-lists