Formatting problem from string to Datetime [duplicate] - python

This question already has answers here:
What is the difference between __str__ and __repr__?
(28 answers)
Closed 5 months ago.
I'm trying to parse a string with the datetime standard library module and then display it.
When I try this code, the output looks correct:
>>> import datetime
>>> endDate = datetime.datetime.strptime("2022-05-03", '%Y-%m-%d').date()
>>> print(endDate)
2022-05-03
But it changes if the endDate is put into a list or tuple:
>>> print([endDate])
[datetime.date(2022, 5, 3)]
Why does the output have the "datetime.date" text?

>>> from datetime import datetime
>>> endDate = datetime.strptime("2022-05-03", '%Y-%m-%d').date()
When you printed the date object, it used str representation of the date object.
>>> str(endDate)
'2022-05-03'
When you included that in a container and printed it, the container internally uses repr representation of the object
>>> repr(endDate)
'datetime.date(2022, 5, 3)'
print function by default converts all the objects passed to it to a String with str.
All non-keyword arguments are converted to strings like str() does
To understand this better, we can create a class which implements both __str__ and __repr__ functions like this
>>> class Test:
... def __str__(self):
... return "TEST_FROM_STR"
...
... def __repr__(self):
... return "TEST_FROM_REPR"
...
Now, we can create instances of that class and print them separately and with list, like this
>>> Test()
TEST_FROM_REPR
>>> [Test()]
[TEST_FROM_REPR]
>>> print(Test())
TEST_FROM_STR
>>> print([Test()])
[TEST_FROM_REPR]

Related

What to do with the error [<__main__.Student object at 0x000001E84D968090>, <__main__.Student object at 0x000001E84D95E750>] [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.

Default function in python shell [duplicate]

This question already has answers here:
Python console default hex display
(5 answers)
Closed 1 year ago.
Entering an expression in Python shell outputs the repr() of the expression.
Is it possible to set this default function to some user defined function?
What you are looking for is sys.displayhook:
sys.displayhook is called on the result of evaluating an expression entered in an interactive Python session. The display of these values can be customized by assigning another one-argument function to sys.displayhook.
Normal behaviour:
>>> from datetime import datetime
>>> datetime.now()
datetime.datetime(2021, 11, 25, 15, 26, 1, 772968)
then
>>> import sys
>>> def new_hook(value):
... sys.stdout.write(str(value))
... sys.stdout.write("\n")
...
>>> sys.displayhook = new_hook
modified behaviour:
>>> datetime.now()
2021-11-25 15:26:14.177267

What does colon mean in Python string formatting?

I am learning the Python string format() method. Though I understand that {} is a placeholder for arguments, I am not sure what : represent in the following code snippet from Programiz tutorial:
import datetime
# datetime formatting
date = datetime.datetime.now()
print("It's now: {:%Y/%m/%d %H:%M:%S}".format(date))
# custom __format__() method
class Person:
def __format__(self, format):
if(format == 'age'):
return '23'
return 'None'
print("Adam's age is: {:age}".format(Person()))
Why is there a : in front of %Y in print("It's now: {:%Y/%m/%d...? The code outputs It's now: 2021, and there is no : in front of 2021.
Why is there a : in front of age in print("Adam's age is: {:age}...?
Thanks in advance for your valuable input!!
Everything after : is a parameter to the __format__() method of the class of the corresponding arguent. For instance, for a number you can write {:.2f} to format it as a decimal number with 2 digits of precision after the decimal point.
For a datetime value, it's a format string that could be used with datetime.strftime().
And in your Person class, it will be passed as the format argument to Person.__format__(). So if you don't put :age there, the if condition will fail and it will print None instead of 23.
Python objects decide for themselves how they should be formatted using the __format__ method. Mostly we just use the defaults that come with the basic types, but much like __str__ and __repr__ we can customize. The stuff after the colon : is the parameter to __format__.
>>> class Foo:
... def __format__(self, spec):
... print(repr(spec))
... return "I will stubbornly refuse your format"
...
>>> f = Foo()
>>> print("Its now {:myformat}".format(f))
'myformat'
Its now I will stubbornly refuse your format
we can call the formatter ourselves. datetime uses the strftime format rules.
>>> import datetime
>>> # datetime formatting
>>> date = datetime.datetime.now()
>>> print("It's now: {:%Y/%m/%d %H:%M:%S}".format(date))
It's now: 2021/10/04 11:12:23
>>> date.__format__(":%Y/%m/%d %H:%M:%S")
':2021/10/04 11:12:23'
Your custom Person class implemented __format__ and used the format specifier after the colon to return a value.
Try f-strings. In them the colon seems to be more reasonable. It delimits the variable name and its formatting options:
import datetime
# datetime formatting
date = datetime.datetime.now()
print(f"It's now: {date:%Y/%m/%d %H:%M:%S}")
# custom __format__() method
class Person:
def __format__(self, format):
if(format == 'age'):
return '23'
return 'None'
print(f"Adam's age is: {Person():age}")
Btw you can have similar functionality with keyword arguments to format():
print("It's now: {d:%Y/%m/%d %H:%M:%S}".format(d=date))
print("Adam's age is: {adam:age}".format(adam=Person()))

Python string format: When to use !s conversion flag

What's the difference between these 2 string format statements in Python:
'{0}'.format(a)
'{0!s}'.format(a)
Both have the same output if a is an integer, list or dictionary. Is the first one {0} doing an implicit str() call?
Source
PS: keywords: exclamation / bang "!s" formatting
It is mentioned in the documentation:
The conversion field causes a type coercion before formatting.
Normally, the job of formatting a value is done by the __format__()
method of the value itself. However, in some cases it is desirable to
force a type to be formatted as a string, overriding its own
definition of formatting. By converting the value to a string before
calling __format__(), the normal formatting logic is bypassed.
Two conversion flags are currently supported: '!s' which calls
str() on the value, and '!r' which calls repr().
An example can be taken (again from the documentation) to show the difference:
>>> "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
"repr() shows quotes: 'test1'; str() doesn't: test2"
Simply said:
'{0}'.format(a) will use the result of a.__format__() to display the value
'{0!s}'.format(a) will use the result of a.__str__() to display the value
'{0!r}'.format(a) will use the result of a.__repr__() to display the value
>>> class C:
... def __str__(self): return "str"
... def __repr__(self): return "repr"
... def __format__(self, format_spec): return "format as " + str(type(format_spec))
...
>>> c = C()
>>> print "{0}".format(c)
format as <type 'str'>
>>> print u"{0}".format(c)
format as <type 'unicode'>
>>> print "{0!s}".format(c)
str
>>> print "{0!r}".format(c)
repr
Concerning the second argument of __format__, to quote PEP 3101 "Controlling Formatting on a Per-Type Basis":
The 'format_spec' argument will be either
a string object or a unicode object, depending on the type of the
original format string. The __format__ method should test the type
of the specifiers parameter to determine whether to return a string or
unicode object. It is the responsibility of the __format__ method
to return an object of the proper type.
Thanks to the comment & answer from #hjpotter92 for explanation:
Here's an example that shows the difference (it's when you override the __format__ method)
class MyClass:
i = 12345
def __format__(self, i):
return 'I Override'
>>> obj = MyClass()
>>> '{0}'.format(obj)
'I Override'
>>> '{0!s}'.format(obj)
'<__main__.MyClass instance at 0x021AA6C0>'

Convert list to comma-delimited string

The following is the list that I have:
>>> issue_search
[<JIRA Issue: key=u'NEC-1519', id=u'991356'>, <JIRA Issue: key=u'NEC-1516', id=u'991344'>, <JIRA Issue: key=u'NEC-1518', id=u'990463'>]
>>>
I was using the following:
issue_string = ','.join(map(str, issue_search))
But the output is:
NEC-1519, NEC-1516, NEC-1518
I am confused on the output. How is only the key getting displayed? How to get the other text too in the string format?
What you see in the list is the values returned by each object's __repr__ method. If you want these values, map the list to repr instead of str:
issue_string = ','.join(map(repr, issue_search))
Below is a demonstration with decimal.Decimal:
>>> from decimal import Decimal
>>> lst = [Decimal('1.2'), Decimal('3.4'), Decimal('5.6')]
>>> lst
[Decimal('1.2'), Decimal('3.4'), Decimal('5.6')]
>>> print ','.join(map(str, lst))
1.2,3.4,5.6
>>> print ','.join(map(repr, lst))
Decimal('1.2'),Decimal('3.4'),Decimal('5.6')
>>>
You are calling str on the objects within issue_search before joining them. So obviously, the call of str on a “JIRA Issue” will only result in the key.
The return value of str is determined by an object’s __str__ method which is likely defined in the described way for the “JIRA Issue” type. If you cannot change the method, you could also call repr on the objects instead, or specify a custom format function:
>>> ', '.join(map(lambda x: '{} ({})'.format(x.key, x.id), issue_search))
'NEC-1519 (991356), NEC-1516 (991344), NEC-1518 (990463)'

Categories

Resources