snippetpythonMinor
Base object to convert positive numbers into other bases (2 <= base <= 35) in Python
Viewed 0 times
basesconvertintonumberspositiveotherpythonobjectbase
Problem
I'm fairly new to Python (this is the first thing I've done that really takes advantage of classes). This works and I'm happy with it; just looking for general advice. Especially nice would be input on my comments and how 'pythonic' the code is.
``
#self.vals = convert(int(cols)).vals
# ^Thought about this before but it shouldn't be allowed
elif isinstance(cols, dict):
self.dict_init(cols)
elif isinstance(cols, Base):
self.
``
#import fractions #unused, on todo
class Base:
# Dicts for getting a digit from a value and a value from a digit
nums = {0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F', 16: 'G', 17: 'H', 18: 'I', 19: 'J', 20: 'K', 21: 'L', 22: 'M', 23: 'N', 24: 'O', 25: 'P', 26: 'Q', 27: 'R', 28: 'S', 29: 'T', 30: 'U', 31: 'V', 32: 'W', 33: 'X', 34: 'Y', 35: 'Z'}
rnums = {'6': 6, 'Y': 34, '3': 3, 'M': 22, 'C': 12, '0': 0, '7': 7, 'X': 33, '1': 1, 'D': 13, 'W': 32, '9': 9, 'V': 31, 'U': 30, 'A': 10, 'L': 21, 'F': 15, 'O': 24, '4': 4, 'J': 19, 'Z': 35, 'I': 18, '5': 5, 'T': 29, 'P': 25, '2': 2, 'E': 14, 'R': 27, 'H': 17, 'S': 28, 'N': 23, '8': 8, 'B': 11, 'Q': 26, 'K': 20, 'G': 16}
# The special bases (binary, octal, hex) have different identifiers from the pattern followed by most
sbases = {2: 'b', 8: 'o', 16: 'x'}
rsbases = {'b': 2, 'o': 8, 'x': 16}
def __init__(self, cols, base = 8, bigval = None): #cols is just a holdover; not sure what the best name for this general value would be
self.vals = {} # {column: value} dictionary
self.base = base
#can be created from an int & base, a str, a dict, or another Base object
if isinstance(cols, int) and bigval is None:
self.int_init(cols)
elif isinstance(cols, str):
if cols[0] == '0' and cols[2] == 'b': #valid string
self.baseNum_init(cols)
else:
raise ValueError('str init can only be used with a string of the form 0b`')#self.vals = convert(int(cols)).vals
# ^Thought about this before but it shouldn't be allowed
elif isinstance(cols, dict):
self.dict_init(cols)
elif isinstance(cols, Base):
self.
Solution
You can build your data structures even easier than in Stephen's answer:
You can also use the
For the
In Python 2.x use
In Python, almost always if you find yourself iterating over the indices of a collection, there is a simpler way to directly iterate over the elements. Here you can use
instead of:
You should avoid using string additions like this:
This is because, since
Instead, you can use
And if you are using Python 3.6+, you can even take advantage of f-strings:
This applies in many other places as well. For example here:
This could be:
because
nums = dict(enumerate('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'))You can also use the
string module, so you don't even have to type out the string:import string
num = dict(enumerate(string.digits + string.ascii_uppercase))For the
rnums, his is already as good as you can get. But you could put that functionality into a function and just call that, since you use it twice:def invert_dict(d):
"""
Inverts a dictionary.
Assumes all values are hashable and unique. The responsibility for this lies
with the caller.
"""
return {v: k for k, v in d.items()}In Python 2.x use
d.iteritems, instead of d.items for some speed-boost. Then you can use it like this:rnums = invert_dict(nums)
rsbases = invert_dict(sbases)In Python, almost always if you find yourself iterating over the indices of a collection, there is a simpler way to directly iterate over the elements. Here you can use
reversed:for power in reversed(self.powers):
# Do stuffinstead of:
for k in range(len(self.powers) - 1, 0 - 1, -1): #counting down through self.powers
power = self.powers[k]
# Do stuffYou should avoid using string additions like this:
ValueError('Value in column ' + str(col) + 'greater than allowed.')This is because, since
str is immutable in Python, this involves creating one additional string (the output string) for every addition. As soon as you add many (possibly even long) strings, this becomes costly.Instead, you can use
str.format:ValueError('Value in column {} greater than allowed.'.format(col))And if you are using Python 3.6+, you can even take advantage of f-strings:
ValueError(f'Value in column {col} greater than allowed.')This applies in many other places as well. For example here:
class Base:
...
def __repr__(self):
return "Base('" + self.__str__() + "')"
# b/c of str_init, eval(repr(Base)) == BaseThis could be:
class Base:
...
def __repr__(self):
return "{}('{}')".format(self.__class__.__name__, self)
# b/c of str_init, eval(repr(Base)) == Basebecause
format calls the __str__ method by default (you can also choose by using {!s} or {!r} for __str__ and __repr__, respectively).Code Snippets
nums = dict(enumerate('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'))import string
num = dict(enumerate(string.digits + string.ascii_uppercase))def invert_dict(d):
"""
Inverts a dictionary.
Assumes all values are hashable and unique. The responsibility for this lies
with the caller.
"""
return {v: k for k, v in d.items()}rnums = invert_dict(nums)
rsbases = invert_dict(sbases)for power in reversed(self.powers):
# Do stuffContext
StackExchange Code Review Q#158444, answer score: 3
Revisions (0)
No revisions yet.