Skip to main content
 首页 » 编程设计

用于字符串的内部 API 的 Pythonic 方法

2025年05月04日17落叶无声

问题

是否有一种“pythonic”(即规范的、官方的、PEP8 批准的等)方式在 python 内部(和外部)API 中重用字符串文字?


背景

例如,我正在处理一些(不一致的)JSON 处理代码(数千行),其中有我们组装、解析等各种 JSON“structs”。其中之一在代码审查期间反复出现的问题是不同的 JSON struct 使用相同的内部参数名称,导致混淆并最终导致错误出现,例如:

pathPacket['src'] = "/tmp" 
pathPacket['dst'] = "/home/user/out" 
urlPacket['src'] = "localhost" 
urlPacket['dst'] = "contoso" 

这两个(示例)数据包具有数十个同名字段,但它们代表非常不同类型的数据。此实现没有代码重用理由。人们通常使用代码完成引擎来获取 JSON struct 的成员,这最终会导致难以调试的问题,因为错误键入的字符串文字会导致功能问题,而不是早些时候触发错误。当我们必须更改这些 API 时,需要花费大量时间来查找字符串文字以找出哪些 JSON struct 使用了哪些字段。


问题 - Redux

python 社区成员之间是否有更好的通用方法?如果我在 C++ 中执行此操作,则前面的示例将类似于:

const char *JSON_PATH_SRC = "src"; 
const char *JSON_PATH_DST = "dst"; 
const char *JSON_URL_SRC = "src"; 
const char *JSON_URL_DST = "dst"; 
// Define/allocate JSON structs 
pathPacket[JSON_PATH_SRC] = "/tmp"; 
pathPacket[JSON_PATH_DST] = "/home/user/out"; 
urlPacket[JSON_URL_SRC] = "localhost"; 
urlPacket[JSON_URL_SRC] = "contoso"; 

我最初的做法是:

  • 使用abc创建一个不能作为对象初始化的抽象基类,并用只读常量填充它.
  • 将该类用作整个项目的通用模块。
  • 通过使用这些常量,我可以减少猴子修补错误的可能性,因为如果拼写错误,符号将不存在,而字符串文字拼写错误可能会通过代码审查。

我提出的解决方案(接受建议/批评)

from abc import ABCMeta 
 
class Custom_Structure: 
    __metaclass__ = ABCMeta 
 
    @property 
    def JSON_PATH_SRC(): 
        return self._JSON_PATH_SRC 
 
    @property 
    def JSON_PATH_DST(): 
        return self._JSON_PATH_DST 
 
    @property 
    def JSON_URL_SRC(): 
        return self._JSON_URL_SRC 
 
    @property 
    def JSON_URL_DST(): 
        return self._JSON_URL_DST 

请您参考如下方法:

通常的做法是:

JSON_PATH_SRC = "src" 
JSON_PATH_DST = "dst" 
JSON_URL_SRC = "src" 
JSON_URL_DST = "dst" 
 
 
pathPacket[JSON_PATH_SRC] = "/tmp" 
pathPacket[JSON_PATH_DST] = "/home/user/out" 
urlPacket[JSON_URL_SRC] = "localhost" 
urlPacket[JSON_URL_SRC] = "contoso" 

大写表示“常量”是它的方式。你会在标准库中看到它,它甚至在 PEP8 中被推荐。 :

Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples include MAX_OVERFLOW and TOTAL.

Python 没有真正的常量,而且它似乎没有它们也能生存下来。如果将它包装在一个使用 ABCmeta 属性的类中会让您感觉更舒服,那就继续吧。事实上,我很确定 abc.ABCmeta 不会不会阻止对象初始化。事实上,如果它确实,您对property 的使用将不起作用! property 对象属于类,但要从实例访问。对我来说,它看起来就像是大量的 rigamarole,却收获甚微。