Python设计指导:

5 投票
2 回答
1116 浏览
提问于 2025-04-17 02:23

我是一名非常有经验的开发者,已经用Delphi、C#和C++做了很多复杂的工作好多年了。我一直非常遵循结构化编程、面向对象编程(OOP)、松耦合模块设计等原则。因为我用的这些语言都有内置的方式来强制执行这些概念,比如访问控制、静态类型、接口和抽象类支持等等,所以我依赖这些来组织我的代码。

最近,我开始玩Python几个月了。它有很多很棒的功能让我印象深刻,但我非常怀念那些内置的约束,这些约束能让我更容易保持代码的模块化和有序。不幸的是,我发现很多用Python写的“意大利面条代码”——也就是混乱不堪的代码,甚至来自一些很有声望的来源。我不想点名,但我有几本大牌Python专家写的书,里面的例子充满了让我感到不安的设计(更准确地说,是“反设计”)。在我看来,Python虽然很容易使用,但也很容易被滥用

我在用Python编码时尽量自律,但我发现要实现这些设计原则需要额外的努力,很多时候我只能依靠自己的记忆来设置和遵循约束,而语言本身并没有提供任何帮助。而且,由于没有“编译时”检查,这让事情变得更加困难——通常你要等到真正运行那段代码时才会发现设计上的缺陷。

所以,我在寻找非常具体的信息:一些例子,或者更好的是一本关于良好结构化Python设计和设计技巧的书——如何最好地实现封装、间接性、非常松耦合的设计等等。

在我看来,一位知名Python书籍作者的糟糕设计——(带有混淆)

def populateList(self, selecteddisk=None):
selected = None ***#Bundling - coupling:*** 
self.listWidget.clear()
for disk in self.disks.inOrder():
item = QListWidgetItem(QString("%1 of %2/%3 (%L4)") \
.arg(disk.name).arg(disk.owner).arg(disk.country) \
.arg(disk.teu))
self.listWidget.addItem(item)
***#Bundling - coupling:*** 
if selecteddisk is not None and selecteddisk == id(disk):
    selected = item
    if selected is not None:
    selected.setSelected(True)
    self.listWidget.setCurrentItem(selected)

2 个回答

2

关于设计模式支持

有一种观点认为,设计模式可以作为衡量编程语言不足之处的一个粗略标准。这将是一个有趣的阅读材料,也可以作为你提到的设计模式是语言支持的限制的反面观点。

2

我发现,要实现和编译符合设计要求的代码,光靠我自己的记忆而不借助语言的帮助,真的需要额外花费很多功夫。在写代码之前,语言本身并没有给我任何帮助。虽然一些集成开发环境(IDE)提供了一些帮助,但语言本身却没有。

而且,由于“编译时”检查似乎并不能帮我找到普通的逻辑错误,这让事情变得更加困难——通常你要等到真正运行那段代码时,才会发现设计上的缺陷。

Python的设计和设计技巧…… 如何最好地实现封装,

通过封装。在像Java和C++这样的语言中,“封装”意味着到处使用私有的东西。但在Python中,这种做法并不被支持。

我们都是成年人。

你仍然可以像在其他语言中那样进行封装,只是没有private这个词。

Python提供了属性、装饰器和重写__getattribute__的方法来实现各种封装技巧。

间接引用,

通过引用其他对象。我不太清楚你具体遇到了什么问题,但也许是你给某个函数传了错误类型的参数。避免这种情况的方法就是阅读你自己写的文档字符串。

非常松散耦合的设计等等。

通过依赖注入来实现。同样,Python在松散耦合方面的工作方式和其他语言是一样的。

你应该深入研究并大量使用文档字符串。

你可能还想使用https://www.sphinx-doc.org来从你的文档字符串生成漂亮的文档。

你也可以使用Python内置的help()函数来查看你在写代码时写的文档字符串。

撰写回答