所以,Python很乐意让我写这样的代码,
class A(): pass
a1 = A()
a2 = A()
a1.some_field = 5
a2.other_field = 7现在,当涉及到将对象传递给方法时,我已经学会了不再担心,并喜欢上了鸭子类型。我承认,允许一个类的不同实例拥有不同的字段有时会很方便。
我的问题是,我正在和一个由4个开发人员组成的团队构建一个中型web应用程序,我不禁认为向对象添加任意字段会使对应用程序状态的推理变得更加困难。
我想我的问题是:向对象添加任意字段的做法只是一种自然的扩展,还是应该避免的事情?
下面是一个具体的例子:
class Visitor():
def __init__(self, name, address, dob):
self.name = name
self.address = address
self.dob = dob
def summarize_visits(visits):
self.most_recent_visit = find_most_recent_visit(visits)在这种情况下,处理Visitor对象的代码必须知道这样一个事实,即visitor.most_recent_visit将引发一个AttributeError,除非有人以前对同一对象调用了summarize_visits。这看起来会导致很多if hasattr(...)块,不是吗?
发布于 2013-04-11 05:35:58
编写这样的代码实际上是Python最大的好处之一。我的经验法则是只在内部使用实例特定的字段(即,在一个函数中,并且仅在必要时),并且不期望它们被外部模块使用。
如果我的对象被其他人使用,我希望他们查看类定义,并在一个位置清楚地描绘出他们需要了解的关于其结构的所有内容。记住,explicit is better than implicit。
发布于 2013-04-11 05:26:45
这样做通常很方便,但我看到您担心这可能会导致与其他开发人员合作时的混乱。您可以通过按照讨论的here定义__slots__变量来阻止人们向类中添加任意值。这将迫使人们明确他们想要在对象中的属性,这可以帮助避免混淆。
发布于 2013-04-11 05:28:42
我相信Python对此的术语是“猴子修补”;以下是一些相关信息:
Stack Overflow - monkey patching
这样做的一个好处是,您的python代码非常动态;您可以添加字段来定制类、模块或任何具有属性的Python结构。
它的一个非常巧妙的用法是"Bunch“python配方,它定义了一个通用容器,可以使用关键字参数构造:
Bunch recipe
一个成本是潜在的维护问题;很难跟踪一个类或模块最后的“猴子补丁”在哪里。
当然,如果您真的喜欢鸭子类型,那么使用some_field和other_field的代码应该使用try/except来确保属性确实存在,并处理这两种情况。
在您的特定示例中,似乎可以将Visitor.most_recent_visits初始化为None或其他一些标记。如果你能在构造函数中将属性初始化为有意义的值,那么你应该这样做,并且只在极端情况下保留“猴子修补”。此外,对库类和函数进行简单的修补似乎也很麻烦。
https://stackoverflow.com/questions/15936615
复制相似问题