在运行时向类中添加方法而不是子类化是否存在缺陷?

2024-05-18 15:46:41 发布

您现在位置:Python中文网/ 问答频道 /正文

从django1.5开始,现在已经内置了对用户模型子类化的支持,以添加自定义功能,但是仍然有一些兼容性方面的考虑,这意味着我不希望这样做。在1.5之前,子类化是一个大麻烦。但是,我需要一些功能,特别是方法的形式,.full\u name()。它返回用户的first + " " + middle + " " +last名称。更一般地说,它只在适当的地方放置空格,可以处理中间名,但不要求模型包含中间名。你知道吗

现在,我不再使用子类User,而是在我的型号.py地址:

def full_name(self):                                    # Here's a useful full_name method
    '''Return the full name of an object, or else an empty string. Can be applied to objects with first_name, last_name and optionally middle_name fields'''
    fullname = self.first_name
    try:
        self.middle_name
    except AttributeError:                          # this type of object might not have a middle_name field
        pass
    else:                                           # If it has a middle_name field, append it with a conditional space
        if(self.first_name and self.middle_name):
            fullname += " "
        fullname += self.middle_name
    if(fullname and self.last_name):                # if fullname has stuff in it now, we'll need a space.
            fullname += " "
    fullname += self.last_name
    return fullname
User.full_name = full_name                              # Bless the User model with our full_name function

一般来说,我对Python还比较陌生,所以我很高兴地发现这是可行的。通过对其他几个模型使用相同的函数,我节省了一些时间(在后面的类定义中简单地描述full\u name=full\u name)型号.py). 也许现在中间名功能更有意义了——其他模型都有中间名。你知道吗

我的问题是,这种做法与子类化相比,有什么本质上的错误吗?大概主要的缺点是我不能用这种方式向模型中添加字段。但就是这样吗?此方法添加似乎在应用程序的其余部分以及导入用户的任何其他模块(具体来说,模板按预期工作)中始终存在。你知道吗

基本上,我认为这是一个相当聪明和优雅(虽然我肯定不是新奇)的方式来解决我的问题,需要更多的功能,但它会回来咬我以后?你知道吗

进一步的细节:我问这个问题的一个原因是我有一些用户角色(我们称它们为Painter、Clerk和Manager),它们具有models.ForeignKey(User, blank=True)关系。比如说,用户.painter可以返回一个Painter角色,但如果用户实际上不是Painter,它也可能引发ObjectNotFound异常。我不想在代码中乱放try:except:statements,而是想扩展我对上述概念的使用,例如,向用户添加.is\u painter()和.is\u manager()方法,这样我就可以简单地在if语句中查询这些方法,而不必做太多的修改尝试:除了:到处乱七八糟。你知道吗


Tags: and方法用户name模型self功能middle
1条回答
网友
1楼 · 发布于 2024-05-18 15:46:41

这被称为monkey patching。正如你可能已经从它的不太讨人喜欢的名字,并不总是被看好。在Python社区中,这不是一种常见的技术,通常是在没有其他选择时保留的。因为您有一个合适的接口(子类化)来实现您想要的,所以最好避免使用它。你知道吗

猴子补丁可能是脆弱的,如果你正在修改的模块在你下面发生了变化,就会被破坏。其他人可能很难在以后进行修改/调试,因为代码的实际位置并不总是显而易见的。你知道吗

也就是说,如果它已经在那里工作了,你可以把它放在里面。没人会追踪到你,在黑暗的巷子里打败你。你知道吗

相关问题 更多 >

    热门问题