Python script to convert octal to string eg octal(755) to (rwxr-xr-x). Stuck at adding the dash seperator

Question:

Below is the script printing the converted octal to string. I would appreciate suggestion on how to add the – separator to the string on each permission (r/w/x)

def octal_to_string(octal):
    result = ""
    value_letters = [(4,"r"),(2,"w"),(1,"x")]
    #Iterating over each digit in octal
    for digit in [int(n) for n in str(octal)]:

        #Checking for each of permission values
        for value, letter in value_letters:
            if digit >= value:
                result += letter
                digit -= value
            else:
                pass
    return result

I currently get:

In [7]: octal_to_string(755)
Out[7]: 'rwxrxrx'

In [8]: octal_to_string(644)
Out[8]: 'rwrr'
Asked By: Karimi254

||

Answers:

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
Answered By: Martijn Pieters

Change the pass to result += "-":

def octal_to_string(octal): 
    result = "" 
    value_letters = [(4,"r"),(2,"w"),(1,"x")] 
    #Iterating over each digit in octal 
    for digit in [int(n) for n in str(octal)]: 

        #Checking for each of permission values 
        for value, letter in value_letters: 
            if digit >= value: 
                result += letter 
                digit -= value 
            else: 
                result += "-" 
    return result 

print(octal_to_string(755))

Output:

rwxr-xr-x
Answered By: Joan Lara Ganau
def octal_to_string(octal):
    result = ""
    value_letters = [(4,"r"),(2,"w"),(1,"x")]
    # Iterate over each of the digits in octal
    for digits in [int(n) for n in str(octal)]:
        # Check for each of the permissions values
        for value, letter in value_letters:
            if digits >= value:
                result += letter
                digits -= value
            else:
                result += "-"
    return result
Answered By: Sapan Sidhwani
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.