2012-05-11 69 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 
) 

就个人而言,我会去为类方法,甚至包装计数器,因为它使所有的相关功能组合在一起。