Python编程使用有限状态机识别地址有效性

夏知夏
夏知夏
发布时间:2026-10-14| 5人浏览过
原创

本文介绍如何利用Python中的有限状态机(FSM)来识别和验证中国地址的有效性。通过定义状态和转移规则,程序可以判断地址字符串是否符合标准格式,如省、市、区、街道及门号段的正确组合。文章提供了具体的代码示例,展示了如何构建状态机以处理不同层级的地址信息,并讨论了其在实际应用中的局限性与扩展方式。

在收发快递填写地址时,我们常需手动输入地址供程序智能识别。标准地址格式通常为“xx省xx市xx县/区xx路xx号”,但有时也可简化为“xx市xx县/区xx路xx号”、“xx省xx县/区xx路xx号”或“xx市xx路xx号”。

然而,并非所有输入都是合法地址。例如,“xx省xx街道xx号”或“xx市xx省xx区xx号”这类组合属于无效地址。

核心问题在于:如何编程识别一个中国地址是否有效?

虽然人类大脑能一眼识别地址合法性,但对计算机而言却并非易事。根本原因在于,尽管地址描述看似简单,实则涉及较为复杂的上下文相关文法。

例如,“上海市北京东路xx号”与“南京市北京东路xx号”中,扫描到“北京东路”时,其后的门牌号是否构成正确地址取决于上下文,即城市名。

幸运的是,地址上下文相对有限。尽管可以暴力穷举所有省、市、区、街道的组合,但更有效的方法是使用有限状态机。

每一个有限状态机都包含一个开始状态、一个终止状态以及若干中间状态。每条弧上标注了从当前状态进入下一状态的条件。例如,若当前状态为“省”,遇到与“区”相关的词组则进入“区”状态;若遇到与“城市”相关的词组,则进入“市”状态。

如果一条地址能从状态机的开始状态出发,经过若干中间状态,最终到达终止状态,则该地址有效;否则无效。

例如,“xx市xx省xx区xx号”即为无效地址,因为无法从“市”状态直接转移到“省”状态。

接下来,我们通过一个简单的优先状态机来实现这一功能。代码中包含注释,易于理解。


from enum import Enum
def isAddress(address: str) -> bool:
 
    #定义状态
    State = Enum("State", [
        "STATE_INITIAL", #开始
        "STATE_PROVINCE", # 省
        "STATE_CITY", # 市
        "STATE_AREA", # 区 / 县
        "STATE_STREET", # 街道
        "STATE_NUM", #号
        "STATE_END", #结束
        "STATE_ILLEGAL", #错误状态
    ])
    def toAddressType(addr_slice : str) -> State:
        if "省" in addr_slice:
            return State.STATE_PROVINCE
        elif "市" in addr_slice:
            return State.STATE_CITY
        elif "区" in addr_slice or "县" in addr_slice:
            return State.STATE_AREA
        elif "路" in addr_slice or "街道" in addr_slice:
            return State.STATE_STREET
        elif "号" in addr_slice:
            return State.STATE_NUM
        else:
            return State.STATE_ILLEGAL   
    #定义状态转移   
    transfer = {
        #开始可以转为 省或市
        State.STATE_INITIAL: {
            State.STATE_PROVINCE, 
            State.STATE_CITY,
        },
        #省可以转 市或区县
        State.STATE_PROVINCE:{
            State.STATE_CITY,
            State.STATE_AREA,
        },
        #市可以转区或街道
        State.STATE_CITY: {
            State.STATE_AREA,
            State.STATE_STREET,
        },
        #区县可以转街道
        State.STATE_AREA: {
            State.STATE_STREET,
        },
        #街道可以转号或终止
        State.STATE_STREET: {
            State.STATE_NUM,
            State.STATE_END,
        },
        #号只能转终止
        State.STATE_NUM: {
            State.STATE_END,
        },
    } 
    st = State.STATE_INITIAL
    for ch in address:
        current_state = toAddressType(ch)
        if current_state not in transfer[st]:
            return False
        st = current_state 
     return st in [State.STATE_STREET, State.STATE_NUM,State.STATE_END] 
if __name__ == '__main__':
    address1 = ["江苏省","苏州市", "吴中区", "中山北路", "208号"]
    address2 = ["苏州市","吴中区", "中山北路", "208号"]
    address3 = ["苏州市","吴江区", "中山北路", "208号"]
    address4 = ["苏州市","吴江区","208号"]
    address5 = ["苏州市","中山北路"]
    assert isAddress(address1)
    assert isAddress(address2)
    assert isAddress(address3)
    assert isAddress(address5)
    assert isAddress(address4) == False
 

此处未对地址字符串进行分词,而是直接将地址写为列表形式,旨在说明状态机的实现与应用。上述代码仅能从格式上保证地址有效,并不能确保地址真实存在。若要判断地址是否真实有效,需建立包含全国所有省、市、区县、街道的哈希表,并将门牌号用范围表示,再进行状态转移判断。

上述代码中的`transfer`即为一个哈希表,相当于穷举了所有正确转移的情况。它涵盖了在任何情况下,对应任何输入所需转移的状态。

最后的话

本文分享了如何实现一个简单的有限状态机。

附有限状态机的开源实现:

django-fsm[1]

python-state-machine[2]

参考资料

[1]

django-fsm:

https://github.com/viewflow/django-fsm

[2]

python-state-machine:

https://github.com/jtushman/state_machine

以上就是Python编程使用有限状态机识别地址有效性的详细内容,更多关于Python之有限状态机识别地址的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。