String output modifiers in Python - python

In C++, objects can be output by "left-shifting" them to cout. They can be preceded by modifiers that change the output:
// print 2 numbers 'a' and 'b' in 0xAAAABBBB (hex) format
cout << "0x" << hex << uppercase << setw(4) << setfill('0') << a
(Source)
I'm looking for something similar in Python: I have a class for which I want two different possible outputs: it's something containing a float which I want to output either as a normal float or as a fraction. Currently, I'm passing a use_fractions flag in the constructor and have an if use_fractions: ... else: ... conditional in the __str__ and __repr__ members. But I find that logically flawed: the output format isn't some intrinsic property of the object, so I don't want to pass it to the constructor.
So my question is, is there any sort of modifier to __str__ comparable to the C++ example above? Something like a "contextual" parameter that can be set, and whose state I can check within __str__?

In Python, you'd use string formatting with str.format() or format(), which delegates handling of the actual formatting to a .__format__() special method.
The special method is passed the actual format spec; you can use anything you like there:
>>> class Foo(object):
... def __format__(self, spec):
... if spec == 'f':
... return 'fractions used'
... else:
... return 'decimals used'
...
>>> format(Foo(), 'f')
'fractions used'
>>> format(Foo(), 'g')
'decimals used'
The datetime.datetime() type uses this to support full strptime formatting, for example:
>>> from datetime import datetime
>>> format(datetime.now(), '%Y')
'2014'

You could do something like this:
class StringState():
fraction = False
class SetFraction():
def __str__(self):
StringState.fraction = True
return ""
class UnsetFraction():
def __str__(self):
StringState.fraction = False
return ""
class Test():
def __init__(self):
self.value = 0.05
def __str__(self):
if StringState.fraction:
return "1/20"
else:
return "0.05"
print Test(),'\n',SetFraction(),Test(),'\n',UnsetFraction(),Test()
Output:
0.05
1/20
0.05
I don't think there's any way to attach state to print itself, but if you use your own separate class, and then reference it in your print statements, you can achieve the same effect. There's probably a way to avoid the ugly spaces too.

Related

How to print an object's representation using the string format function?

I'm creating a Money class, and I'd like to pass the object directly to the string format() function and get the money representation with 2 decimals and the currency symbol.
What method should I override to print with the string format function? Overriding str and repr did not work.
from decimal import Decimal
class Money(Decimal):
def __str__(self):
return "$" + format(self, ',.2f')
def __repr__(self):
return "$" + format(self, ',.2f')
m = Money("123.44")
print(m) # $123.44. Good.
m # $123.44. Good.
print("Amount: {0}".format(m)) # 123.44. Bad. I wanted $123.44
print(f"Amount: {m}") # 123.44. Bad. I wanted $123.44
You can give your class a __format__ method; in this case just call overridden version:
def __format__(self, spec):
spec = spec or ',.2f' # set a default spec when not explicitly given
return '$' + super().__format__(spec)
From the linked documentation:
Called by the format() built-in function, and by extension, evaluation of formatted string literals and the str.format() method, to produce a “formatted” string representation of an object. The format_spec argument is a string that contains a description of the formatting options desired. The interpretation of the format_spec argument is up to the type implementing __format__(), however most classes will either delegate formatting to one of the built-in types, or use a similar formatting option syntax.
You'll want to drop your __str__ and __repr__ implementations now, or at least not add another '$' on top of the one __format__ now adds (which format(self, ...) will trigger).
Demo:
>>> from decimal import Decimal
>>> class Money(Decimal):
... def __format__(self, spec):
... spec = spec or ',.2f' # set a default spec when not explicitly given
... return '$' + super().__format__(spec)
...
>>> m = Money("123.44")
>>> print("Amount: {0}".format(m))
Amount: $123.44
>>> print(f"Amount: {m}")
Amount: $123.44

I don't get what's the difference between format() and ... (python)

Confused newbie here. What's the difference between using:
print ("So you are {0} years old".format(age))
AND
print ("So you are", age, "years old")
Both work.
Actually there's a huge difference. The former use string's format method to create a string. The latter, pass several arguments to print function, which will concatenate them all adding a whitespace (default) between them.
The former is far more powerful, for instance, you can use the format syntax to accomplish things like:
# trunc a float to two decimal places
>>> '{:.2f}'.format(3.4567)
'3.46'
# access an objects method
>>> import math
>>> '{.pi}'.format(math)
'3.141592653589793'
It is similar to printf style formats used in earlier versions of python with the % operator: (ie: "%d" % 3) Now str.format() is recommended over the % operator and is the new standard in Python 3.
>>> class Age:
... def __format__(self, format_spec):
... return "{:{}}".format("format", format_spec)
... def __str__(self):
... return "str"
...
>>> age = Age()
>>> print(age)
str
>>> print("{:s}".format(age))
format
format() allows to convert the same object into a string using different representations specified by format_spec. print uses __str__ or __repr__ if the former is not defined. format() may also use __str__, __repr__ if __format__ is not defined.
In Python 2 you could also define __unicode__ method:
>>> class U:
... def __unicode__(self):
... return u"unicode"
... def __str__(self):
... return "str"
... def __repr__(self):
... return "repr"
...
>>> u = U()
>>> print(u"%s" % u)
unicode
>>> print(u)
str
>>> print(repr(u))
repr
>>> u
repr
There is also ascii() builtin function in Python 3 that behaves like repr() but produces ascii-only results:
>>> print(ascii("🐍"))
'\U0001f40d'
See U+1F40D SNAKE.
format() uses Format Specification Mini-Language instead of running various conversion to string functions.
An object may invent its own format_spec language e.g., datetime allows to use strftime formats:
>>> from datetime import datetime
>>> "{:%c}".format(datetime.utcnow())
'Sun May 4 18:51:18 2014'
The former is more convenient. Imagine if you have lots of parameters, you'll end up with something like this:
print ("So your name is ", firstname, " ", lastname, " and you are ", age, " years old")
This is a pain to both read and write. So the format method is there to help you write cleaner and more readable strings.

Convention to print an object in python

Is there any standard convention to print an object in python. I know that if I just try to print the object it would print the memory address but I would like to overwrite that method and be able to print human readable format of the object to help in debugging.
is there any standard convention people follow or is it not a good way to define such a method instead there are better alternatives?
You can overwrite either the __str__ or the __repr__ method.
There is no convention on how to implement the __str__ method; it can just return any human-readable string representation you want. There is, however, a convention on how to implement the __repr__ method: it should return a string representation of the object so that the object could be recreated from that representation (if possible), i.e. eval(repr(obj)) == obj.
Assuming you have a class Point, __str__ and __repr__ could be implemented like this:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return "(%.2f, %.2f)" % (self.x, self.y)
def __repr__(self):
return "Point(x=%r, y=%r)" % (self.x, self.y)
def __eq__(self, other):
return isinstance(other, Point) and self.x == other.x and self.y == other.y
Example:
>>> p = Point(0.1234, 5.6789)
>>> str(p)
'(0.12, 5.68)'
>>> "The point is %s" % p # this will call str
'The point is (0.12, 5.68)'
>>> repr(p)
'Point(x=0.1234, y=5.6789)'
>>> p # echoing p in the interactive shell calls repr internally
Point(x=0.1234, y=5.6789)
>>> eval(repr(p)) # this echos the repr of the new point created by eval
Point(x=0.1234, y=5.6789)
>>> type(eval(repr(p)))
<class '__main__.Point'>
>>> eval(repr(p)) == p
True
Implement function __str__ in the class for the object you are printing.
If you are printing objects for a class that you can't alter then it is fairly straightforward to provide your own print function, since you are using Python 3.
Edit: Usually the string returned by __str__ will be specific to the class, but will at least be enough to identify the object. The exact format of the string will vary depending on the class and public attributes.
Edit2: Here is a simple (cutdown) example from a class describing countries:
def __str__(self):
return "{0:<32} {1:>010}".
format(self.__name, self.__population)
If your object can be represented in a way that allows recreation, then override the __repr__ function. For example, if you can create your object with the following code:
MyObject('foo', 45)
The the __repr__ should return "MyObject('foo', 45)". You then don't need to implement a __str__.
But if the object is so complex that you can't represent it like that, override __str__ instead. You should then return something that both makes it clear the object can't be recreated, and that it is an object. Hence, don't return "foo:45", because that looks like a string, or {'foo': 45} because that looks like a dictionary, and that will confuse you when you debug.
I'd recommend that you keep the brackets, for example <MyObject foo:45>. That way it is clear that you have been printing an object, and it is also clear that it is not just a question of writing MyObject('foo', 45) to recreate the object, but that there is more data stored.
The standard way to print custom info about an object (class instance) is to use __str__ method:
class A:
var = 1
def __str__(self):
return 'Accessing from print function, var = {0}'.format(self.var)
In this method you can display any info you want
a = A()
print(a)
>>> Accessing from print function, var = 1

How to apply __str__ function when printing a list of objects in Python [duplicate]

This question already has answers here:
How to print instances of a class using print()?
(12 answers)
Closed 7 months ago.
Well this interactive python console snippet will tell everything:
>>> class Test:
... def __str__(self):
... return 'asd'
...
>>> t = Test()
>>> print(t)
asd
>>> l = [Test(), Test(), Test()]
>>> print(l)
[__main__.Test instance at 0x00CBC1E8, __main__.Test instance at 0x00CBC260,
__main__.Test instance at 0x00CBC238]
Basically I would like to get three asd string printed when I print the list. I have also tried pprint but it gives the same results.
Try:
class Test:
def __repr__(self):
return 'asd'
And read this documentation link:
The suggestion in other answers to implement __repr__ is definitely one possibility. If that's unfeasible for whatever reason (existing type, __repr__ needed for reasons other than aesthetic, etc), then just do
print [str(x) for x in l]
or, as some are sure to suggest, map(str, l) (just a bit more compact).
You need to make a __repr__ method:
>>> class Test:
def __str__(self):
return 'asd'
def __repr__(self):
return 'zxcv'
>>> [Test(), Test()]
[zxcv, zxcv]
>>> print _
[zxcv, zxcv]
Refer to the docs:
object.__repr__(self)
Called by the repr() built-in function and by string conversions (reverse quotes) to compute the “official” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form <...some useful description...> should be returned. The return value must be a string object. If a class defines __repr__() but not __str__(), then __repr__() is also used when an “informal” string representation of instances of that class is required.
This is typically used for debugging, so it is important that the representation is information-rich and unambiguous.

What is the meaning of %r?

What's the meaning of %r in the following statement?
print '%r' % (1)
I think I've heard of %s, %d, and %f but never heard of this.
Background:
In Python, there are two builtin functions for turning an object into a string: str vs. repr. str is supposed to be a friendly, human readable string. repr is supposed to include detailed information about an object's contents (sometimes, they'll return the same thing, such as for integers). By convention, if there's a Python expression that will eval to another object that's ==, repr will return such an expression e.g.
>>> print repr('hi')
'hi' # notice the quotes here as opposed to...
>>> print str('hi')
hi
If returning an expression doesn't make sense for an object, repr should return a string that's surrounded by < and > symbols e.g. <blah>.
To answer your original question:
%s <-> str
%r <-> repr
In addition:
You can control the way an instance of your own classes convert to strings by implementing __str__ and __repr__ methods.
class Foo:
def __init__(self, foo):
self.foo = foo
def __eq__(self, other):
"""Implements ==."""
return self.foo == other.foo
def __repr__(self):
# if you eval the return value of this function,
# you'll get another Foo instance that's == to self
return "Foo(%r)" % self.foo
It calls repr() on the object and inserts the resulting string.
Adding to the replies given above, '%r' can be useful in a scenario where you have a list with heterogeneous data type.
Let's say, we have a list = [1, 'apple' , 2 , 'r','banana']
Obviously in this case using '%d' or '%s' would cause an error. Instead, we can use '%r' to print all these values.
It prints the replacement as a string with repr().
The difference between %r and %s is, %r calls the repr() method and %s calls the str() method. Both of these are built-in Python functions.
The repr() method returns a printable representation of the given object.
The str() method returns the "informal" or nicely printable representation of a given object.
In simple language, what the str() method does is print the result in a way which the end user would like to see:
name = "Adam"
str(name)
Out[1]: 'Adam'
The repr() method would print or show what an object actually looks like:
name = "Adam"
repr(name)
Out[1]: "'Adam'"
%s <=> str
%r <=> repr
%r calls repr() on the object, and inserts the resulting string returned by __repr__.
The string returned by __repr__ should be unambiguous and, if possible, match the source code necessary to recreate the object being represented.
A quick example:
class Foo:
def __init__(self, foo):
self.foo = foo
def __repr__(self):
return 'Foo(%r)' % self.foo
def __str__(self):
return self.foo
test = Foo('Text')
So,
in[1]: test
Out[1]: Foo('Text')
in[2]: str(test)
Out[2]: 'Text'
%s calls the __str()__ method of the selected object and replaces itself with the return value,
%r calls the __repr()__ method of the selected object and replaces itself with the return value.
See String Formatting Operations in the docs. Notice that %s and %d etc, might work differently to how you expect if you are used to the way they work in another language such as C.
In particular, %s also works well for ints and floats unless you have special formatting requirements where %d or %f will give you more control.
I read in "Learning Python the Hard Way", the author said that
%r is the best for debugging, other formats are for displaying variables to users

Categories