Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在运行时向类中添加方法而不是子类化是否存在缺陷?_Python_Django - Fatal编程技术网

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

Python 在运行时向类中添加方法而不是子类化是否存在缺陷?,python,django,Python,Django,从Django 1.5开始,现在已经内置了对用户模型子类化的支持,以添加自定义功能,但是仍然存在一些兼容性方面的考虑,这意味着我不希望这样做。在1.5之前,子类化是一个大麻烦。但是,我需要一些功能,特别是以方法的形式,.full_name()。这将返回用户的first+“”+middle+“”+last名称。更一般地说,它只在适当的地方放置空格,并且可以处理中间名,但不要求模型包含中间名 现在,在models.py的顶部有以下内容,而不是User的子类: def full_name(self):

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

现在,在models.py的顶部有以下内容,而不是User的子类:

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比较陌生,所以我很高兴地发现这是可行的。通过对其他几个模型使用相同的函数,我节省了一些时间(稍后在models.py的类定义中简单地描述full_name=full_name)。也许现在中间名功能更有意义了——其他模型都有中间名

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

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

进一步的细节:我问这个问题的一个原因是我有一些用户角色(我们称它们为Painter、Clerk和Manager)与
models.ForeignKey(user,blank=True)
关系。例如,User.painter可能返回一个painter角色,但如果用户实际上不是painter,它也可能引发ObjectNotFound异常。我不想在我的代码中乱放try:except:语句,而是想扩展我对上述思想的使用,例如,向用户添加.is_painter()和.is_manager()方法,这样我就可以简单地查询if语句中的方法,而不必进行很少的try:except:messes everywhere。

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

猴子补丁可能是脆弱的,如果你正在修改的模块在你下面发生了变化,它就会断开。其他人以后可能很难修改/调试,因为代码实际存在的位置并不总是很明显


也就是说,如果它已经在那里工作了,你可以把它放在里面。没有人会因此而追踪你并在黑暗的巷子里打败你。

谢谢你为我命名它,仅此一点就很有帮助。我想我应该在某一点上继续使用它和子类,但是是的,现在一切都很顺利。