For a quick fix, just replace the pass
with result += '-'
; for every permission test that is False you can simply insert a dash:
for value, letter in value_letters:
if digit >= value:
result += letter
digit -= value
else:
result += '-'
I'd just use bit masking however, with the &
bitwise and operator:
for value, letter in value_letters:
result += letter if digit & value else '-'
This works because 4
, 2
and 1
are the decimal (and octal) values for numbers with each one of the 3 bits set to 1, the others to 0. digit & 4
is only going to produce 4
or 0
, depending on the value of the 3rd bit from the right being set in digit
or not. Since 0
is false, and 4
is a true value, this lets you test if the right bit is set and so decide between the permission letter and -
. I used a conditional expression to return either in a single line.
Next, I'd not use a list comprehension to convert the input value into octal digits; just use map()
here to lazily convert without creating an additional list object:
for digit in map(int, str(octal)):
Next, try to avoid using string concatenation in a loop; although Python has some optimisations in place to avoid the worst case performance in simple situations, you can easily miss out on that optimisation. Best to append characters to a list then use str.join()
to create the final string in one step.
Put together into a complete function:
def octal_to_string(octal):
result = []
for digit in map(int, str(octal)):
for value, letter in ((4, "r"), (2, "w"), (1, "x")):
result.append(letter if digit & value else "-")
return "".join(result)
Demo:
>>> octal_to_string(755)
'rwxr-xr-x'
>>> octal_to_string(644)
'rw-r--r--'
Now, what the function accepts are decimal numbers, not octal numbers. From an API design you'd really want to either accept strings only (containing digits representing an octal value), or if you do accept an integer, then you should treat that value as decimal and use 0o
octal notation:
>>> 0o755 # actual octal number
493
>>> format(0o755, "o") # string representing value in octal notation
'755'
If you do so, just change str(octal)
into format(octal, 'o')
to get the octal digits:
>>> octal = 0o755
>>> for digit in map(int, format(octal, "o")):
... print(digit)
...
...
7
5
5