2017-05-05 66 views
0

我創建了一個模擬標記/掃描垃圾收集算法的小程序。大多數情況下,它的工作原理完全只有一個例外:我用於區分10和pointer_variable->mem_block(因爲pointer_variable名稱不能是整數)的引用的自定義is_int()函數在傳遞0時無法返回True運行整個程序Python整數類型檢查函數輸出不一致

當我在Python交互模式下運行is_int(0)運行功能,而正確返回True。但是,在運行整個程序時,if is_int(x)/else會將我轉入else分支,因此x == 0和我無法弄清楚原因。

這裏是源代碼和一些截圖展示的局面,最相關的代碼塊被標以「#問題代碼」:

import argparse 
import re 
import sys 

class MemoryObject(): 
    def __init__(self): 
     self.marked = 0 
     self.references = [] # list of <MemoryObject> references 

def arg_parse(): 
    # Sets up a parser object for handling arguments passed to the program 
    parser = argparse.ArgumentParser(description='Some description') 
    parser.add_argument('filename', help='Filename parameter for input file') 
    return parser.parse_args() 

# PROBLEM CODE 
def is_int(s): 
    # Determines if the given variable contains only an integer value 
    # Primarily used to distinguish memory-blocks from named 
    # pointer variables 
    if int(s): 
     return True 
    elif s == 0: 
     return True 
    else: 
     return False 
# /PROBLEM CODE 

def node_trace(current_node, node_dict): 
    # This function recursively simulates the "mark" phase of 
    # Mark/Sweep G.C. using a dictionary of <MemoryObject> 
    # each element therin containing its list of references 
    # 
    # Each node traversed is marked, and the function returns 
    # if the node has already been checked 
    # 
    # This function assumed the inital call was passed the RootMemoryBlock 
    # as it's starting point, which garuntees only accessible memory will 
    # be marked since RootMemoryBlock only references pointers which 
    # in turn, by definition, only reference chains of accessible memory 

    if current_node.marked == 1: 
     return 
    else: 
     current_node.marked = 1 

     for node in current_node.references: 
      node_trace(node, node_dict) 


def get_nodes(): 
    # This function creates a dictionary of memory-blocks and named 
    # pointer-variables ncluding a "RootMemoryBlock" that hold the 
    # pointer-variables. The number of memory blocks/variables is 
    # determined by the contents of the input file. 
    # 
    # Each object is stored in the dictionary as a <MemoryObject> 
    # 
    # The contents of the input file are then used to determine all references 
    # between variables->blocks and blocks->blocks, with the only object 
    # referencing named-variables being the RootMemoryBlock. The format 
    # of the file garuntees that memory_blocks are listed as integers, and 
    # variables as strings that start with either a letter or an underscore '_' 
    # 
    # is_int is therefor used to determing if an object is a variable or a 
    # memory-block when populating the reference lists for the elements 
    # of the <MemoryObject> dictionary 
    # 
    # Each object's reference list is stored in its <MemoryObject>::references 
    # as a list of references to <MemoryObject> 
    # 
    # The dictionary is then passed into the node_trace function along with the 
    # RootMemoryBlock <MemoryObject> which recursively performs the 
    # "mark" phase of Mark/Sweep G.C. 
    # 
    # Finally a new dictionary is created and JUST the info for the 
    # memory-blocks (not variables, or the RootBlock) is copied into it. 
    # 
    # That dictionary is then returned to the calling function. 
    node_pointers = [] 
    node_dict = {} 
    args = arg_parse() 
    input_file = args.filename 

    with open(input_file) as in_file: 
     node_count = 0 
     for line in in_file: 
      if node_count == 0: 
       node_count = int(line) 
      else: 
       split_line = line.rstrip() 
       split_line = re.split(r'[,]', split_line) 
       node_pointers.append([split_line[0], int(split_line[1])]) 

    root_node_key = node_count 
    array_size = node_count + 1 
    for i in range (array_size): 
     node_dict[i] = MemoryObject() 

    # The format of the input file garuntees that each item will 
    # describe a link of the form [source, target] 
    SOURCE = 0 # The source of a reference link 
    TARGET = 1 # The target of a reference link 

    for item in node_pointers: 
    # PROBLEM CODE 
     if is_int(item[SOURCE]):   
      node_dict[int(item[SOURCE])].references.append(node_dict[item[TARGET]]) 
     else: 
      if item[SOURCE] not in node_dict.keys(): 
       node_dict[item[SOURCE]] = MemoryObject() 

      node_dict[item[SOURCE]].references.append(node_dict[item[TARGET]]) 
      node_dict[root_node_key].references.append(node_dict[item[SOURCE]]) 
    # /PROBLEM CODE 
    node_trace(node_dict[root_node_key], node_dict) 

    node_dict_final = {} 

    for element in node_dict.keys(): 
     if is_int(element) and element != root_node_key: 
      node_dict_final[element] = node_dict[element] 

    return node_dict_final 


def print_result(message, value, nodes): 
    # Displays the results of the mark/sweep algorithm 
    # as stored in the dictionary "nodes" 
    # 
    # Prints all marked nodes if value == 1 
    # Prints all reclaimed nodes if value == 0 
    print(message) 
    for element in nodes.items(): 
     if element[1].marked == value: 
      if is_int(element[0]): 
       print(element[0]) 


def main(): 
    # Entry Point function. Calls get_nodes which processes 
    # the input_file, then runs the simluated mark/sweep 
    # algorithm. 
    # 
    # It then displays the returned results of the mark/sweep 

    nodes = get_nodes() 
    print_result('\nMarked: ', 1, nodes) 
    print_result('\nReclaimed: ', 0, nodes) 
    print() 


if __name__ == '__main__': 
    main() 

截圖:

Interactive Mode

Running program with no references from 0th mem_block

Running program with references from 0th mem_block

+2

你確定它是整數0而不是一個單一的字符串'「0」'? –

+0

@IljaEverilä你知道這是我想到的第一件事,我多次瀏覽了代碼,試圖瞭解這可能會導致問題無濟於事,只是現在才知道爲什麼/如何。 我需要將'elif s == 0'改爲'elif int(s)== 0' 由於該函數可以用於任何其他整數EVEN,如果這些整數是單個字符串,我沒有注意到它將不會使用單個字符串「0」,因爲該部分是在不同的語句中處理的。 – user3776749

回答

0

在功能is_int(),線:

elif s == 0

需要被改變以

elif int(s) == 0

由於參數是包含一個字符串正確評價輸入任一個整數或變量名稱從文件讀入。這隱含在任何非零整數的if的情況下處理,但需要在elif零情況下再次完成。

+0

這並沒有多大意義,因爲'int(s)'(如果它沒有提升)將總是*爲真或爲零。所以你的整個'is_int'函數等價於'int(s)',接着是'return True'。 IOW,它只會返回True,或者如果輸入無法轉換爲int,則會引發異常。 –

+0

你可能只想做's.isdigit()'(假設你不需要處理負數整數)。 –

+0

@MarkDickinson是的,我有另一個版本的函數看起來像'try:return int(s)except ValueError:return False',但afaik int()的工作方式,如果s == 0,那麼函數會返回' 0',python認爲是'False',我需要在這種情況下將檢查評估爲'True'。 'isdigit'是否適用於多個數字的字符串,即's ==「1234」'? – user3776749