Difference between `print(9)` and `print(str(9))` - python-3.x

What is the difference between print(9) and print(str(9)) in Python when the output is the same for both functions?

print will always first try to call __str__ on the object you give it. In the first case the __str__ of the int instance 9 is '9'.
In the second case, you first explicitly call str on 9 (which calls its __str__ and yields '9'). Then, print calls '9''s __str__ which, if supplied with a string instance, returns it as it is resulting in '9' again.
So in both cases, in the end print will print out similar output.

From the documentation:
All non-keyword arguments are converted to strings like str() does

print(str(9))
print(9)
Output:
9
9
There is no change in output. But if we check the data type by executing,
print(type(str(9)))
print(type(9))
Then we get output as,
<class 'str'>
<class 'int'>
So, you can see, the types are different but the output is same.

In simple terms:
An integer is a variable that specifically holds a numerical value. Whereas a string is a variable that can hold a range of characters (including numbers).
print(9) says it should print the NUMERICAL value 9
print(str(9)) says it should print the character 9,
So if you were to do additions on both types for instance:
9 + 9 will always return 18
str(9) + str(9) will always return 99

Related

Beginner Question why can I do str(number) and not str(letter)

As the title says, I dont understand why letters without quotes doesn't convert into a string while using the str() method.
f = str(ab)
print(type(ab))
print(type(f))
returns a NameError: name 'ab' is not defined.
So I have to write it as 'ab'.
When using numbers, I do not need the quotes, like
f = str(10)
print(type(10))
print(type(f))
returns
<class 'int'>
<class 'str'>
Is it because letters doesnt belong to a class?
Because variables are any combination of letters/numbers and symbols, such as Hello_There. Therefore as far as Python is concerned ab is a variable name, not a string. To tell Python its a string you have to put quote marks around it.

Inner workings of map() in a specific parsing situation

I know there are already at least two topics that explain how map() works but I can't seem to understand its workings in a specific case I encountered.
I was working on the following Python exercise:
Write a program that computes the net amount of a bank account based a
transaction log from console input. The transaction log format is
shown as following:
D 100
W 200
D means deposit while W means withdrawal. Suppose the following input
is supplied to the program:
D 300
D 300
W 200
D 100
Then, the output should be:
500
One of the answers offered for this exercise was the following:
total = 0
while True:
s = input().split()
if not s:
break
cm,num = map(str,s)
if cm=='D':
total+=int(num)
if cm=='W':
total-=int(num)
print(total)
Now, I understand that map applies a function (str) to an iterable (s), but what I'm failing to see is how the program identifies what is a number in the s string. I assume str converts each letter/number/etc in a string type, but then how does int(num) know what to pick as a whole number? In other words, how come this code doesn't produce some kind of TypeError or ValueError, because the way I see it, it would try and make an integer of (for example) "D 100"?
first
cm,num = map(str,s)
could be simplified as
cm,num = s
since s is already a list of strings made of 2 elements (if the input is correct). No need to convert strings that are already strings. s is just unpacked into 2 variables.
the way I see it, it would try and make an integer of (for example) "D 100"?
no it cannot, since num is the second parameter of the string.
if input is "D 100", then s is ['D','100'], then cm is 'D' and num is '100'
Then since num represents an integer int(num) is going to convert num to its integer value.
The above code is completely devoid of error checking (number of parameters, parameters "type") but with the correct parameters it works.
and map is completely useless in that particular example too.
The reason is the .split(), statement before in the s = input().split(). This creates a list of the values D and 100 (or ['D', '100']), because the default split character is a space ( ). Then the map function applies the str operation to both 'D' and '100'.
Now the map, function is not really required because both values upon input are automatically of the type str (strings).
The second question is how int(num) knows how to convert a string. This has to do with the second (implicit) argument base. Similar to how .split() has a default argument of the character to split on, so does num have a default argument to convert to.
The full code is similar to int(num, base=10). So as long as num has the values 0-9 and at most 1 ., int can convert it properly to the base 10. For more examples check out built in int.

Confusion with valueError vs ValueType try/exception

I have a follow up question to a post I saw on converting a str() input to a int() type. Based on the definitions of valueError and valueType I would expect the valueType exception to have been used however, it doesn't work (when i tried it). ValueError works but I'm not sure why, isn't int('some string') an example of a wrong type?
Link to original post i'm referring to: Converting String to Int using try/except in Python
From the docs:
class int(x, base=10) Return an integer object constructed from a
number or string x, or return 0 if no arguments are given. If x is a
number, return x.int(). For floating point numbers, this truncates
towards zero.
If x is not a number or if base is given, then x must be a string,
bytes, or bytearray instance representing an integer literal in radix
base. Optionally, the literal can be preceded by + or - (with no space
in between) and surrounded by whitespace. A base-n literal consists of
the digits 0 to n-1, with a to z (or A to Z) having values 10 to 35.
The default base is 10. The allowed values are 0 and 2–36. Base-2, -8,
and -16 literals can be optionally prefixed with 0b/0B, 0o/0O, or
0x/0X, as with integer literals in code. Base 0 means to interpret
exactly as a code literal, so that the actual base is 2, 8, 10, or 16,
and so that int('010', 0) is not legal, while int('010') is, as well
as int('010', 8).
When you call the int() function on a string it will try to convert it to the specified base in the arguments (by default base-10) by iterating over the string and converting the string object over to an int object in the desired base. If it reaches a point where the conversion can not be made due to illegal syntax , it will raise a ValueError so terminate the program early. If for some reason you want to go forward you can but a try: except block in the code to catch the exception.
From the Docs:
exception ValueError Raised when a built-in operation or function
receives an argument that has the right type but an inappropriate
value, and the situation is not described by a more precise exception
such as IndexError.

Cannot return a float value of -1.00

I am currently doing an assignment for a computer science paper at university. I am in my first year.
in one of the questions, if the gender is incorrect the function is suppose to return a value of -1. But in the testing column, it says the expected value is -1.00. And I cannot seem to be able to return the value of '-1.00', it will always return a value of -1.0 (with one zero). I used the .format to make the value 2sf (so it will appear with two zero's) but when converting it to a float the value always returns "-1.0".
return float('{:.2f}'.format(-1))
This isn’t as clear as it could be. Does your instructor or testing
software expect a string '-1.00'? If so, just return that. Is a
float type expected? Then return -1.0; the number of digits shown does
not affect the value.
I don't know exactly what you have done, but i had tried this way and output what you expect.
b = -1
>>> print("%.2f" % (b))
-1.00
>>> print("%.2f" % (-1))
-1.00
What does the following code do?
print(float('{:.2f}'.format(-1)))
The '{:.2f}'.format(-1) creates some string representation of -1. defined by the format string. The float(...) converts this string to the float 1. The print command converts this float to a sting, using some default format, and prints this string to the screen. I think that isn't what you expected because the format you used does not effect the print command in formatting the string.
I assume you want
print('{:.2f}'.format(float(-1)))
and this actually does what you want, it prints
1.00
http://ideone.com/GyINQR
It is not necessary to convert -1 explicitely to float
print('{:.2f}'.format(-1))
gives the desired result:
http://ideone.com/U2RTMX

Python bytes concatenation

I want to concatenate the first byte of a bytes string to the end of the string:
a = b'\x14\xf6'
a += a[0]
I get an error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't concat bytes to int
When I type bytes(a[0]) I get:
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
And bytes({a[0]}) gives the correct b'\x14'.
Why do I need {} ?
If you want to change your byte sequence, you should use a bytearray. It is mutable and has the .append method:
>>> a = bytearray(b'\x14\xf6')
>>> a.append(a[0])
>>> a
bytearray(b'\x14\xf6\x14')
What happens in your approach: when you do
a += a[0]
you are trying to add an integer to a bytes object. That doesn't make sense, since you are trying to add different types.
If you do
bytes(a[0])
you get a bytes object of length 20, as the documentation describes:
If [the argument] is an integer, the array will have that size and will be initialized with null bytes.
If you use curly braces, you are creating a set, and a different option in the constructor is chosen:
If it is an iterable, it must be an iterable of integers in the range 0 <= x < 256, which are used as the initial contents of the array.
Bytes don't work quite like strings. When you index with a single value (rather than a slice), you get an integer, rather than a length-one bytes instance. In your case, a[0] is 20 (hex 0x14).
A similar issue happens with the bytes constructor. If you pass a single integer in as the argument (rather than an iterable), you get a bytes instance that consists of that many null bytes ("\x00"). This explains why bytes(a[0]) gives you twenty null bytes. The version with the curly brackets works because it creates a set (which is iterable).
To do what you want, I suggest slicing a[0:1] rather than indexing with a single value. This will give you a bytes instance that you can concatenate onto your existing value.
a += a[0:1]
bytes is a sequence type. Its individual elements are integers. You can't do a + a[0] for the same reason you can't do a + a[0] if a is a list. You can only concatenate a sequence with another sequence.
bytes(a[0]) gives you that because a[0] is an integer, and as documented doing bytes(someInteger) gives you a sequence of that many zero bytes (e.g,, bytes(3) gives you 3 zero bytes).
{a[0]} is a set. When you do bytes({a[0]}) you convert the contents of that set into a bytes object. This is not a great way to do it in general, because sets are unordered, so if you try to do it with more than one byte in there you may not get what you expect.
The easiest way to do what you want is a + a[:1]. You could also do a + bytes([a[0]]). There is no shortcut for creating a single-element bytes object; you have to either use a slice or make a length-one sequence of that byte.
Try this
values = [0x49, 0x7A]
concat = (values[0] << 8) + values[1]
print(hex(concat))
you should get 0x497A

Resources