how % applies to this method in Python? - python

From my studying of python, I've found two uses for %. It can be used as what's called a modulo, meaning it will divide the value to the left of it and the value to the right of it and spit back the remainder.
The other use is a string formatter. So I can do something like 'Hi there %s' % name, where name is a list of names.
Also, if you see %% in a string formatting, that means a literal % will be entered.
Here is my question, I found this:
class FormatFormatStr(FormatObj):
def __init__(self, fmt):
self.fmt = fmt
def tostr(self, x):
if x is None: return 'None'
return self.fmt%self.toval(x)
What does return self.fmt%self.toval(x) mean? It can't be a modulo because toval will give me a string. It's not really a string formatter because there isn't another percent sign.
also, related to this:
def csvformat_factory(format):
format = copy.deepcopy(format)
if isinstance(format, FormatFloat):
format.scale = 1. # override scaling for storage
format.fmt = '%r'
return format
What does the percent mean in format.fmt = '%r' does this mean to insert a string a la repr()? Or does it mean insert what the variable r represents? r in this overall program also refers to a recarray.
Thanks everyone. Hope this makes sense =)

The string % operator is simpler than you are imagining. It takes a string on the left side, and a variety of things on the right side. The left side doesn't have to be a literal string, it can be a variable, or the result of another computation. Any expression that results in a string is valid for the left side of the %.
In your first example, self.fmt is a string. In order to be useful in this context, it should have a percent sign in it.
In your second example, format.fmt is being set to a string that would be useful as the left side of the %. In this case, "%r" means, insert the repr() of the value into the string, as you have said.

In
return self.fmt%self.toval(x)
self.fmt is a string, and that string presumably has a percent-sign placeholder in it.
%r in a format string is like %s but it prints the repr() of the string, so it'll have quotes and backslashes and all that.
% is just an operator which is just a method, and like any other method you can either pass in a literal value or a variable containing a value. In your examples they use a variable containing the format string.

def tostr(self, x):
if x is None: return 'None'
return self.fmt%self.toval(x)
The % in this is a string formatter, definitely. Pass the tostr method a formatter, eg "%s" or "%r" to see what happens
I think the '%r' in csvformat_factory is also a string formatter. '%r' means take the repr() which is a reasonable way to display something to a user. I imagine that format.fmt is used elsewhere format.fmt % somevalue.

The code:
return self.fmt % self.toval(x)
Is the "string formatting" use of the % operator, just like you suspected.
The class is handed format, which is a string containing the formatting, and when tostr(x) is called, it will return the string % x.
This is just like using % directly, only with saving the format string for later. In other words, instead of doing:
"I want to print the number: %n" % 20
What's happening is:
format_str = "I want to print the number: %n"
x = 20
print format_str % x
Which is exactly the same thing.

% has more than one use in string formatting. One use is in %s, %d, etc.
Another use is to separate 'string in which we use %d and %s' from int-value and string-value.
For example
'string in which we use %d and %s' % (17, 'blue')
would result in
'string in which we use 17 and blue'
we could store 'string in which we use %d and %s' in a variable,
a = 'string in which we use %d and %s'
then
a % (17, 'blue')
results in
'string in which we use 17 and blue'
In your example
self.fmt%self.toval(x)
self.fmt is similar to a above and self.toval(x) is (17, 'blue')

Related

parsing integers in python into a command for another software

I want to write
vol_id = geom.get_owning_volume("surface", 12)
and I have S=12 on the fly during large code execution so I use
S=12
vol_id = geom.get_owning_volume("surface", "%d") %(S)
which gives me an error
TypeError: in method 'get_owning_volume', argument 2 of type 'int'
I have used the variation
S=12
vol_id = geom.get_owning_volume("surface", "%d" %(S))
this gives the same error
why I cannot parse the integer 12 to the desired place! any suggestions?
The % operator is for interpolating into strings, not into Python code. Your example is trying to pass the string "%d" where the function expects a number; no wonder it fails!
In your case, just put the variable S where you need it:
S=12
vol_id = geom.get_owning_volume("surface", S)
From the documentation that I found, get_owning_volume takes a string and an integer, and you already have an integer, so there's no need to convert it:
vol_id = geom.get_owning_volume("surface", S)
From the comments it looks like S is actually a string, and you want an integer, then this should work:
vol_id = geom.get_owning_volume("surface", int(S))

Python - convert to string with formatter as parameter

I am trying to write a function which takes two arguments:
an object
a formatter string (as specified in docs)
which then returns a formatted string:
What I tried is sort of:
def my_formatter(x, form):
return str(x).format(form)
What I am expecting is:
s = my_formatter(5, "%2f")
# s = 05
t = my_formatter(5, "%.2")
# t = 5.00
etc...
The format function unfortunately does not work like that. Any ideas?
For that style of formatting you'd have to use the string % values string formatting operation:
def my_formatter(x, form):
return form % x
You'd also have to alter your format; to get 05 you'd have to use "%02d", not "%2f".
You were getting confused by the str.format() method, which uses a different formatting syntax, and you got the arguments swapped; you'd use form.format(x) instead.
You probably want to look into the built-in format() function here; the syntax is slightly different, but offers more features:
>>> format(5, '02d')
'05'
>>> format(5, '.2f')
'5.00'
That's pretty close to what you were already using, minus the %.

variable number of digit in format string

Which is a clean way to write this formatting function:
def percent(value,digits=0):
return ('{0:.%d%%}' % digits).format(value)
>>> percent(0.1565)
'16%'
>>> percent(0.1565,2)
'15.65%'
the problem is formatting a number with a given number of digits, I don't like to use both '%' operator and format method.
I like this one:
'{0:.{1}%}'.format(value, digits)
Test:
>> '{0:.{1}%}'.format(0.1565, 0)
'16%'
>> '{0:.{1}%}'.format(0.1565, 2)
'15.65%'
* does what you want, for printf-style string formatting.
>>> def percent(value, digits=0):
... return '%.*f%%' % (digits, value * 100)
...
>>> percent(0.1565, 2)
'15.65%'
Advanced string formatting (defined in PEP 3101 and documented in 7.1.3. Format String Syntax) doesn't seem to be capable of doing this in one pass. (See 7.1.3.1. Format Specification Mini-Language: precision is integer only.)
From the docs:
Minimum field width (optional). If specified as an '*' (asterisk), the
actual width is read from the next element of the tuple in values, and
the object to convert comes after the minimum field width and optional
precision.
Example:
def percent(value, digits=0):
print '%.*f%%' % (digits, value*100)
>>> percent(0.1565, 2)
15.65%

String formatting with “{0:d}” doesn't convert to integer

This is about the same issue as in this question about floats.
When you've got a value that could get converted to an integer, the old %d would convert it, but format doesn't.
class MyIntegerTenClass:
def __int__(self):
return 10
def __str__(self):
return 'ten'
ten = MyIntegerTenClass()
print '%d, %02X, %s' % (ten, ten, ten) # ok
print '{0}'.format(ten) # ok
print '{0:d}, {0:02X}'.format(ten) # ValueError: Unknown format code 'd' for object of type 'str'
Is there a way to modify the behaviour of format, without touching the class of the value to be formatted (without adding a __format__ method to that class)?
Edit: My goal is to get the formatting dependent on the format string, but not on the value.
So if the format string says "d" or "x", convert the value to int and then to decimal or hexadecimal representation.
If the format string says "s", convert it to string directly. As the old % did.
Actually, I could even add a __format__ method to the class of the value. But how do I check, in that method, if the given format specification is an integer format specification? Without reimplementing the format specification parser of the builtin format.
Edit: Here's a solution with __format__ and exceptions. Any better ideas?
class MyIntegerTenClass:
def __int__(self):
return 10
def __str__(self):
return 'ten'
def __format__(self, spec):
fmt = '{0:%s}'%spec
try:
return fmt.format(str(self))
except:
return fmt.format(int(self))
ten = MyIntegerTenClass()
print '%d, %02X, %s' % (ten, ten, ten) # ok, prints "10, 0A, ten"
print '{0:d}, {0:02X}, {0}'.format(ten) # ok, prints "10, 0A, ten"
A first approach to this problem might be simply to try it:
class MyIntegerTenClass:
def __int__(self):
return 10
def __str__(self):
return 'ten'
def __format__(self, format_spec):
try:
s = format(str(self), format_spec)
except ValueError:
s = format(int(self), format_spec)
return s
If MyIntegerTenClass can be inserted into the format string as a string, it will be. If not, it will be converted into an int and resubmitted to format.
>>> print '{0}, {0:s}, {0:d}, {0:02X}, {0:f}'.format(ten)
ten, ten, 10, 0A, 10.000000
If you want the default representation to be 10 instead of ten, you need only swap the conversion lines:
def __format__(self, format_spec):
try:
s = format(int(self), format_spec)
except ValueError:
s = format(str(self), format_spec)
return s
Test output:
>>> print '{0}, {0:s}, {0:d}, {0:02X}, {0:f}'.format(ten)
10, ten, 10, 0A, 10.000000
As an addendum, I don't believe you'll be able to get the behavior you want without defining __format__; however, you can develop a more sophisticated approach using a Formatter object. Still, I think the exception-based approach gives you a lot of built-in functionality for free.
pass an integer instead of a string and it'll work fine.
>>> print '{0:d}'.format(1)
1
>>> print '{0:d}'.format('1')
Traceback (most recent call last):
File "<pyshell#57>", line 1, in <module>
print '{0:d}'.format('1')
ValueError: Unknown format code 'd' for object of type 'str'
It says ten is a string, you are trying to format it as a number.
Try wrapping it in a cast:
>>> print '{0:d}, {0:02X}'.format(int(ten))
10, 0A

When to use %r instead of %s in Python? [duplicate]

This question already has answers here:
What is the meaning of %r?
(9 answers)
Closed 8 years ago.
On Learn Python the Hard Way page 21, I see this code example:
x = "There are %d types of people." % 10
...
print "I said: %r." % x
Why is %r used here instead of %s? When would you use %r, and when would you use %s?
The %s specifier converts the object using str(), and %r converts it using repr().
For some objects such as integers, they yield the same result, but repr() is special in that (for types where this is possible) it conventionally returns a result that is valid Python syntax, which could be used to unambiguously recreate the object it represents.
Here's an example, using a date:
>>> import datetime
>>> d = datetime.date.today()
>>> str(d)
'2011-05-14'
>>> repr(d)
'datetime.date(2011, 5, 14)'
Types for which repr() doesn't produce Python syntax include those that point to external resources such as a file, which you can't guarantee to recreate in a different context.
Use the %r for debugging, since it displays the "raw" data of the variable,
but the others are used for displaying to users.
That's how %r formatting works; it prints it the way you wrote it (or close to it). It's the "raw" format for debugging. Here \n used to display to users doesn't work. %r shows the representation if the raw data of the variable.
months = "\nJan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug"
print "Here are the months: %r" % months
Output:
Here are the months: '\nJan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug'
Check this example from Learn Python the Hard Way.
%r shows with quotes:
It will be like:
I said: 'There are 10 types of people.'.
If you had used %s it would have been:
I said: There are 10 types of people..
This is a version of Ben James's answer, above:
>>> import datetime
>>> x = datetime.date.today()
>>> print x
2013-01-11
>>>
>>>
>>> print "Today's date is %s ..." % x
Today's date is 2013-01-11 ...
>>>
>>> print "Today's date is %r ..." % x
Today's date is datetime.date(2013, 1, 11) ...
>>>
When I ran this, it helped me see the usefulness of %r.

Categories

Resources