2012-05-11 111 views
4

我想創建一個腳本,設置一個局部變量的一個函數返回變量,引用它,並且可以返回操縱值回主範圍(或任何它被稱爲;我是新來的Python)的Python:在功能使用本地變量,從功能

我簡化了我的代碼顯示的是什麼,我試圖完成,這是導入從模塊到本地功能塊的最大基礎,我想。

我已經得到了這個用globals工作,但不是最好的解決辦法。 。 。

chambersinreactor = 0; 
cardsdiscarded = 0; 

def find_chamber_discard(): 
    """Find chambers and discard in row (reads each player slot)""" 
    chambersinreactor = 0; # Resets the variable, not what I want 
    cardsdiscarded = 0; # Resets the variable, not what I want 
    chambersinreactor += 1 
    cardsdiscarded += 1 
    return # Don't know what to put here 

find_chamber_discard() 

print chambersinreactor # prints as 0, should be 1 
print cardsdiscarded # prints as 0, should be 1 
+0

你的意思是你想在參數傳遞給函數然後返回他們呢? –

+2

'chambersinreactor'和'cardsdiscarded'是全局變量。它們在本地範圍之外定義。 –

回答

17

函數不應該知道它們被調用的範圍;一個函數的重點是創建一個可重用的代碼塊,可以從不同的地方多次調用。

你將其通過其輸入變量的信息傳達給一個功能。該函數通過返回給調用者返回信息。

管理作用域的變量是該作用域中代碼的作業而不是它調用的任何函數。如果您需要將變量設置爲由函數確定的值,那麼您可以使用函數返回這些值,然後使用它們來設置變量。如果該函數計算的值取決於你在呼叫範圍內有變量的值,那麼你需要將它們傳遞給函數作爲參數。你所調用的函數不需要知道你正在使用的變量,也不應該能夠混淆它們。

把所有在一起,你想做的事是這樣的:

def find_chamber_discard(chambersinreactor, cardsdiscarded): 
    chambersinreactor += 1 
    cardsdiscarded += 1 
    return (chambersinreactor, cardsdiscarded) 

chambersinreactor = 0; 
cardsdiscarded = 0; 

chambersinreactor, cardsdiscarded = find_chamber_discard(chambersinreactor, cardsdiscarded) 

print chambersinreactor 
print cardsdiscarded 

有辦法解決這個全局變量或操縱可變的數據結構,但最終他們使你的程序不夠靈活並且更可能包含將難以發現的錯誤。沒有爲這些技術的地方,但你達到信息溝通,並從功能,真的是第一種方法,應傳遞參數和接收返回值。

+1

'chambersinreactor,cardsdiscarded = find_chamber_discard(chambersinreactor,cardsdiscarded)' - 這是驚人的 - 誰知道你能回到這樣的多個值? – toonarmycaptain

2
#!/usr/bin/env python 
chambersinreactor = 0; cardsdiscarded = 0; 

def find_chamber_discard(): 
    chambersinreactor = 0 
    cardsdiscarded = 0 
    chambersinreactor += 1 
    cardsdiscarded += 1 
    return(chambersinreactor, cardsdiscarded) 

#Here the globals remain unchanged by the locals. 
#In python, a scope is similar to a 'namespace' 
find_chamber_discard() 

print chambersinreactor #prints as 0 
print cardsdiscarded 

#I've modified the function to return a pair (tuple) of numbers. 
#Above I ignored them. Now I'm going to assign the variables in the 
#main name space to the result of the function call. 
print("=====with assignment===") 
(chambersinreactor, cardsdiscarded) = find_chamber_discard() 

print chambersinreactor # now prints as 1 
print cardsdiscarded 

# Here is another way that doesn't depend on returning values. 
#Pass a dictionary of all the main variables into your function 
#and directly access them from within the function as needed 

print("=======using locals===") 
def find_chamber_discard2(_locals): 
    _locals['chambersinreactor'] += 1 
    _locals['cardsdiscarded'] += 1 
    return 

find_chamber_discard2(locals()) 

print chambersinreactor #incremented the value, which was already 1 
print cardsdiscarded 
+1

文檔中的建議是_never_修改locals(),因爲您注意到的行爲完全基於實現,並且不能保證:「不應修改此字典的內容;更改可能不會影響口譯員使用的本地和自由變量。「 –

2

一種方法是使用可變值,比如類型的字典或列表:

settings = dict(
    chambersinreactor = 0, 
    cardsdiscarded = 0 
) 

def find_chamber_discard(): 
    settings['chambersinreactor'] += 1 
    settings['cardsdiscarded'] += 1 

find_chamber_discard() 

print settings['chambersinreactor'] 
print settings['cardsdiscarded'] 

但是,如果您有一些改變狀態的功能,你可能會更好過包裹,所有達在課堂上,因爲這是他們是什麼:

class CardCounter(object): 
    def __init__(self): 
     chambersinreactor = 0 
     cardsdiscarded = 0 

    def find_chamber_discard(self, hand): 
     for card in hand: 
      if card.is_chamber: 
       self.chambersinreactor += 1 
      if card.is_discarded: 
       self.cardsdiscarded += 1 

如果你正在做的是什麼計數,也許你可以使用計數器:

from collections import Counter 

def test_for_chamberness(x): return x == 'C' 
def test_for_discarded(x): return x == 'D' 

def chamber_or_discard(card): 
    if test_for_chamberness(card): 
     return 'chambersinreactor' 
    if test_for_discarded(card): 
     return 'cardsdiscarded' 

hand = ['C','C','D','X','D','E','C'] 

print Counter(
    x for x in (chamber_or_discard(card) for card in hand) if x is not None 
) 

就個人而言,我會去爲類方法,甚至包裝計數器,因爲它使所有的相關功能組合在一起。