
本文通过一个电商产品目录的实例,详解如何在python中正确实现solid中的依赖倒置原则(dip),重点解决因忽略静态方法声明导致的`typeerror: missing 1 required positional argument 'self'`错误。
在将Java风格的SOLID示例迁移至Python时,一个常见陷阱是机械翻译语法而忽略语言范式差异。上述错误的核心在于:Java中ProductFactory.create()被声明为static方法,不依赖实例状态;而Python中若未显式标注,def create()默认为实例方法,必须传入self参数——这正是报错missing 1 required positional argument: 'self'的根本原因。
要准确还原设计意图,需使用@staticmethod装饰器:
import zope.interface
class ProductRepository(zope.interface.Interface): # 修正拼写:Respository → Repository
def getAllProductNames(self) -> list:
pass
@zope.interface.implementer(ProductRepository)
class SQLProductRepository:
def getAllProductNames(self) -> list:
return ["soap", "toothpaste"]
class ProductFactory:
@staticmethod # ✅ 关键修正:声明为静态方法
def create() -> ProductRepository:
return SQLProductRepository()
class ProductCatalog:
def listAllProducts(self) -> None:
# ✅ 正确调用:无需实例化ProductFactory
product_repository = ProductFactory.create()
all_product_names = product_repository.getAllProductNames()
print(all_product_names)
# 执行
my_catalog = ProductCatalog()
my_catalog.listAllProducts() # 输出: ['soap', 'toothpaste']关键注意事项:
- 命名规范:ProductRespository 应修正为 ProductRepository(原Java代码中亦为ProductRepository),避免接口名拼写错误导致zope.interface校验失败;
- 工厂调用逻辑:Java中ProductFactory.create()是静态调用,Python对应ProductFactory.create()(无括号实例化),而非ProductFactory().create();
- 依赖注入更优实践:虽然本例使用静态工厂符合原始Java逻辑,但更符合Python惯用法及DIP精神的方式是构造函数注入——将ProductRepository实例作为参数传入ProductCatalog,从而彻底解耦对具体工厂的依赖;
- 接口非必需:Python为鸭子类型语言,zope.interface提供运行时契约检查,但若仅需轻量级抽象,可直接用抽象基类(abc.ABC)或纯协议(typing.Protocol,Python 3.8+)替代。
综上,理解“静态方法”在不同语言中的语义等价性,是跨语言践行SOLID原则的第一步。真正的依赖倒置不在于语法形式,而在于高层模块(ProductCatalog)不依赖低层细节(SQLProductRepository),而是共同依赖于抽象(ProductRepository接口)。
立即学习“Java免费学习笔记(深入)”;










