简体   繁体   中英

How do I access class variables without changing them in python?

I'm new to programming so sorry for the basic question. I am trying to write a search algorithm for a class, and I thought creating a class for each search node would be helpful.

class Node(object):

    def __init__(self, path_to_node, search_depth, current_state):
        self.path_to_node = path_to_node
        self.search_depth = search_depth
        self.current_state = current_state

    ...

With some functions too. I am now trying to define a function outside of the class to create children nodes of a node and add them to a queue. node.current_state is a list

def bfs_expand(node, queuey, test_states):
    # Node Queue List -> Queue List
    # If legal move and not already in test states create and put children nodes
    # into the queue and their state into test_states. Return queue and test states

    # Copy original path, depth, and state to separate variables
    original_path = node.path_to_node
    original_depth = node.search_depth
    original_state = node.current_state

    # Check if up is legal, if so add new node to queue and state to test state
    if node.is_legal_move('Up'):
        up_state = original_state
        a = up_state.index(0)
        b = a - 3
        up_state[a], up_state[b] = up_state[b], up_state[a]
        if up_state not in test_states:
            test_states.append(up_state)
            up_node = Node(original_path + ['Up'], original_depth + 1, up_state)
            queuey.put(up_node)

    print(test_states)
    print(original_state)

I then try to proceed through down, left and right with similar if statements, but they are messed up because the original_state has changed. When I print the original state after that up statement, it returns the up_state created in the if statement. I realize (well, I think) that this is because original_state, and therefore up_state, are actually calling node.current_state and do not store the list in a separate variable. How should I get the variable from a node to manipulate independently? Should I not even be using a class for something like this, maybe a dictionary? I don't need code written for me but a conceptual nudge would be greatly appreciated!

You should use copy.deepcopy if you want to avoid modifying the original

original_path = copy.deepcopy(node.path_to_node)
original_depth = copy.deepcopy(node.search_depth)
original_state = copy.deepcopy(node.current_state)

Or essentially whichever object you want to use as a "working copy" should be a deep copy of the original if you don't want to modify the original version of it.

Expanding a bit on @CoryKramer's answer: In Python, objects have reference semantics , which means that saying

a = b

where a and b are objects, makes both a and b references to the same object, meaning that changing a property on a will change that same property on b as well. In order to actually get a new object with the same properties as the old one, you should use copy.deepcopy as already stated. However, be careful when using that function. If your object contains a reference cycle (ie: It contains a reference to an object which contains a reference to itself), copy.deepcopy will lead to an infinite loop.

For this reason, there is also copy.copy , which does not follow object references contained in the object to copy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM