OK. Let's make some correction and demystification ;-) The class represents the description of the behaviour of the object that will be created later. The object is also called the instance of the class. Let the class PackedDecimal represents one number in the packed decimal form. The __init__() is the first method that is called for the created object. The self (the first argument of all methods) refers to the object data part. The function inside the class is called a method.
class PackedDecimal:
def __init__(self, packedValue, decimals): # This will only remember the given packed form and the number of decimal places. self.packedValue = packedValue self.decimals = decimals def asReadableString(self): # This method returns the readable string created from the packed form stored in the object. # Take each byte and convert it to 2 digits. Put them into the list of digits. lst = [] for c in self.packedValue: # for each byte i = ord(c) # convert it to a number lst.append(str((i & 0xf0) >> 4)) # digit from upper 4 bits lst.append(str(i & 0x0f)) # digit from lower 4 bits
# The last digit in the list encodes the sign. The 5 means negative, # 3 means positive. Set the sign character to empty or minus and remove # the last digit that represented the sign from the list. Only the valid # digits will remain in the list. sign = '' if lst[-1] == '5': sign = '-' del lst[-1]
# Insert the decimal point character exactly in front of the fraction digits. if self.decimals > 0: assert self.decimals <= len(lst) lst.insert(-self.decimals, '.')
# Join all the characters (digits and the decimal point) in the list # into one string, remove the leading zeros, and prepend the sign result = (''.join(lst)).lstrip('0') if result == '': result = '0' return sign + result
def assignFromInt(self, intValue, precision, decimals): # This method creates the new packed representation. # Build the list of digits -- initialized to empty. lst = []
# The last item encodes the sign. The 5 means negative, the 3 means positive. # Get the absolute value. if intValue < 0: lst.append(5) intValue = -intValue else: lst.append(3) # While the absolute value is not zero, get the value of the decimal digit # and insert it to the beginning of the list. while intValue > 0: digit = intValue % 10 intValue = intValue // 10 lst.insert(0, digit)
# Prepend the leading zeros until we have enough of them. while len(lst) < precision: lst.insert(0, 0)
# When having odd number of items, prepend one more zero. if len(lst) % 2 == 1: lst.insert(0, 0) # Get always next 2 digits and combine them into one byte. Append it into list # characters that represent the bytes. buf = [] for i in xrange(0, len(lst), 2): buf.append(chr((lst[i] << 4) + lst[i+1]))
# Join the characters into one string and remember it in the data member. self.packedValue = ''.join(buf) self.decimals = decimals
# Here the definition of the class ended. When the Python interpreter consumes # the script for the first time, executing the lines means building the class from # sources. The following lines do not belong to class definition. When the special # identifier __name__ containst the string "__main__", then the script was given # explicitly to the interpreter. (The other case would be the file used as a module.) # The body after the if are normal lines.
if __name__ == '__main__': # test
packedVal = '\x01\x23\x43' # 12.34 for 2 decimal places pdA = PackedDecimal(packedVal, 2) # Create the instance of the class (the object). # The __init__() method is called automatically. The self inside will be identical # to the outer pdA, the next two arguments are also passed to __init__().
print pdA.asReadableString() packedVal = '\x01\x23\x45' # -12.34 for 2 decimal places pdB = PackedDecimal(packedVal, 2) print pdB.asReadableString()
pdC = PackedDecimal('\x00\x00\x03', 0) # let this be zero -- init (prec 6, zero decimals) print pdC.asReadableString() pdC.assignFromInt(-1234, 6, 2) # precision 6 including the sign; 2 decimal places print pdC.asReadableString() print repr(pdC.packedValue)
# to simulate your record... record = '\x00\x00\x00\x12\x34\x53' + 'some text ' print repr(record) pd = PackedDecimal(record[0:6], 2)
# Do some changes... pd.assignFromInt(-987654, 12, 4) # -98.7654
# The record in the string must be converted to list of characters lst = list(record) print lst # The part of the list must be replaced by new bytes that represent new value... lst[0:6] = list(pd.packedValue) print lst
# ... and the list must be converted to resulting string (the modified record) record = ''.join(lst) print repr(record)
Feel free to ask.
|