Uploaded on:
str.format() - or-How "%s, %s" % ("Hello", "world") got to be "{}, {}".format("Hello", "world") Eric V. Smith Genuine Cutting edge Frameworks, Inc. Diagram: What and Why? Basic Use Design Detail for Fundamental Sorts Organizing for Your Own particular Sorts
Slide 1

str.format() - or-How "%s, %s" % ("Hello", "world") got to be "{}, {}".format("Hello", "world") Eric V. Smith True Blade Systems, Inc.

Slide 2

Overview: What and Why? Straightforward Usage Format Specification for Basic Types Formatting for Your Own Types Defining Your Own Templating Language Tips and Tricks

Slide 3

Getting our feet wet "My {0} is {1}".format("name", "Eric") - > "My name is Eric" "{1} is my {0}".format("name", "Eric") - > "Eric is my name" "My {attr} is {value}".format(attr="name", value="Eric") - > "My name is Eric" "My {attr} is {0}".format("Eric", attr="name") - > "My name is Eric"

Slide 4

What str.format() brings New string strategy: str.format (and in 2.x, unicode , as well). New system on all items (articles design themselves!): __format__(self, fmt) . New inherent: format(obj, fmt=None) . New class: string.Formatter .

Slide 5

str.format() Described in PEP 3101. An approach to arrangement strings, like and notwithstanding %-organizing and string.Template. Utilizes {} installed as a part of strings to grow variables. Initially showed up in CPython 2.6 and 3.0. Bolstered by Jython and IronPython. Minor (however critical!) upgrades made in 2.7 and 3.1.

Slide 6

Isn’t %-designing sufficient? The essential issue is that it’s a paired administrator and hard to improve or augment. Not at all like most different things in Python, it’s not a “normal” capacity with parameters. It’s not usable with client characterized sorts. It has zero extensibility snares. It has the wrong priority. Specifically it ties more firmly than + : "this is %s" + "a %s" % ("not", "test")

Slide 7

My most concerning issue Problem with various component tuples. print("result: %s" % result) What happens when result is (0, 1) ?

Slide 8

Ouch . Traceback (latest call last): File "<stdin>", line 1, in ? TypeError: not all contentions changed over amid string designing

Slide 9

Solution To secure yourself against obscure parameters, you should dependably say: print("result: %s" % (result,)) what number of us generally do that?

Slide 10

More issues with %-designing You can utilize either named contentions or positional contentions, yet not a blend. You must utilize named contentions for l10n in light of the fact that that’s the best way to swap the request of parameters. Linguistic structure for named contentions is inconvenient: "result: %(value)10.10s" % mydict Can’t blend named contentions with ‘ * ’.

Slide 11

What about string.Template? Depicted in PEP 292. Utilizes $ (with discretionary props) for development variables. Not by any stretch of the imagination in the same issue space.

Slide 12

More samples "pi={0:.5}".format(math.pi) - > "pi=3.1416" "pi={0:.5} or {0:.2}".format(math.pi) - > \'pi=3.1416 or 3.1\' "pi={0.pi} e={0.e}".format(math) - > \'pi=3.14159265359 e=2.71828182846\'

Slide 13

__getitem__ access "{0[0]}.{0[1]}".format(sys.version_info) - > "3.1" "The {0[thing]}\'s expected in {0[when]} days".format({\'when\':3, \'thing\': \'homework\'}) - > \'The homework\'s expected in 3 days\' "{0[0]}.{0.minor}".format(sys.version_info) - > "2.7"

Slide 14

Yet more illustrations "pi={0.pi:.{n}}".format(math, n=7) - > "pi=3.141593" "i={0:d} {0:X} {0:#b}".format(300) - > \'i=300 12C 0b100101100\' "{0:*^20}".format("Python") - > "*******Python*******"

Slide 15

Still more cases "{0:%Y-%m-%d}".format( - > \'2010-02-17\' "My {0} is {2}".format("last name", "Eric", "Smith") - > \'My last name is Smith\'

Slide 16

I guarantee, the last case It’s simple to make an organizing capacity. f = "{0} is {1:.12f}".format f(\'pi\', math.pi) - > \'pi is 3.141592653590\'

Slide 17

Type changes They begin with “ ! ” and must precede the configuration specifier (if any). Legitimate changes are: !s : believer to string utilizing str() . !r : believer to string utilizing repr() . !a : proselyte to ascii utilizing ascii() 3.x just.

Slide 18

Type changes "{0!r}".format(now) - > \', 2, 17)\' "{0!s}".format(now) - > \'2010-02-17\' "{0:%Y} {0!s} {0!r}".format(now) - > \'2010-02-17, 2, 17)\' "{0!s:#>20}".format(now) - > \'##########2010-02-17\'

Slide 19

Improvements in 2.7 and 3.1 Comma designing for numeric sorts: format(1234567, \',\') - > "1,234,567" If you need numbered, all together substitution values, you can overlook the numbers. This is an immense ease of use change! \'I have {:#x} {}\'.format(16, \'puppies\') - > \'I have 0x10 pooches\' unpredictable is better bolstered.

Slide 20

str.format() versus position versus obj.__format__() configuration() assembled in and obj.__format__() are the building squares. str.format() parses strings, isolates out the {} parts, does any lookups or transformations, and calls group() with the ascertained item and the supplied configuration string. It then sews the outcome back together into its arrival parameter. This is like %-arranging.

Slide 21

object.__format__ The default execution is (essentially): def __format__(self, fmt): return format(str(self), fmt) DO NOT RELY ON THIS BEHAVIOR! 2.6: format(1+1j,\'*^8s\') - > "*(1+1j)*" 2.7: format(1+1j,\'*^8s\') - > ValueError: Unknown arrangement code "s" for object of sort "complex"

Slide 22

What to do? On the off chance that you truly need this conduct, believer to a string first. format(str(1+1j), \'*^8s\') gives back the same thing in 2.6, 2.7, 3.1, 3.2. This is identical to: \'{0!s:*^8}\'.format(1+1j)

Slide 23

Types executing __format__ object str (and unicode in 2.x) int (and long in 2.x) coast complex decimal.Decimal , .datetime , .time

Slide 24

str & unicode Very like %-organizing. [[fill]align][minimumwidth][.precision][type] Addition of ‘ ^ ’ for focus arrangement.

Slide 25

Numeric sorts Again, like %-arranging. [[fill]align][sign][#][0][minimumwidth][.precision][type] New components: ‘ ^ ’, ‘ % ’, ‘ b ’, ‘ n ’, ‘’ (vacant)

Slide 26

Formatting your own sorts Just actualize __format__(self, spec) . Parse the spec anyway you need. It’s your own particular sort particular dialect. On the other hand, do what Decimal does and treat spec like the inherent buoy detail dialect. You’ll naturally be useable through the systems I’ve appeared: str.format() and position() .

Slide 27

str.format() shortcomings Slower than %-arranging. A few individuals hate the grammar. In 2.6 and 3.0, you should dependably expressly distinguish all substitution variables (by name or number).

Slide 28

str.format() qualities Types that can be organized are not constrained to a couple constructed in ones. Sorts can organize themselves. The designing dialect can by sort particular. In 2.7 and 3.2, numbers can undoubtedly have commas.

Slide 29

Your own particular layout dialect string.Formatter : minimal known, however intense. It’s sensibly quick. The essential parts are actualized in C (for CPython). Along these lines, say we need to utilize vertical bars “ | ” rather than wavy props. Let’s compose a custom class.

Slide 30

How string.Template works out of the case >>> fmtr = string.Formatter() >>> fmtr.format(\'- {0:^10}-\', \'abc\') \'- abc - " >>> fmt = string.Formatter().format >>> fmt(\'- {0:^10}-\', \'abc\') \'- abc - "

Slide 31

Custom layout class BarFormatter(string.Formatter): def parse(self, format): for s, fld in grouper(2, template.split(\'|\')): if fld: name, _, spec = \ fld.partition(\':\') yield s, name, spec, None else: yield s, None, None, None

Slide 32

Using our custom format dialect >>> fmt = BarFormatter().format >>> fmt(\'- |0:^10s|-\', \'abc\') \'- abc - " >>> f = lambda k, v: \ fmt(\'|0:s| is |1:.13f|\', k, v) >>> f(\'e\', math.e) \'e is 2.7182818284590\'

Slide 33

Tips and Tricks Migrating a library from %-designing to str.format() . Postponing instantiation of parameters.

Slide 34

Migrating from %-organizing to str.format() Problem: You have a library that uncovered a %-designing interface, you need to relocate to a more expressive str.format() interface. Arrangement: You bolster both for a couple discharges, then in the end just backing str.format() .

Slide 35

Existing Library class Logger: def __init__(self): self.fmt = "%(msg)s" def log(self, msg): args = {\'now\':, \'msg\': msg} s = self.fmt % args print(s)

Slide 36

Interim Solution class Logger: def __init__(self): self.fmt = "{msg!s}" def log(self, msg): args = {\'now\':, \'msg\': msg} s = expand_str_mapping( self.fmt, args) # s = self.fmt.format(args) print(s)

Slide 37

expand_str_mapping Some measure of speculating included in view of the configuration string, yet truly just for obsessive cases. In the event that the arrangement string has a ‘ %( ’ however not a ‘ { ‘, use %-designing. On the off chance that it has a ‘ { ‘ however no ‘ %( ’, use str.format() . Also, if has not one or the other, no development required (or, it doesn’t matter which you utilize).

Slide 38

The crucial step What if a configuration string has both ‘ { ‘ and ‘ %( ’? We’ll need to parse the string, however even

View more...