Python format with variable digits count - python

So, I can do:
>>> '%.4x' % 0x45f
'045f'
But I need to pass 4 from variable, smth like
>>> digits=4
>>> '%.'+str(digits)+'x' % 0x45f
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting

The % operator has a higher precedence than +, so you need to put the first part in parenthesis:
>>> digits = 4
>>> ('%.'+str(digits)+'x') % 0x45f
'045f'
>>>
Otherwise, 'x' % 0x45f will be evaluated first.
However, the modern approach is to use str.format for string formatting operations:
>>> digits = 4
>>> "{:0{}x}".format(0x45f, digits)
'045f'
>>>

Related

Can't get my input value to be used in the subsequent calculation in Python [duplicate]

If I try to do the following:
things = 5
print("You have " + things + " things.")
I get the following error in Python 3.x:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
... and a similar error in Python 2.x:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
How can I get around this problem?
The problem here is that the + operator has (at least) two different meanings in Python: for numeric types, it means "add the numbers together":
>>> 1 + 2
3
>>> 3.4 + 5.6
9.0
... and for sequence types, it means "concatenate the sequences":
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> 'abc' + 'def'
'abcdef'
As a rule, Python doesn't implicitly convert objects from one type to another1 in order to make operations "make sense", because that would be confusing: for instance, you might think that '3' + 5 should mean '35', but someone else might think it should mean 8 or even '8'.
Similarly, Python won't let you concatenate two different types of sequence:
>>> [7, 8, 9] + 'ghi'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
Because of this, you need to do the conversion explicitly, whether what you want is concatenation or addition:
>>> 'Total: ' + str(123)
'Total: 123'
>>> int('456') + 789
1245
However, there is a better way. Depending on which version of Python you use, there are three different kinds of string formatting available2, which not only allow you to avoid multiple + operations:
>>> things = 5
>>> 'You have %d things.' % things # % interpolation
'You have 5 things.'
>>> 'You have {} things.'.format(things) # str.format()
'You have 5 things.'
>>> f'You have {things} things.' # f-string (since Python 3.6)
'You have 5 things.'
... but also allow you to control how values are displayed:
>>> value = 5
>>> sq_root = value ** 0.5
>>> sq_root
2.23606797749979
>>> 'The square root of %d is %.2f (roughly).' % (value, sq_root)
'The square root of 5 is 2.24 (roughly).'
>>> 'The square root of {v} is {sr:.2f} (roughly).'.format(v=value, sr=sq_root)
'The square root of 5 is 2.24 (roughly).'
>>> f'The square root of {value} is {sq_root:.2f} (roughly).'
'The square root of 5 is 2.24 (roughly).'
Whether you use % interpolation, str.format(), or f-strings is up to you: % interpolation has been around the longest (and is familiar to people with a background in C), str.format() is often more powerful, and f-strings are more powerful still (but available only in Python 3.6 and later).
Another alternative is to use the fact that if you give print multiple positional arguments, it will join their string representations together using the sep keyword argument (which defaults to ' '):
>>> things = 5
>>> print('you have', things, 'things.')
you have 5 things.
>>> print('you have', things, 'things.', sep=' ... ')
you have ... 5 ... things.
... but that's usually not as flexible as using Python's built-in string formatting abilities.
1 Although it makes an exception for numeric types, where most people would agree on the 'right' thing to do:
>>> 1 + 2.3
3.3
>>> 4.5 + (5.6+7j)
(10.1+7j)
2 Actually four, but template strings are rarely used, and are somewhat awkward.
Other Resources:
Real Python: Splitting, Concatenating, and Joining Strings in Python
Python.org: string - Common string operations
python string concatenation with int site:stackoverflow.com

format value that could be number and/or string in python 3

Is there a concise way of formatting a number, that on occasion can also be a string?
The number would normally be a float, but occasionally it's also denoted as the string "n/a".
I would like to format the float with a fixed number of decimals, but print the entire string in case it is not a number.
For instance:
var=3.145623
print("This is {0:.2f}".format(var))
>>>This is 3.14
,but
var = "n/a"
print("This is {0:.2f}".format(var))
>>> File "<stdin>", line 1, in <module>
>>> ValueError: Unknown format code 'f' for object of type 'str'
I am not surprised by the ValueError, but wonder if there is a concise way around it, ideally without an explicit if-statement.
Indeed, the f format specifier only works on actual float values. You can't avoid having to special-case your n/a value.
You can format the float separately, and conditionally, then interpolate the result into the larger template:
var_formatted = format(var, '.2f') if var != 'n/a' else var
print("This is {0:4}".format(var_formatted))
If you are really averse to if, you can use exception handling too:
try:
var_formatted = format(var, '.2f')
except ValueError:
var_formatted = 'n/a'
print("This is {0:4}".format(var_formatted))
Another option would be for you to wrap the value in a class with a __format__ method:
class OptionalFloat(object):
def __init__(self, value):
self.value = value
def __format__(self, fmt):
try:
return self.value.__format__(fmt)
except ValueError:
return self.value
print("This is {0:.2f}".format(OptionalFloat(var)))
This moves the requirement to detect the type into another class method, keeping your output code a little cleaner and free of all those pesky conditionals or exception handlers:
>>> var = 3.145623
>>> print("This is {0:.2f}".format(OptionalFloat(var)))
This is 3.15
>>> var = 'n/a'
>>> print("This is {0:.2f}".format(OptionalFloat(var)))
This is n/a
Python supports not-a-number as float('nan') and it may be more useful than the string "n/a" in your code. It works with formatting and produces more sane results than a string if you use it in computations.
NaN:
>>> n = float('nan')
>>> n
nan
>>> "{0:.2f}".format(n)
'nan'
>>> n == 3
False
>>> n * 2
nan
>>> n < 5
False
String:
>>> n = 'n/a'
>>> "{0:.2f}".format(n)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'f' for object of type 'str'
>>> n == 3
False
>>> n * 2
'n/an/a'
>>> n < 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() < int()
maybe something like this
str = "{0:.2f}".format(var) if isinstance(var, float) else var
print(str)

Using str.replace to replace letters in a string at different placeholders of the string

I have a problem that I am working on. The goal of the problem is to take the string placeholder i. If i is an even placeholder, replace the letter at i with the letter at i -1. If the i place holder is odd, then replace the letter i with the letter at i +1.
Here is my code so far:
def easyCrypto (s):
for i in range (0,len(s)-1):
if i % 2 == 0:
str(s).replace(i,((i-1)))
if i % 2 != 0:
str(s).replace(i,((i+2)))
print (s)
My error:
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
easyCrypto('abc')
File "C:/Python/cjakobhomework7.py", line 4, in easyCrypto
str(s).replace(i,((i-1)))
TypeError: Can't convert 'int' object to str implicitly
update!!
New code based on answers:
def easyCrypto (s):
for i in range (0,len(s)-1):
if i % 2 == 0:
s = str(s).replace(s(i),(s(i-1)))
else:
s = s.replace(s(i), s(i + 1))
print (s)
However I still have the following errors:
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
easyCrypto('abc')
File "C:/Python/cjakobhomework7.py", line 4, in easyCrypto
s = str(s).replace(s(i),(s(i-1)))
TypeError: 'str' object is not callable
Any ideas? thank you
Use s[i] instead of s(i), and likewise for the other indexes.
There are two things here:
str.replace does not automatically stringify its arguments. You need to manually convert them into strings. Remember that: "Explicit is better than implicit."
str.replace does not work in-place because strings are immutable in Python. You need to reassign s to the new string object returned by str.replace.
Your code should be:
s = s.replace(str(i), str(i-1))
Also, you can replace if i % 2 != 0: with else: since the condition of the second if-statement can only be true if the first is false:
if i % 2 == 0:
s = s.replace(str(i), str(i-1))
else:
s = s.replace(str(i), str(i+1))
Regarding your edited question, you are trying to call the string s as a function by placing parenthesis after it. You need to use square brackets to index the string:
>>> 'abcde'[0]
'a'
>>> 'abcde'[3]
'd'
>>>
In your case it would be:
s = s.replace(s[i], s[i-1])
As a general rule of thumb, parenthesis (...) are for calling functions while square brackets [...] are for indexing sequences/containers.

Error trying to strip "0x'

I am trying to strip of "0x" form the hex value using below code and running into error,can anyone suggest how to fix it?
with open(r'\\Network\files\build_ver.txt','r+') as f:
value = int(f.read(), 16)
f.seek(0)
write_value = hex(value + 1)
final_value = format(write_value, 'x')
f.write(final_value)
Error:-
Traceback (most recent call last):
File "build_ver.py", line 5, in <module>
final_value = format(write_value, 'x')
ValueError: Unknown format code 'x' for object of type 'str'
The hex built-in returns a string value:
>>> hex(123)
'0x7b'
>>> type(hex(123))
<class 'str'>
>>>
but format is expecting a hexadecimal value as its first argument:
>>> format('0x7b', 'x')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'x' for object of type 'str'
>>>
>>> format(0x7b, 'x')
'7b'
>>>
Thus, it cannot be used here. Instead, you can just strip off the 0x with slicing:
with open(r'\\Network\files\build_ver.txt','r+') as f:
value = int(f.read(), 16)
f.seek(0)
write_value = hex(value + 1)[2:]
f.write(write_value)
[2:] will get every character in the string except for the first two. See a demonstration below:
>>> hex(123)
'0x7b'
>>> hex(123)[2:]
'7b'
>>>

String to Int conversion in python

If I have a string "2+3", is there anyway to convert it to an integer so it comes out as 5?
I tried this:
string = 2+3
answer = int(string)
But I get an error:
ValueError: invalid literal for int() with base 10: '2+3'
I'm trying to take a fully parenthesized equation and use stacks to answer it.
ex. Equation = ((2+3) - (4*1))
I tried taking the equation as an input, but python just solves it on its own.
So to avoid that problem, I took the equation as a raw_input.
There is one way, eval function..
>>> x = raw_input()
2 + 6
>>> x
'2 + 6'
>>> eval(x)
8
But be sure to verify that the input only has numbers,and symbols.
>>> def verify(x):
for i in x:
if i not in '1234567890.+-/*%( )':
return False
return True
>>> x = raw_input()
2 + 6
>>> x
'2 + 6'
>>> if verify(x):
print eval(x)
8
ast.literal_eval doesn't work:
>>> ast.literal_eval('2+3')
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
ast.literal_eval('2+3')
File "C:\Python2.7 For Chintoo\lib\ast.py", line 80, in literal_eval
return _convert(node_or_string)
File "C:\Python2.7 For Chintoo\lib\ast.py", line 79, in _convert
raise ValueError('malformed string')
ValueError: malformed string
Use eval (and remember to sanitize your input. More on this if you read the docs):
>>> eval('2+3')
5
It even supports variables:
>>> x = 1
>>> eval('x+1')
2

Categories