7

在 Python 中,您可以从定义类之外分配任意属性:

class Profile(models.Model):
    user = models.OneToOneField(User)  
    name = models.CharField(max_length=140)

p = Profile()
p.age = 42

这里的底层机制是__dict__维护所有属性的字典的属性。

我们都被告知不要将我们的内部工作暴露给客户端代码,但是附加数据根本与封装无关,对吧?这个成语在 Python 代码中很常见吗?


就是我的意思……</h2>

每个Tweet都有标准字段,例如id, text, owner
当返回一个用户的推文列表时,你想显示一条推文是否被这个用户“收藏”。

显然,要获得这个,is_favorite您需要查询多对多关系user
可以用当前用户对应的对象预填充Tweet对象is_favorite吗?

当然我可以公开一个方法is_favorite_for(user),但是我遇到了Django 模板语言限制,它不允许从模板内部调用带有参数的方法。另外,我相信模板根本不应该调用方法


我知道这会很好,但我想知道在开源项目中做这样的事情是否会让其他开发人员鄙视我。

边注:

我来自 C#/.NET 背景,其中动态类型是最近引入的,除了一些利基领域(互操作性、IoC 框架、REST 客户端框架等)外,并未得到广泛应用。

4

3 回答 3

7

我的观点是,这是一种不好的做法。

该对象不知道您在弄乱它的属性。例如,考虑一下,如果Profile后来扩展为在您的代码中拥有一个名为 的属性agep.age会发生什么情况。

如果要添加属性,为什么不使用子类,或者使用自定义属性对对象进行Profile外部映射?Profiles

于 2011-10-28T16:40:43.213 回答
4

我认为答案是:视情况而定。首先,如果你真的想阻止它,你可以通过__slots__在类中定义。添加未在类中实际定义的属性通常不是一个好习惯,因为它可能会使阅读代码的人感到困惑并且很少有用。

但在某些时候,能够做到这一点是很有用的,Python 文档将其作为一种获得类似于 C 结构或 Pascal Record 的方法来讨论(参见 http://docs.python.org/tutorial/classes.html根据第 9.7 节赔率和结束。)

于 2011-10-28T16:42:36.597 回答
3

If the attribute is only there sometimes, you risk getting an AttributeError out of nowhere for one object while the code worked fine for another object of the same class (yes, exact types aren't that important when duck-typing, but objects of the same class are frequently assumed to be of the same "duck type"). Even if it doesn't happen, you can't be sure just by looking at part of the code, and it's much harder to check in any case. So, doing this only makes your code less reliable.

Then there's the option of providing a default attribute as class attribute or property, only assigning an object attribute when it differs from the default. But for stuff that is expected to vary per object, the clarity of having every attribute ever listed in __init__ usually outweights any potential advantages of delaying instance attribute access.

That is not to say it's not acceptable, but you'd have to make a compelling argument for it to be considered a good idea.

于 2011-10-28T16:45:57.610 回答