python方法变量和方法中创建的对象

时间:2011-08-16 08:34:12

标签: python

所以我知道在Python中,在方法中声明的变量在它之外是不可见的。但他们的生命周期是什么?我希望每次调用该方法时都会创建一个在方法内声明的变量。

我问因为以下情况。我有一个方法如下(这与cherrypy一起使用,可能不相关,但我仍然会添加它以便以任何方式影响它。)

首先我正在使用的自定义Filter类:

class Filter():
"""
Class used to filter tables displayed in UI, based on few criteria.
Initialize filter with a list of fields, and correspondinf values.
"""
def __init__(self, display_name= "", fields= [], values= [], operations= []):
    self.display_name = display_name
    self.fields = fields
    self.values = values
    self.selected = False 
    self.operations = operations

现在我正在谈论的方法

@cherrypy.expose
@logged() 
def getfiltereddatatypes(self, name, filters, datatype):
    ...some mumbo jumbo...

    default_filter = self._get_default_filters(inputTree, name)

    #default_filter here can be a object of type Filter if defined or None otherwise

    print "RECIEVED " + str(filters)
    if default_filter is not None:
        print "CREATING NEW"
        new_filter = copy.deepcopy(default_filter)
    else:
        print "CREATING NEW"
        new_filter = Filter()
    [new_filter.fields.append(value) for value in filters['fields']]
    [new_filter.operations.append(value) for value in filters['operations']]
    [new_filter.values.append(value) for value in filters['values']]
    print "LENGTH =" + str(len(new_filter.fields))

    ...Some other mumbo jumbo....

所以基本上我想将filters变量中作为参数接收的过滤器值添加到default_ones。但我希望每次调用该方法时都要这样做,或者为了更好地解释它,我制作了打印件以显示我的问题。所以在第一次调用方法时:

    RECIEVED {'operations': ['!='], 'fields': ['model.DataType.subject'], 'values': ['w']}
    CREATING NEW
    LENGTH =1

正如预期的那样,创建了一个新的Filter对象,并添加了recieved参数中的操作,字段和值,length(fields)= 1.但在我的第二遍:

    RECIEVED {'operations': ['!='], 'fields': ['model.DataType.subject'], 'values': ['']}
    CREATING NEW
    LENGTH =2

现在我无法解释这种行为。正如您所看到的,再次调用if的CREATING NEW brach,filters变量保存一个项目列表,但结果的长度为2.如果我再次运行它,它将始终递增。就像new_filter = Filter()调用返回上一个方法调用中的new_filter一样。是什么导致了这种行为?我很兴奋,如果我做了new_filter = copy.deepcopy(Filter())它可以解决它但我为什么要被迫这样做呢?

此致 波格丹

1 个答案:

答案 0 :(得分:5)

def __init__(self, display_name= "", fields= [], values= [], operations= [])

列表仅创建一次。因此,如果您修改它们,下一个调用将具有修改后的列表。如果您不想要此行为,只需使用None作为默认值并添加如下内容:

if fields is None:
    fields = []
self.fields = fields

另一种解决方案是创建一个新列表,无论传递什么:

self.fields = list(fields)

http://effbot.org/zone/default-values.htm

上还有一篇关于此行为的详细文章

顺便说一下,你滥用列表推导并不好。

[new_filter.fields.append(value) for value in filters['fields']]

应该是

new_filter.fields += filters['fields']