类实例上的setattr()未设置值

Python 3,频道1.x,Django 1.11。

游戏是tron轻循环,但要转弯,用户必须解决数学问题。多人游戏,目前最多2人

generate_first_4_problems_game func (inside channels session - see decorator @channel_session_user) is triggered at the start of a game. it sends the flux_instance to generate_first_4_problems func, which is outside the channels session (I'm not sure if this matters though). Inside generate_first_4_problems, setattr is supposed to set the values (details aren't too important, just know that the relevant (class) attributes are p1/p2-up/down/left/right (8 attributes total) and they store math problems) in the flux_instance that is being used in the channels session but that never happens.

Printing getattr(flux_instance,d) (example, flux.p1up = '2 + 8') inside generate_first_4_problems exhibits expected behavior (math problem is printed), but printing inside send_answer gives a None.

The focus of this question is inside send_answer, where getattr(flux_instance,d) is supposed to be some math problem, which was supposed to be defined in generate_first_4_problems (and it seems like it was, because the print statement inside of it exhibited expected behavior (a math problem for each getattr(flux_instance, d))), but it is not.

有人可以帮忙吗?

def is_correct_answer(problem_string, input_answer):
    # determines if input answer is correct for given problem string

def generate_problem(level, operation, flux_instance=None, player_type=None):
    # generates random math problem

def generate_first_4_problems(flux_instance, player_type):

    creator_directions = ['p1up', 'p1right', 'p1down', 'p1left']
    opponent_directions = ['p2up', 'p2right', 'p2down', 'p2left']

    problems = []
    answers = []

    while len(problems) < 4:
        problem = generate_problem(flux_instance.level, flux_instance.operation)
        answer = x(problem).expr()
        # no duplicate answers
        if answer not in answers:
            if flux_instance.level == 1:
                # no negative numbers as answers
                if answer > 0:
                    problems.append(problem)
                    answers.append(answer)
                else:
                    pass
            else:
                problems.append(problem)
                answers.append(answer)
        else:
            pass
    if player_type == 'creator':
        for i, d in enumerate(creator_directions):
            setattr(flux_instance, d, problems[i])
    elif player_type == 'opponent':
        for i, d in enumerate(opponent_directions):
            setattr(flux_instance, d, problems[i])
    return problems

class Flux:

    # player starting positions and directions

    creator_history = ['790,358']
    opponent_history = ['262,358']
    creator_direction = 'left'
    opponent_direction = 'right'

    # game dimensions in pixels

    game_width = 1056
    game_height = 708

    # questions for player directions

    p1up = None
    p1right = None
    p1down = None
    p1left = None
    p2up = None
    p2right = None
    p2down = None
    p2left = None

    # needed for checkcollision

    creator = {
        'x': None,
        'y': None,
    }

    opponent = {
        'x': None,
        'y': None
    }

    def __init__(self, game_object, game_label):
        self.game_object = game_object
        self.level = game_object.level
        self.operation = game_object.operation
        self.game_label = game_label

    def update_game_state(self, player_and_direction=None):

        last_cx = self.creator_history[-1].split(',')[0]
        last_cy = self.creator_history[-1].split(',')[1]

        last_ox = self.opponent_history[-1].split(',')[0]
        last_oy = self.opponent_history[-1].split(',')[1]

        def check_collision(cycle, opponent):
                    # checks to see if creator or opponent have collided, which would end the game

        def get_player_xy(direction, last_x, last_y):
            direction_actions = {
                'left': lambda last_x, last_y : '%s,%s' % (int(last_x) - 4, last_y),
                'right': lambda last_x, last_y : '%s,%s' % (int(last_x) + 4, last_y),
                'up': lambda last_x, last_y : '%s,%s' % (last_x, int(last_y) - 4),
                'down': lambda last_x, last_y : '%s,%s' % (last_x, int(last_y) + 4),     
            }
            xy = direction_actions[direction](last_x, last_y)
            return xy

        if player_and_direction != None:
            if player_and_direction[0:2] == 'p1':
                self.creator_direction = player_and_direction[2:]
            elif player_and_direction[0:2] == 'p2':
                self.opponent_direction = player_and_direction[2:]

        cxy = get_player_xy(self.creator_direction, last_cx, last_cy)
        oxy = get_player_xy(self.opponent_direction, last_ox, last_oy)

        self.creator_history.append(cxy)
        self.opponent_history.append(oxy)

        self.creator['x'] = cxy.split(',')[0]
        self.creator['y'] = cxy.split(',')[1]

        self.opponent['x'] = oxy.split(',')[0]
        self.opponent['y'] = oxy.split(',')[1]

        check_collision(self.creator, self.opponent)
        check_collision(self.opponent, self.creator)

        context = {
            'cxy': cxy,
            'oxy': oxy
        }

        Group('game-' + self.game_label).send({'text': json.dumps(context)})

    def stop_game(self, winner, loser):
        context = {}
        gs_interval = getattr(self, 'gs_interval', None)
        if gs_interval:
            self.gs_interval.cancel()
            self.game_object.winner = winner
            self.game_object.loser = loser
            self.game_object.save()
            context['game_over_finished'] = True
            Group('game-' + self.game_label).send({'text': json.dumps(context)})

@channel_session_user
def ws_receive_game(message):

    gamelabel = message.channel_session[u'gamelabel']
    gamepk = gamelabel.split('-')[1]

    with transaction.atomic():
        game = Game.objects.select_for_update().get(pk=gamepk)

    data = json.loads(message['text'])

    # set these to something to avoid
    # referenced before assignment error

    flux = Flux(game, gamelabel)

    # fix weird glitch where history from last game is loaded
    # (find out why this happens at some point)

    flux.creator_history = ['790,358']
    flux.opponent_history = ['262,358']
    flux.creator_direction = 'left'
    flux.opponent_direction = 'right'

    answer = None
    level = None
    operation = None
    winner = None
    current_position = None
    current_direction = None
    game_start = None

    if u'level' in data:
        level = data[u'level']
    if u'operation' in data:
        operation = data[u'operation']
    if u'answer' in data:
        answer = data[u'answer']
    if u'winner' in data:
        winner = data[u'winner']
    if u'current_position' in data:
        current_position = data[u'current_position']
    if u'current_direction' in data:
        current_direction = data[u'current_direction']

    if message.user.username != data[u'username']:
        return

    context = {}

    if message.user == game.creator:
        player_type = 'creator'
    elif message.user == game.opponent:
        player_type = 'opponent'

    def game_start():
        game.game_start = timezone.now()
        flux.game_state = flux.update_game_state()
        flux.gs_interval = SetInterval(0.1, flux.update_game_state)
        game.save()

    def generate_first_4_problems_game(flux_instance, player_type):
        problem_list = generate_first_4_problems(flux_instance, player_type)

        if player_type == 'creator':
            context['creator_problem_list'] = problem_list
        else:
            context['opponent_problem_list'] = problem_list

    # cpl = current_problems_list
    def generate_problem_game(level, operation, flux_instance=None, player_type=None):
        problem = generate_problem(level, operation, flux_instance, player_type)
        return problem

    def send_answer(answer, flux_instance, player_type):

        directions_list = {
            'creator': ['p1up', 'p1right', 'p1down', 'p1left'],
            'opponent': ['p2up', 'p2right', 'p2down', 'p2left']
        }

        for d in directions_list[player_type]:
            if is_correct_answer(getattr(flux_instance, d), int(answer)):
                flux_instance.game_state = flux_instance.update_game_state(d)
                new_problem = generate_problem_game(
                    flux_instance.level, flux_instance.operation, flux_instance, player_type)
                setattr(flux_instance, d, new_problem)
                context['new_problem'] = [d, new_problem]

    signals = {
        u'generate_first_4_problems_game': partial(generate_first_4_problems_game, flux, player_type),
        u'send_answer': partial(send_answer, answer, flux, player_type),
        u'game_start': game_start,
    }

    if 'signal' in data and message.user.username == data[u'username']:
        signal = data[u'signal']
        signals[signal]()

    print('context', context)
    Group('game-' + gamelabel).send({'text': json.dumps(context)})