0

我正在尝试使用父类__div__()来维护相同的类型,以便可以一次调用许多操作,如下面的最后一个示例mix1 = bf2/bf4*bf1%bf5所示main(),其中多个算术运算串在一起。出于某种原因,我可以使用 super() in__add__()但不能 in __div__()。错误是“IndexError:list index out of range”,我一直在反复检查这个,没有任何进展。请注意,这都与有限域内的多项式算术有关。

我包括了parsePolyVariable()和它的依赖项(对不起,如果它看起来有一些代码,但我向你保证这一切都是为了一个好的事业并建立性格),因为这似乎是列表错误的根源,但我不能为了我的一生,弄清楚一切都出了什么问题。我正在自学 Python,所以我敢肯定还有其他一些初学者会看到我遗漏了明显的地方。

我一直在查看这些,但它们似乎与这种情况无关:

http://docs.python.org/2/library/functions.html#super

Python super(Class, self).method vs super(Parent, self).method

如何使用 Python 的 super() 更新父值?

import re

class GF2Polynomial(object): #classes should generally inherit from object

    def __init__(self, string):
        '''__init__ is a standard special method used to initialize objects.
        Here __init__ will initialize a gf2infix object based on a string.'''
        self.string = string  #basically the initial string (polynomial)
        #if self.parsePolyVariable(string) == "0": self.key,self.lst = "0",[0]
        #else:
        self.key,self.lst = self.parsePolyVariable(string) # key determines polynomial compatibility
        self.bin = self.prepBinary(string)  #main value used in operations

    def id(self,lst):
        """returns modulus 2 (1,0,0,1,1,....) for input lists"""
        return [int(lst[i])%2 for i in range(len(lst))]

    def listToInt(self,lst):
        """converts list to integer for later use"""
        result = self.id(lst)
        return int(''.join(map(str,result)))

    def parsePolyToListInput(self,poly):
        """
        replaced by parsePolyVariable. still functional but not needed.
        performs regex on raw string and converts to list
        """
        c = [int(i.group(0)) for i in re.finditer(r'\d+', poly)]
        return [1 if x in c else 0  for x in xrange(max(c), -1, -1)]

    def parsePolyVariable(self,poly):
        """
        performs regex on raw string, converts to list.
        also determines key (main variable used) in each polynomial on intake
        """
        c = [int(m.group(0)) for m in re.finditer(r'\d+', poly)] #re.finditer returns an iterator
        if sum(c) == 0: return "0",[0]
        letter = [str(m.group(0)) for m in re.finditer(r'[a-z]', poly)]
        degree = max(c); varmatch = True; key = letter[0]
        for i in range(len(letter)):
            if letter[i] != key: varmatch = False
            else: varmatch = True
        if varmatch == False: return "error: not all variables in %s are the same"%a
        lst = [1 if x in c else (1 if x==0 else (1 if x=='x' else 0))  for x in xrange(degree, -1, -1)]
        return key,lst

    def polyVariableCheck(self,other):
        return self.key == other.key

    def prepBinary(self,poly):
        """converts to base 2; bina,binb are binary values like 110100101100....."""
        x = self.lst; a = self.listToInt(x)
        return int(str(a),2)

    def __add__(self,other):
        """
        __add__ is another special method, and is used to override the + operator.  This will only
        work for instances of gf2pim and its subclasses.
        self,other are gf2infix instances; returns GF(2) polynomial in string format
        """
        if self.polyVariableCheck(other) == False:
            return "error: variables of %s and %s do not match"%(self.string,other.string)
        return GF2Polynomial(self.outFormat(self.bin^other.bin))

    def __sub__(self,other):
        """
        __sub__ is the special method for overriding the - operator
        same as addition in GF(2)
        """
        return self.__add__(other)

    def __mul__(self,other):
        """
        __mul__ is the special method for overriding the * operator
        returns product of 2 polynomials in gf2; self,other are values 10110011...
        """
        if self.polyVariableCheck(other) == False:
            return "error: variables of %s and %s do not match"%(self.string,other.string)
        bitsa = reversed("{0:b}".format(self.bin))
        g = [(other.bin<<i)*int(bit) for i,bit in enumerate(bitsa)]
        return GF2Polynomial(self.outFormat(reduce(lambda x,y: x^y,g)))

    def __div__(self,other):
        """
        __div__ is the special method for overriding the / operator
        returns quotient formatted as polynomial
        """
        if self.polyVariableCheck(other) == False:
            return "error: variables of %s and %s do not match"%(self.string,other.string)
        if self.bin == other.bin: return 1
        return GF2Polynomial(self.outFormat(self.bin/other.bin))

    def __mod__(self,other):
        """
        __mod__ is the special method for overriding the % operator
        returns remainder formatted as polynomial
        """
        if self.polyVariableCheck(other) == False:
            return "error: variables of %s and %s do not match"%(self.string,other.string)
        if self.bin == other.bin: return 0
        return GF2Polynomial(self.outFormat(self.bin%other.bin))

    def __str__(self):
        return self.string

    def outFormat(self,raw):
        """process resulting values into polynomial format"""
        raw = "{0:b}".format(raw); raw = str(raw[::-1]); g = [] #reverse binary string for enumeration
        g = [i for i,c in enumerate(raw) if c == '1']
        processed = "x**"+" + x**".join(map(str, g[::-1]))
        proc1 = processed.replace("x**1","x"); proc2 = proc1.replace("x**0","1")
        if len(g) == 0: return 0 #return 0 if list empty
        return proc2  #returns result in gf(2) polynomial form



class BinaryField(GF2Polynomial):
    def __init__(self, poly, mod):
        if mod == "0": self.string = "Error: modulus division by 0"
        elif mod == "0": self.string = "%s is 0 so resulting mod is 0"%(poly)
        fieldPoly = GF2Polynomial(poly) % mod
        if fieldPoly == 0: self.string = "%s and %s are the same so resulting mod is 0"%(poly,mod)
        else: super(BinaryField, self).__init__(fieldPoly.string)
        #self.degree = len(str(fieldPoly))

    def polyFieldCheck(self,other):
        return self.degree() == other.degree()

    def __add__(self, other):
        """
        inherited from GF2Polynomial
        """
        return super(BinaryField, self).__add__(other) % min(other,self)

    def __sub__(self,other):
        """
        inherited from GF2Polynomial
        """
        return self.__add__(other)

    def __mul__(self, other):
        """
        special method of BinaryField, needed for format adjustments between classes
        """
        #print "self = %s,%s   other = %s,%s  "%(self.degree(),type(self.degree()),other.degree(),type(other.degree()))
        if self.polyVariableCheck(other) == False:
            return "error: variables of %s and %s do not match"%(self.string,other.string)
        if self.polyFieldCheck(other) == False:
            return "error: fields of %s and %s do not match"%(self.string,other.string)
        else: print "Operation will proceed: fields of %s and %s match"%(self.string,other.string)
        bitsa = reversed("{0:b}".format(self.bin))
        g = [(other.bin<<i)*int(bit) for i,bit in enumerate(bitsa)]
        result = reduce(lambda x,y: x^y,g)%min(self.bin,other.bin)
        return GF2Polynomial(self.outFormat(result))

    def __div__(self, other):
        """
        special method of BinaryField, needed for format adjustments between classes
        """
        if self.polyVariableCheck(other) == False:
            return "error: variables of %s and %s do not match"%(self.string,other.string)
        if self.polyFieldCheck(other) == False:
            return "error: fields of %s and %s do not match"%(self.string,other.string)
        else: print "Operation will proceed: fields of %s and %s match"%(self.string,other.string)
        if self.bin == other.bin: return 1
        result = self.bin/other.bin
        #return self.outFormat(result)
        return super(BinaryField, self).__div__(other) #% min(other,self)

    def degree(self):
        return len(self.lst)-1

这是main()

if __name__ == '__main__':
    ## "x**1 + x**0" polynomial string style input
    poly1 = "x**14 + x**1 + x**0"; poly2 = "x**6 + x**2 + x**1"; poly3 = "y**6 + y**2 + y**1"
    a = GF2Polynomial(poly1); b = GF2Polynomial(poly2); c = GF2Polynomial(poly3)
    ## "x+1" polynomial string style input
    poly4 = "x**14 + x + 1"; poly5 = "x**6 + x**2 + x"; poly6 = "x**8 + x**3 + 1"
    d = GF2Polynomial(poly4); e = GF2Polynomial(poly5); f = GF2Polynomial(poly6)
    poly7 = "x**9 + x**5 + 1"; poly8 = "x**11 + x**7 + x**4 + 1"; poly9 = "x**5 + x**4 + x**2 + x"
    g = GF2Polynomial(poly7); h = GF2Polynomial(poly8); i = GF2Polynomial(poly9)
##    g = GF2Polynomial("x**5 + x**4 + x**3 + 1"); h = GF2Polynomial("x**5 + x"); print "(g*h)%b = ",(g*h)%b
##    dd = GF2Polynomial("x**0"); print "dd -- ",dd
##    ee = GF2Polynomial("0"); print "ee -- ",ee
    bf1 = BinaryField(poly1,b); print bf1; print "degree bf1 = ",bf1.degree()
    bf2 = BinaryField(poly4,e); print "bf2  ",bf2; bf3 = BinaryField(poly4,d); print "bf3  ",bf3,type(bf3)
    bf4 = BinaryField(poly4,h); bf5 = BinaryField(poly9,e); bf6 = BinaryField(poly8,i)
    add1 = bf1+bf2
    print "add1   ",add1
    div1 = bf1/bf2
    print "div1   ",div1,type(div1)
    mix1 = bf2*bf1%bf5
    print "mix1    ",mix1,type(mix1)

编辑:完整的追溯——

Message File Name   Line    Position    
Traceback               
    <module>    C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py    233     
    __div__ C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py    197     
    __div__ C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py    100     
    __init__    C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py    20      
    parsePolyVariable   C:\Users\win7pro-vm\Desktop\crypto\GF2BinaryField.py    48      
IndexError: list index out of range             

对于参考线 48 是degree = max(c); varmatch = True; key = letter[0]。个人笔记和信息被删除,调整了行号。

4

1 回答 1

3

您的return GF2Polynomial(self.outFormat(self.bin/other.bin))行生成 string 1,然后将其传递给该GF2Polynomial.parsePolyVariable()方法。

该值没有字母,因此该行:

letter = [str(m.group(0)) for m in re.finditer(r'[a-z]', poly)]

返回一个列表。下一行:

degree = max(c); varmatch = True; key = letter[0]

然后失败,因为key = letter[0]给出了IndexError异常。

您的代码难以阅读,因为您使用单字母变量并将多个语句放在一行中,因此很难弄清楚您对该函数的期望是什么。

该异常与super(). 您自己的代码中有一个简单的错误。

于 2013-08-13T21:46:21.327 回答