Я пытаюсь использовать __div__()
родительского класса, чтобы поддерживать один и тот же тип, чтобы можно было вызывать сразу несколько операций, как в последнем примере mix1 = bf2/bf4*bf1%bf5
в main()
ниже, где несколько арифметических операций связаны вместе. По какой-то причине я могу использовать super() в __add__()
, но не в __div__()
. Ошибка «IndexError: индекс списка вне диапазона», и я повторял это снова и снова без какого-либо прогресса. Обратите внимание, что все это связано с полиномиальной арифметикой в пределах конечного поля.
Я включаю parsePolyVariable()
и его иждивенцев (извините, если это выглядит так, как будто есть немного кода, но я уверяю вас, что все это по уважительной причине и создает характер), так как это то, откуда ошибка списка, но я могу' t для жизни мне понять, где все идет очень неправильно. Я сам учу Python, поэтому уверен, что есть и другие новички, которые увидят, где я упускаю очевидное.
Я просматривал их, но они, похоже, не связаны с этой ситуацией:
http://docs.python.org/2/library/functions.html#super
Python super(Class, self).method vs 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]
. Личные заметки и информация были удалены, скорректированы номера строк.
super
, а с внутренним состоянием ваших полиномов. Родительский метод (вероятно... без трассировки, я не могу точно сказать) вызывается правильно, но он не работает по какой-то другой причине. Вы должны дважды проверить правильность реализации__div__
. (Примечания к стилю: я действительно не вижу ` == False. Simply use
not self.polyVariableCheck(other)` и не могу понять, почему ваши__div__
методы возвращают строки ошибок, когда они терпят неудачу. Вместо этого вам, вероятно, следует вызвать исключение). - person Bakuriu   schedule 14.08.2013__mod__
необходим во время инициализации класса, а__mul__
(также может потребоваться исправление) предназначен для сравнения типа возвращаемого значения с другими специальными методами. Ценю любую помощь, которую вы можете предоставить, так как я отлаживал эту единственную проблему в течение очень долгого времени. Я не знаю, что еще проверить в__div__()
, так как это, по сути, только само подразделение. Я хотел бы использовать__div__()
из родителя вместо того, чтобы переписывать его, поэтому я пытаюсь использоватьsuper()
. - person stackuser   schedule 14.08.2013super()
. - person Martijn Pieters   schedule 14.08.2013