【问题标题】:How can you return multiple variables defined and initiated in a function in python?如何返回在 python 函数中定义和启动的多个变量?
【发布时间】:2012-01-21 22:47:20
【问题描述】:

所以我的代码如下所示:

def parse(info):
    """
    'info' is a list made out of data received (info = list(data)). Examples are as follows:
    ['NEWGAME', '1', 'testbot', 'testbot', '100', '200', '2', '1', '10000.00000']
    ['NEWHAND', '1', '0', '4c', '5d', '0', '0', '0', '10000.00000']
    ['GETACTION', '3', '0', '2', 'POST:testbot:1,POST:testbot:2', '3', 'FOLD,CALL,RAISE:4', '10000.0']
    ['HANDOVER', '0', '0', '0', '3', 'FOLD:bot3001,FOLD:testbot,WIN:testbot:3', '9999.9506']
    """
    phase = info[0]   # setting board cards to 0
    boardCard1 = 0    # 0 means no card
    boardCard2 = 0
    boardCard3 = 0
    boardCard4 = 0
    boardCard5 = 0
    if phase == "NEWGAME":
        gameID = int(info[1])  # Game ID
        leftOpp = info[2]  # Left Opponent
        rightOpp = info[3]  # Right Opponent
        maxHands = int(info[4]) #Initializing number of hands that will be played
        maxStackSize = int(info[5]) # Stack size, also the maximum bet size
        bigBlind = int(info[6])
        smBlind = int(info[7])
        maxTime = float(info[8])  # Initiallizing milliseconds of time allocated for the game
        return (phase, gameID, leftOpp, rightOpp, maxHands, maxStackSize, bigBlind, smBlind, maxTime)
    if phase == "NEWHAND":
        handID = int(info[1]) # The hand number which we're currently at
        position = int(info[2]) # Possition, either 0, 1, or 2. 0 = dealer, 1 = smalll blind, 2 = big blind
        card1 = info[3]              # Card 1
        card1Rank = (list(info[3]))[0] # Rank of Card 1
        card1Suit = (list(info[3]))[1] # Suit of Card 1
        card2 = info[4]              # Card 2
        card2Rank = (list(info[4]))[0] # Rank of Card 2
        card2Suit = (list(info[4]))[1] # Suit of Card 2
        hand = [card1, card2]        # A list containing the 2 cards in your hand
        bankRoll = int(info[5])    # Your bank roll, total amount made (can be negative)
        leftOppBank = info[6]   # Left Opponent's bankroll
        rightOppBank = info[7]  # Right Opponent's bankroll
        timeLeft = float(info[8])  # Milliseconds of time allocated for the game
        boardPhase = "PREFLOP"     # Initializing boardPhase
        return(boardPhase, phase, handID, position, card1, card1Rank, card1Suit, card2, card2Rank, card2Suit, hand, bankRoll, leftOppBank, rightOppBank, timeLeft)
    elif phase == "GETACTION":
        potSize = int(info[1])
        numBoardCards = int(info[2]) # can be 0,3,4 or 5
        boardCardsPacket = 0    # 0 for none, 1 for present
        boardCards =[]
        if numBoardCards != 0:       
            boardCardsPacket = 1
            boardCards = (info[4]).split(",")   # info[4] looks like 'Th,Ad,Js,5h' and split(",") turns it into [Th, Ad, Js, 5h]
            boardCard1 = boardCards[0]
            boardCard2 = boardCards[1]
            boardCard3 = boardCards[2]
            try:
                boardCard4 = boardCards[3]
                try:
                    boardCard5 = boardCards[4]
                except:
                    pass
            except:
                pass
        numLastActions = int(info[3+boardCardsPacket])
        lastActions = []
        if numLastActions != 0:
            actionsString = info[4+boardCardsPacket] # a string of actions ex: POST:testbot:1,POST:testbot:2
            lastActions = actionsString.split(",")         # A list of the actions ex: ['POST:testbot:1','FOLD:testbot','WIN:testbot:3']
        for i, item in enumerate(actions):
            if "DEAL" in item.split(":"):
                boardPhase = item.split(":")[1]
        numLegalActions = int(info[5+boardCardsPacket])
        legalActions = (info[6+boardCardsPacket]).split(",") # List of Legal Actions, ex: ['FOLD', 'CALL', 'RAISE:4']
        minBet = "NULL"   # it will be NULL if BET is not a legal action.
        for i, item in enumerate(legalActions):
            if "BET" in item.split(":"):
                minBet = item.split(":")[1]
        minRaise = "NULL"
        for i, item in enumerate(legalActions):
            if "RAISE" in item.split(":"):
                minRaise = item.split(":")[1]        
        realLegalActions = []
        for item1 in legalActions:
            for item2 in item1.split(":"):    # this creates realLegalActions which will not include numbers, will look like ['FOLD','CALL', 'RAISE'], makes it easier to check if an action is in legalActions
                try:
                    int(item2)
                except:
                    realLegalActions.append(item2)       
        timeLeft = float(info[7+boardCardsPacket])
        try:                                             # If the boardPhase is still PREFLOP then there is no variable boardPhase to return, so we have an exception for that.
            return (realLegalActions, minBet, timeLeft, boardPhase, legalActions, numLegalActions, lastActions, numLastActions, boardCardsPacket,
                    boardCards, boardCard1, boardCard2, boardCard3, boardCard4, boardCard5, potSize, numBoardCards, minRaise)
        except:
            return (realLegalActions, minBet, timeLeft, legalActions, numLegalActions, lastActions, numLastActions, boardCardsPacket,
                    boardCards, boardCard1, boardCard2, boardCard3, boardCard4, boardCard5, potSize, numBoardCards, minRaise)
    elif info[0] == "HANDOVER":
        bankRoll = int(info[1])
        leftOppBank = int(info[2])
        rightOppBank = int(info[3])
        numLastAction = int(info[4])
        LastActions =[]
        if numLastAction!=0:
            LastActions = (info[5]).split(",")
        timeLeft = float(info[6])
        return(numLastAction, timeLeft, bankRoll, leftOppBank, rightOppBank, LastActions)    

如何使用我返回的所有变量?最简单的方法是什么?我是否应该创建一个类(我不太擅长使用类,但如果可以使用类,我会重新审视我的代码)?

编辑---- 我只想解析字符串,然后返回所有变量,以便可以在其他类和函数中使用它们。这是导入它的主要功能:

import socket
import sys
import pokerParser
from time import time
import betMaster
import historian


if __name__ == "__main__":
    port = int(sys.argv[1])
    s = socket.create_connection(('127.0.0.1', int(sys.argv[1])))
    f_in = s.makefile()
    while 1:
        start = time() # converting from seconds to miliseconds
        data = f_in.readline()
        if not data:
            print "Gameover, engine disconnected"
            break
        info = data.split()
        pokerParser.parse(info)
        if phase == "HANDOVER":
            historian.lastActionInitiator(lastActions)
        if phase == "GETACTION":
            if (timeLeft/handsRemaining) < (maxTime*.90)/maxHands:
                output = "NULL" #Null is not a legalAction so it will be changed to CHECK or FOLD later.
                while (maxTime-(time()-startTimeelapsedTime)*1000)*.90/(handsRemaining-1): #This will set the cutoff time for a response at a time that will set the bot back on track time-wise.
                    #output = jonsModule.attribute()
            else:
                while (time()-startTime)*1000 < (maxTime*.90)/maxHands:
                    #output = jonsModule.attribute()  
            #if output.split(":")[0] not in realLegalActions and "CHECK" in realLegalActions:
                #output = "CHECK"
            #if output.split(":")[0] == "BET":
                #if output.split(":")[1] < minBet:
                    #output = "CHECK"
            #if output.split(":")[0] == "RAISE":
                #if output.split(":")[1] < minRaise:
                    #output = "CHECK"        
            #elif output not in legalActions and "CHECK" not in legalActions:
                    #output = "FOLD"
            #s.send(output)
    s.close()

# commented = dummy code for now

【问题讨论】:

  • 那个函数看起来应该是多个独立的函数;它做得太多了。
  • 你应该提供一个简单的例子来说明你的问题,我认为没有人会阅读这个混乱的代码。
  • TL;博士。请参阅sscce.org
  • 是的!使用类和类方法。虽然没有法律规定你不能在程序上编写 python,但你错过了 oop 功能,并且这样做真的让你自己更难编程

标签: python function return


【解决方案1】:
def test():
  return 1, 2, 3

a, b, c = test()  # a=1, b=2, c=3

顺便说一句,您不需要返回元组。

【讨论】:

  • 这没有帮助,因为根据字符串的不同,变量的数量和变量的名称是不同的。
  • 有时我会返回 5 个变量,有时会返回 6 个,而且每次我返回的变量都不同时,唯一的方法是使用类吗?还是我不应该使用函数?
  • 如果您返回可变数量的值,那么您肯定需要返回一个列表。我还建议返回一个 dict ,因为您似乎返回了一种结构。顺便说一句,根据输入参数返回不同的值集不是 OOP 风格。这种方式维护和使用功能是有问题的。考虑编写几个函数:每个阶段一个。创建一个将这些函数分组的 Parser 类也很有意义。
【解决方案2】:

最简单的就是返回locals()

>>> def myfunction():
...    a = 1
...    b = 2
...    c = 3
...    return locals()
...
>>> print myfunction()
{'a': 1, 'c': 3, 'b': 2}

【讨论】:

    【解决方案3】:

    简答

    您可以以任何对您或您的预期目的有意义的方式从 Python 方法返回变量。这可能是一个奇异值、一个元组、一个字典、一个新类,或者什么都没有——当然,这取决于你的意图。

    长答案(可能是 CodeReview 问题)

    在这样的上下文中,您会遇到一个问题,即定义了太多变量来跟踪不同的事物。使用局部范围变量来跟踪内容可能是一个旧习惯,但在 Python 中,由于您有列表(并且您记录了列表中的每个位置在某处表示的内容),您可以直接使用它来代替。

    例子:

    if phase == "NEWGAME":
        return tuple([i for i in info[1:]]) # Returns everything in info except "NEWGAME"
    

    这取决于您的代码的全部意图和范围。我会强烈鼓励你坐下来refactor你的代码,所以它的意图很清楚(不仅对我们,而且对你自己),每个功能目的明确且明确。

    【讨论】:

      【解决方案4】:

      如果你想返回多个值并且一个元组不起作用,你可以改为返回一个字典:

      {name1: value1, name2: value2, ...}
      

      然后很容易通过以下方式检查是否返回了某个变量:

      if name in returnvalues:
      

      (这一切都假设你不只是完全重组你的脚本,这看起来是个好主意)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-02
        • 1970-01-01
        • 1970-01-01
        • 2015-05-04
        • 1970-01-01
        相关资源
        最近更新 更多