2011-08-16 110 views
1

中創建的對象所以我知道在Python中,在方法中聲明的變量在其外部是不可見的。但他們的生命週期是什麼?我期望每次調用方法時都會創建一個在方法中聲明的變量。python方法變量和在方法

我在問以下情況。我有一個方法如下(這是與cherrypy使用,可能不相關,但我仍然會添加它的機會,以任何方式影響它)。

首先,我使用自定義過濾器類:

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 

因此如預期,一個新的過濾器對象被創建,並且被添加的操作,字段和從收到的參數值,長度(字段)= 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

在'def'線會發生什麼情況的方法不會發生,它發生在外部環境。 – agf

回答

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'] 
+6

或者更好的new_filter.fields.extend(過濾['fields']),因爲它擴展了可能的類型範圍。使用'+ =',你只能將列表添加到其他列表中,但使用'extend()'可以使用任何序列類型。 – glglgl

+0

感謝您的輸入,解決了我的問題。 – Bogdan