简体   繁体   中英

How is the global variable being incremented when it's not being directly specified?

I'm working on a small project where I'm implementing a queue as a circular array. As a challenge, I was assigned to not use any list functions like append when implementing this ADT. It's assumed that I only need to resize the queue when it gets full. When I ran my code through a debugger and step through it, I find that the issue revolves around my self.read value (read pointer) which is the global variable in question. This is kind of perplexing to me since neither of my functions that would be affected increments my pointer. Could anyone shed some light on this problem for me?

This class is coded as:

class CircularQueue(object):
    def __init__(self, capacity=2):
        """
        Initialize the queue to be empty with a fixed capacity
        :param capacity: Initial size of the queue
        """
        self.capacity = capacity
        self.size = 0
        self.list = [0] * self.capacity
        self.sum = 0
        self.read = 0
        self.write = 0

    def __eq__(self, other):
        return self.capacity == other.capacity 
               and self.size == other.size 
               and self.read == other.read 
               and self.write == other.write   

    def __str__(self):
        if self.size == 0:
            return "Queue is empty"

        content = ""
        while ((self.read + 1) % self.size) != self.write:

            content = content + str(self.list[self.read]) + " -> "
            self.read = (self.read + 1) % self.size
        content = content[:-3]
        return f"Contents: {content}"
    __repr__ = __str__

The portion that I'm interested in looking at is my enqueue and resize functions:

def resize(self):
    bigger = [None] * (self.capacity * 2) #create bigger queue
    b_ind = 0
    read_ptr = self.read
    while read_ptr != (self.write + 1): #iterate through old queue to copy into new queue
        bigger[b_ind] = self.list[read_ptr]
        b_ind += 1
        read_ptr += 1
    self.capacity *= 2 #setting capacity
    self.list = bigger #setting new list as queue
    self.read = 0 #normalize queue
    self.write = b_ind

def enqueue(self, number):

    if self.size == 0: #if queue was originally empty
        self.list[self.read] = number
        self.write += 1
    else:
        self.list[self.write] = number #add onto end of queue
        if ((self.write + 1) % self.capacity == self.read): #resize if queue loops back and the write pointer is the same as the read pointer
            self.resize()
        else:
            self.write = (self.write + 1) % self.capacity #set write pointer
    self.sum += number #add to sum
    self.size += 1  # increment size

This was the test case I ran for my code:

queue = CircularQueue()
queue.enqueue(23)
queue.enqueue(42)
queue.enqueue(2)
queue.enqueue(195)

print(queue)

You mutate the state of your queue when printing . print() calls __str__ , and that method alters your state:

self.read = (self.read + 1) % self.size

Use a local variable instead of self.read :

def __str__(self):
    if self.size == 0:
        return "Queue is empty"

    content = ""
    read = self.read
    while (read % self.capacity) != self.write:
        if content:
            content += ' -> '
        content += str(self.list[read])
        read = (read + 1) % self.capacity
    return f"Contents: {content}"

Note the while loop condition; you want to see if the current read position is not the same as the write position (meaning you can display the current value), not the next position, and you want to wrap round at the capacity .

I adjusted your separator handling a little to only add the arrow in between values if at least one entry has been added to content already, that avoids having to remove a portion again.

Demo using the fixed __str__ method (no other changes made):

>>> queue = CircularQueue()
>>> print(queue)
Queue is empty
>>> queue.enqueue(23)
>>> print(queue)
Contents: 23
>>> queue.enqueue(42)
>>> print(queue)
Contents: 23 -> 42
>>> queue.enqueue(2)
>>> print(queue)
Contents: 23 -> 42 -> 2
>>> queue.enqueue(195)
>>> print(queue)
Contents: 23 -> 42 -> 2 -> 195

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