dingsir的个人博客分享 http://blog.sciencenet.cn/u/dingsir

博文

分享一个计算分子量的Python小工具

已有 1030 次阅读 2021-9-30 13:17 |个人分类:软件杂谈|系统分类:论文交流

平时工作需要时,常常需要用到原子量和分子量来计算一些结果,但往往又记得不太牢。因此为自己开发了这个python函数,有二个,一个根据元素的英文缩写返回原子量,另一个将分子式(不是结构式)解析为元素原子的个数,再结合原子量就可以计算出整个分子的分子量。

要注意的是,分子式中必须包含了所有元素,如果省去了氢原子,则结果肯定出错,因为我没有去判断这个式子在化学上是否完善,因此使用者要保证输入的分子式是完整和正确的。另外,元素的大小写也应是正确的。

class MyChemInfo():
    @staticmethod
    def AtomicWeight( element: str) -> float:
        """
        根据元素名称返回其原子量,区分大小写的
        """
        if  len(element)>2:  # 元素名称长度不应超过2个字符.
            return None
        return { #该原子量数据从CRC手册第95版提取。
            "H":  1.008,
            "He":  4.002602,
            "Li":  6.94,
            "Be":  9.0121831,
            "B":  10.81,
            "C":  12.011,
            "N":  14.007,
            "O":  15.999,
            "F":  18.998403163,
            "Ne":  20.1797,
            "Na":  22.98976928,
            "Mg":  24.305,
            "Al":  26.9815385,
            "Si":  28.085,
            "P":  30.973761998,
            "S":  32.06,
            "Cl":  35.45,
            "Ar":  39.948,
            "K":  39.0983,
            "Ca":  40.078,
            "Sc":  44.955908,
            "Ti":  47.867,
            "V":  50.9415,
            "Cr":  51.9961,
            "Mn":  54.938044,
            "Fe":  55.845,
            "Co":  58.933194,
            "Ni":  58.6934,
            "Cu":  63.546,
            "Zn":  65.38,
            "Ga":  69.723,
            "Ge":  72.63,
            "As":  74.921595,
            "Se":  78.971,
            "Br":  79.904,
            "Kr":  83.798,
            "Rb":  85.4678,
            "Sr":  87.62,
            "Y":  88.90584,
            "Zr":  91.224,
            "Nb":  92.90637,
            "Mo":  95.95,
            "Ru":  101.07,
            "Rh":  102.9055,
            "Pd":  106.42,
            "Ag":  107.8682,
            "Cd":  112.414,
            "In":  114.818,
            "Sn":  118.71,
            "Sb":  121.76,
            "Te":  127.6,
            "I":  126.90447,
            "Xe":  131.293,
            "Cs":  132.90545196,
            "Ba":  137.327,
            "La":  138.90547,
            "Ce":  140.116,
            "Pr":  140.90766,
            "Nd":  144.242,
            "Sm":  150.36,
            "Eu":  151.964,
            "Gd":  157.25,
            "Tb":  158.92535,
            "Dy":  162.5,
            "Ho":  164.93033,
            "Er":  167.259,
            "Tm":  168.93422,
            "Yb":  173.054,
            "Lu":  174.9668,
            "Hf":  178.49,
            "Ta":  180.94788,
            "W":  183.84,
            "Re":  186.207,
            "Os":  190.23,
            "Ir":  192.217,
            "Pt":  195.084,
            "Au":  196.966569,
            "Hg":  200.592,
            "Tl":  204.38,
            "Pb":  207.2,
            "Bi":  208.9804,
            "Th":  232.0377,
            "Pa":  231.03588,
            "U":  238.02891,
            "Tc":  0,  #有些放射性元素的原子量没有提供,以0表示。
            "Pm":  0,
            "Po":  0,
            "At":  0,
            "Rn":  0,
            "Fr":  0,
            "Ra":  0,
            "Ac":  0,            
            "Np":  0,
            "Pu":  0,
            "Am":  0,
            "Cm":  0,
            "Bk":  0,
            "Cf":  0,
            "Es":  0,
            "Fm":  0,
            "Md":  0,
            "No":  0,
            "Lr":  0,
            "Rf":  0,
            "Db":  0,
            "Sg":  0,
            "Bh":  0,
            "Hs":  0,
            "Mt":  0,
            "Ds":  0,
            "Rg":  0,
            "Cn":  0,
            "Fl":  0,
            "Lv":  0}.get(element, 0.000)        
    
    @staticmethod    
    def MolWt(formula:str) -> float:
        regStr="([A-Z]{1}[a-z]{0,1})([0-9]{0,3})"   #解析化学式的正则表达式 
        MatchList=re.findall(regStr, formula)
        cntMatchList=len(MatchList)
        i=0
        mW=0.000
        while i < cntMatchList:
            eleName=MatchList[i][0]
            eleCount= int(MatchList[i][1]) if len(MatchList[i][1])>0 else 1
            aw=MyChemInfo.AtomicWeight(eleName)
            if (aw==0): #防止错误表示不能及时识别出来。
                return 0
            mW += aw*eleCount
            i=i+1
        return mW

因为我用xlwings库来连接Excel,还有一点小代码将上面的类函数变成Excel可以访问的普通函数

@xw.func
def AW(element):
    return mC.MyChemInfo.AtomicWeight(element)

@xw.func
def mw(formula):
    return mC.MyChemInfo.MolWt(formula)


在Excel里面调用的结果做个演示如下

分子式计算结果演示.png

代码比较简单,因此只能处理比较简单的情况,带括号的复合基团处理不了。

上图中EC因为不是规范的分子式而是缩写,计算结果就以0来提示出错了。


最后贴一张元素周期表,可以在新页面打开看原始尺寸的,有原子量与元素符号、常见价态、常温常压下的形态等信息。---现在的网络太过分了,查个原子量表都要花钱买文档,一股子浓浓的铜臭味。


元素周期表.png



https://wap.sciencenet.cn/blog-1213210-1306286.html

上一篇:安全驾驶体会25条 (更新于2021-9-29)
下一篇:自定义ChemDraw的快捷键

1 郑永军

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2021-12-7 01:24

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部