如何在Python中返回函数内定义和初始化的多个变量?

0 投票
4 回答
4373 浏览
提问于 2025-04-17 10:48

我的代码是这样的:

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

4 个回答

1

最简单的方法就是返回 locals()。

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

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

顺便说一下,你不需要返回元组。

0

简短回答

你可以用任何对你有意义的方式从Python的方法中返回变量,或者说根据你的目的来返回。可以是一个单一的值、一个元组、一个字典、一个新类,甚至什么都不返回——这都取决于你的意图。

详细回答(可能涉及代码审查的问题)

在这种情况下,你可能会遇到一个问题,就是定义了太多变量来跟踪不同的东西。使用局部变量来管理这些信息可能是个老习惯,但在Python中,由于你有列表(并且你在某个地方记录了列表中每个位置代表的内容),你可以直接使用列表来代替这些变量。

举个例子:

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

这完全取决于你代码的整体意图和范围。我强烈建议你坐下来重构你的代码,这样它的意图就会清晰(不仅对我们,对你自己也是),而且每个函数的目的也会明确且具体。

撰写回答