repr(): evaluatable string representation of an object (can "eval()"
it, meaning it is a string representation that evaluates to a Python
object)
In other words:
>>> x = 'foo'
>>> repr(x)
"'foo'"
Questions:
Why do I get the double quotes when I do repr(x)? (I don't get them
when I do str(x))
Why do I get 'foo' when I do eval("'foo'") and not x which is the
object?
>>> x = 'foo'
>>> x
'foo'
So the name x is attached to 'foo' string. When you call for example repr(x) the interpreter puts 'foo' instead of x and then calls repr('foo').
>>> repr(x)
"'foo'"
>>> x.__repr__()
"'foo'"
repr actually calls a magic method __repr__ of x, which gives the string containing the representation of the value 'foo' assigned to x. So it returns 'foo' inside the string "" resulting in "'foo'". The idea of repr is to give a string which contains a series of symbols which we can type in the interpreter and get the same value which was sent as an argument to repr.
>>> eval("'foo'")
'foo'
When we call eval("'foo'"), it's the same as we type 'foo' in the interpreter. It's as we directly type the contents of the outer string "" in the interpreter.
>>> eval('foo')
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
eval('foo')
File "<string>", line 1, in <module>
NameError: name 'foo' is not defined
If we call eval('foo'), it's the same as we type foo in the interpreter. But there is no foo variable available and an exception is raised.
>>> str(x)
'foo'
>>> x.__str__()
'foo'
>>>
str is just the string representation of the object (remember, x variable refers to 'foo'), so this function returns string.
>>> str(5)
'5'
String representation of integer 5 is '5'.
>>> str('foo')
'foo'
And string representation of string 'foo' is the same string 'foo'.
The feedback you get on the interactive interpreter uses repr too. When you type in an expression (let it be expr), the interpreter basically does result = expr; if result is not None: print repr(result). So the second line in your example is formatting the string foo into the representation you want ('foo'). And then the interpreter creates the representation of that, leaving you with double quotes.
Why when I combine %r with double-quote and single quote escapes and print them out, it prints it the way I'd write it in my .py file but not the way I'd like to see it?
I'm not sure what you're asking here. The text single ' and double " quotes, when run through repr, includes escapes for one kind of quote. Of course it does, otherwise it wouldn't be a valid string literal by Python rules. That's precisely what you asked for by calling repr.
Also note that the eval(repr(x)) == x analogy isn't meant literal. It's an approximation and holds true for most (all?) built-in types, but the main thing is that you get a fairly good idea of the type and logical "value" from looking the the repr output.
str() is used for creating output for end user while repr() is used for debugging during development. And it's an official representation of the object.
Example:
>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2018-04-08 18:00:15.178404'
>>> repr(today)
'datetime.datetime(2018, 4, 8, 18, 3, 21, 167886)'
From output we see that repr() shows the official representation of date object.
1) The result of repr('foo') is the string 'foo'. In your Python shell, the result of the expression is expressed as a representation too, so you're essentially seeing repr(repr('foo')).
2) eval calculates the result of an expression. The result is always a value (such as a number, a string, or an object). Multiple variables can refer to the same value, as in:
x = 'foo'
y = x
x and y now refer to the same value.
3) I have no idea what you meant here. Can you post an example, and what you'd like to see?
When you say
foo = 'bar'
baz(foo)
you are not passing foo to the baz function. foo is just a name used to represent a value, in this case 'bar', and that value is passed to the baz function.
Related
I use a negative index in replacement fields to output a formatted list,but it raises a TypeError.The codes are as follows:
>>> a=[1,2,3]
>>> a[2]
3
>>> a[-1]
3
>>> 'The last:{0[2]}'.format(a)
'The last:3'
>>> 'The last:{0[-1]}'.format(a)
Traceback (most recent call last):
File "", line 1, in
TypeError: list indices must be integers, not str
It's what I would call a design glitch in the format string specs. Per the docs,
element_index ::= integer | index_string
but, alas, -1 is not "an integer" -- it's an expression. The unary-minus operator doesn't even have particularly high priority, so that for example print(-2**2) emits -4 -- another common issue and arguably a design glitch (the ** operator has higher priority, so the raise-to-power happens first, then the change-sign requested by the lower priority unary -).
Anything in that position in the format string that's not an integer (but, for example, an expression) is treated as a string, to index a dict argument -- for example:
$ python3 -c "print('The last:{0[2+2]}'.format({'2+2': 23}))"
The last:23
Not sure whether this is worth raising an issue in the Python trac, but it's certainly a somewhat surprising behavior:-(.
There are a few problems here, once you start digging:
The item in question is called "element_index" which is defined to be an integer.
Problem 1: unless users follow the link from "integer" to the language reference manual, they won't know that -1 is deemed to be an expression, not an integer. By the way, anyone tempted to say "works as documented" should see proplem 7 first :-)
Preferred solution: change the definition so that "element_index" can have an optional '-' before the integer.
It's an integer, right? Not so fast ... later the docs say that "an expression of the form '[index]' does an index lookup using __getitem__()"
Problem 3: Should say '[element_index]' (index is not defined).
Problem 4: Not everybody knows off the top of their heads what __getitem__() does. Needs clearer docs.
So we can use a dict here as well as an integer, can we? Yes, with a problem or two:
The element_index is a integer? Yes, that works with a dict:
>>> "{0[2]}".format({2: 'int2'})
'int2'
It seems that we can also use non-integer strings, but this needs more explicit documentation (Problem 5):
>>> "{0[foo]}".format({'foo': 'bar'})
'bar'
But we can't use a dict with a key like '2' (Problem 6):
>>> "{0[2]}".format({'2': 'str2'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 2
>>> "{0['2']}".format({'2': 'str2'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: "'2'"
Problem 7: That "integer" should really be documented to be "decimalinteger" ... 0x22 and 0b11 are treated as str, and 010 (an "octalinteger") is treated as 10, not 8:
>>> "{0[010]}".format('0123456789abcdef')
'a'
Update: PEP 3101 tells the true story:
"""
The rules for parsing an item key are very simple. If it starts with a digit, then it is treated as a number, otherwise it is used as a string.
Because keys are not quote-delimited, it is not possible to specify arbitrary dictionary keys (e.g., the strings "10" or ":-]") from within a format string.
"""
Correct, it does not work. solution:
>>> 'The last:{0}'.format(a[-1])
'The last:3'
I often take Python format strings as config options - with the format string provided with a specific, known list of keyword arguments. Therefore addressing the indexes of a variable length list forwards or backwards within the format string is exactly the kind of thing I end up needing.
I've just written this hack to make the negative indexing work:
string_to_tokenise = "Hello_world"
tokens = re.split(r"[^A-Z\d]+", string_to_tokenise, flags=re.I)
token_dict = {str(i) if i < 0 else i: tokens[i] for i in range(-len(tokens) + 1, len(tokens))}
print "{thing[0]} {thing[-1]}".format(thing=token_dict)
Result:
Hello world
So to explain, instead of passing in the list of tokens, I create a dictionary with all the required integer keys for indexing the list from 0 to len(..)-1, and I also add the negative integer keys for indexing from the end from -1 to -(len(..)-1), however these keys are converted from integers to strings, as that's how format will interpret them.
Can someone explain why the x below can act as a function float()? Basically I dont understand what means? is this a internal function or implicit object ?
>>> x=type(0.0)
>>> x
<type 'float'>
>>> x('9.823')
9.823
It's exactly the same as writing float('9.823'). In fact, you can easily see that as follows:
>>> type(0.0) is float
True
>>>
And you can use them in exactly the same way:
>>> float('9.823')
9.823
>>> type(0.0)('9.823')
9.823
>>>
It's just invokes the constructor for the float type.
You're setting the variable x to the type float. The command type() returns the type of whatever is inside the brackets. In your case, you provided the type command with a float and setting that return of float to your variable x.
It can act as the function float because you are effectively making x = float.
As an example, you could also, for instance do this:
x = type(1) #int
print x(1.1111) # will print 1
As I understand there are no declaration types in Python. When you need an integer or list you would do:
integer = 5
list_of_integers = [0, 1, 2]
This link to the documentation tells me that int in Python is a built-in function.
I'm aware of functions such as str() and int() to convert an integer to string and vice-versa.
But I have never seen a use of int as a type with dot notation E.g. *int.[function_name]*
How come it can be both a type and a function with the same name? Are there other types such as float, double, and etc. which can be used with dot notation and as well as a function?
int and str are classes. As with any class in Python, calling it gives you an instance. And as with any instance, you certainly can call methods on it. int doesn't have that many user-callable methods, but str certainly does: some of the common ones include strip, split, upper, etc.
>>> x = str()
>>> x.upper()
''
Edit
It's still a class. You can do exactly the same with any class, even ones you define yourself:
>>> class Foo(object):
... def bar(self):
... print self.baz
...
>>> f=Foo()
>>> f.baz = 'quux'
>>> f.bar()
quux
>>> Foo.bar(f)
quux
The last operation here is exactly the same idea as calling str.upper(x)
int and str aren't functions.
They are basically data types which in python are actually classes containing different functions of their own.
That's why you can convert an integer to a string using the str(int) method but you can't do the same with int(string) to convert a string to an integer.
And as these are classes one can say that there are different functions (methods) in the class which are in turn use with the dot notation.
We have a list:
myList = [1, "two"]
And want to print it out, normally I would use something like:
"{0} and {1}".format(*myList)
But you could also do:
" and ".join(myList)
But unfortunately:
>>> " and ".join(myList)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected string, int found
Why doesn't it just automatically convert the list it receives to strings?
When would you ever not need it to convert them to strings? Is there some tiny edge case I'm missing?
From the Zen of Python:
Explicit is better than implicit.
and
Errors should never pass silently.
Converting to strings implicitly can easily hide bugs, and I'd really want to know if I suddenly have different types somewhere that were meant to be strings.
If you want to explicitly convert to strings, you can do so using map(), for example:
''.join(map(str, myList))
The problem with attempting to execute something like x = 4 + "8" as written is that the intended meaning is ambiguous. Should x contain "48" (implicitly converting 4 to str) or 12 (implicitly converting "8" to int)? We can't justify either result.
To avoid this confusion, Python requires explicit conversion of one of the operands:
>>> x = str(4) + "8"
>>> y = 4 + int("8")
>>> print x
48
>>> print y
12
Using the correct type is part of programming in Python. A general built-in like print does do the conversion (if the class supports __str__), which is where you should be doing it:
Let print do the work:
print(*myList, sep = " and ")
That's for Python 3, if you are still on Python 2 then use:
from __future__ import print_function
>>> foo = 1
>>> type(foo)
<type 'int'>
>>> type(str(foo))
<type 'str'>
>>> type(`foo`)
<type 'str'>
Which is the more Pythonic way of converting integers to strings? I have always been using the first method but I now find the second method more readable. Is there a practical difference?
String conversions using backticks are a shorthand notation for calling repr() on a value. For integers, the resulting output of str() and repr() happens to be the same, but it is not the same operation:
>>> example = 'bar'
>>> str(example)
'bar'
>>> repr(example)
"'bar'"
>>> `example`
"'bar'"
The backticks syntax was removed from Python 3; I wouldn't use it, as an explicit str() or repr() call is far clearer in its intent.
Note that you have more options to convert integers to strings; you can use str.format() or old style string formatting operations to interpolate an integer into a larger string:
>>> print 'Hello world! The answer is, as always, {}'.format(42)
Hello world! The answer is, as always, 42
which is much more powerful than using string concatenation.