python动态创建类方法

python动态创建类方法,python,Python,对于一些sqlalchemy模型,我有一个相当复杂的基类,我想创建一个rails样式设置器,但是,由于我对python相当陌生,我遇到了一个似乎无法回避的问题。我在new方法上创建setter,这样我就可以在新实例和查询上触发setter,但无论我定义和执行哪个setter,它总是选择最后一个要执行的setter。例如: class Test(object): columns = ['email', 'username'] def __new__( cls, *args, *

对于一些sqlalchemy模型,我有一个相当复杂的基类,我想创建一个rails样式设置器,但是,由于我对python相当陌生,我遇到了一个似乎无法回避的问题。我在new方法上创建setter,这样我就可以在新实例和查询上触发setter,但无论我定义和执行哪个setter,它总是选择最后一个要执行的setter。例如:

class Test(object):

    columns = ['email', 'username']

    def __new__( cls, *args, **kwargs ):
        for column in cls.columns:
            setattr( cls, "set%s" % column.capitalize(), lambda cls, v: cls.setAttribute( cls, column, v ) )
        return super( Test, cls ).__new__( cls, *args, **kwargs )

    @staticmethod
    def setAttribute(cls, attribute, value):
        print "Setting attribute %s with value %s" % ( attribute, value )
        setattr( cls, attribute, value )

test = Test()
test.setEmail('test@test.com')

如您所见,我正在设置电子邮件,但执行时,代码会尝试设置最后一列的用户名。知道为什么吗?

发生这种情况是因为
lambda
函数引用了
列,但没有将其作为参数传入:

lambda cls, v: cls.setAttribute( cls, column, v )
执行此函数时,它将在包含范围或全局范围中查找名称
,并始终查找值
'username'
,因为
设置为最后一个值

以下是使用默认参数值解决此问题的简单方法:

    def __new__( cls, *args, **kwargs ):
        for column in cls.columns:
            setattr( cls, "set%s" % column.capitalize(), lambda cls, v, column=column: cls.setAttribute( cls, column, v ) )
        return super( Test, cls ).__new__( cls, *args, **kwargs )
另一种选择是使用闭包(在某种程度上,可变默认参数是闭包的一种类型):


你需要了解我的代码是完全有效的。我只是忘了添加列作为参数。现在我们来看看闭包。与问题无关,但是您应该使用元类或类装饰器,而不是重写
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。谢谢
    def __new__( cls, *args, **kwargs ):
        def make_setter(column):
            return lambda cls, v: cls.setAttribute( cls, column, v )
        for column in cls.columns:
            setattr( cls, "set%s" % column.capitalize(), make_setter(column))
        return super( Test, cls ).__new__( cls, *args, **kwargs )