An excellent new code pattern: reprs compatible with g.printObj

88 views
Skip to first unread message

Edward K. Ream

unread,
Sep 4, 2019, 5:43:18 AM9/4/19
to leo-editor
tl;dr: A beautiful pattern exposes the "innards" of any class to g.printObj, Leo's best way of showing data.

Here is the new __repr__ for the g.GeneralSetting class:

def __repr__(self):
   
# Better for g.printObj.
    val
= str(self.val).replace('\n', ' ')
   
return 'GS: %20s %7s = %s' % (
        g
.shortFileName(self.path), self.kind, g.truncate(val, 50))

This puts the crucial data on a single line.  This is exactly what I'll need when working in the settings branch.

Here is the __repr__ for both the g.TypedDict and g.TypedDictOfLists classes:

def __repr__(self):
   
"""Suitable for g.printObj"""
   
return '%s\n%s\n' % (g.dictToString(self.d), str(self))

g.dictToString is one of g.printObj's helpers.  It aligns all the dictionary keys.  Crucially, g.printObj need not know about the "inner" dict, self.d.  g.printObj "just works".

The __str__ method of the two g.TypedDict classes is a summary.  For example, for g.TypedDict:

def __str__(self):
   
"""Concise: used by repr."""
   
return '<TypedDict name:%s keys:%s values:%s len(keys): %s>' % (
       
self._name,
       
self.keyType.__name__,
       
self.valType.__name__,
        len
(list(self.keys())))

Summary

This pattern leverages all the good work I have done with g.printObj.  When a class's __repr__ method returns g.objToString (or one of it's helpers), __repr__ will do a better job than a hand-written dump method.

I'm glad I didn't discover this pattern until well into the work on #1316. Had I done so, I probably would not have done the work I did on cleaning g.TypedDict and g.TypedDictOfLists, to be described in another post.

Edward

rengel

unread,
Sep 4, 2019, 10:54:46 AM9/4/19
to leo-e...@googlegroups.com
Why not go for f-strings (Python 3.6+)? See for instance:


The code:

def __repr__(self):
    # Better for g.printObj.
    val = str(self.val).replace('\n', ' ')
    return 'GS: %20s %7s = %s' % (
        g.shortFileName(self.path), self.kind, g.truncate(val, 50))

would look as follows:

def __repr__(self):
    # Better for g.printObj.
    val = (str(self.val).replace('\n', ' '))[:50] # Save call to g.truncate
    return f'GS: {g.shortFileName(self.path):20} {self.kind:7} = {val}'

Less typing, smaller, faster, cleaner.

gar

unread,
Sep 4, 2019, 10:59:54 AM9/4/19
to leo-e...@googlegroups.com
By the way, leo-5.9 could not save py nodes where f-str syntax was used.
Does it work on 6.x?

2019-09-04 17:54 GMT+03:00, rengel <reinhard...@gmail.com>:
> Why not go for f-strings (Python 3.6+). See for instance:
>
> http://zetcode.com/python/fstring/
>
> The code:
>
> def __repr__(self):
> # Better for g.printObj.
> val = str(self.val).replace('\n', ' ')
> return 'GS: %20s %7s = %s' % (
> g.shortFileName(self.path), self.kind, g.truncate(val, 50))
>
> would look as follows:
>
> def __repr__(self):
> # Better for g.printObj.
> val = (str(self.val).replace('\n', ' '))[0:50] # Save call to
> g.truncate
> return f'GS: {g.shortFileName(self.path):20} {self.kind:7} = {val}'
>
> Less typing, Smaller, faster, cleaner.
>
> --
> You received this message because you are subscribed to the Google Groups
> "leo-editor" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to leo-editor+...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/leo-editor/75137e8f-3f5d-4dab-a2b6-e03862d68047%40googlegroups.com.
>

Edward K. Ream

unread,
Sep 4, 2019, 12:53:02 PM9/4/19
to leo-editor
On Wed, Sep 4, 2019 at 9:54 AM rengel <reinhard...@gmail.com> wrote:

Why not go for f-strings (Python 3.6+)...

The code:

def __repr__(self):
    # Better for g.printObj.
    val = str(self.val).replace('\n', ' ')
    return 'GS: %20s %7s = %s' % (
        g.shortFileName(self.path), self.kind, g.truncate(val, 50))

would look as follows:

def __repr__(self):
    # Better for g.printObj.
    val = (str(self.val).replace('\n', ' '))[0:50] # Save call to g.truncate
    return f'GS: {g.shortFileName(self.path):20} {self.kind:7} = {val}'

Less typing, Smaller, faster, cleaner.

Actually, you will notice that the legacy way is slightly shorter :-)  It's a matter of preference, and I'm pretty stuck in my ways.

g.truncate(x, n) is not equivalent x[0:n].  Take a look.

Edward

Edward K. Ream

unread,
Sep 4, 2019, 12:55:06 PM9/4/19
to leo-editor
On Wed, Sep 4, 2019 at 9:59 AM gar <gar...@gmail.com> wrote:

By the way, leo-5.9 could not save py nodes where f-str syntax was used.
Does it work on 6.x?

Leo 6.0 requires Python 3.6 (iirc) or above.  Leo 5.9 is compatible with Python 2.7 (iirc) and above.  The great thing about moving to Python 3 is that these kind of questions disappear.

Edward

Edward K. Ream

unread,
Sep 5, 2019, 4:03:23 AM9/5/19
to leo-editor
On Wednesday, September 4, 2019 at 4:43:18 AM UTC-5, Edward K. Ream wrote:

tl;dr: A beautiful pattern exposes the "innards" of any class to g.printObj, Leo's best way of showing data.

To see this pattern in action,  execute g.printObj(c.config.settingsDict) from the body text of any node.

Edward

Edward K. Ream

unread,
Sep 5, 2019, 4:28:17 AM9/5/19
to leo-editor
On Wed, Sep 4, 2019 at 9:54 AM rengel <reinhard...@gmail.com> wrote:

Why not go for f-strings (Python 3.6+)...Less typing, Smaller, faster, cleaner.

Supposed disadvantages of %

The python 3 docs say this about printf style (%) formatting:

"The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). If the value being printed may be a tuple or dictionary, wrap it in a tuple."

I have never run across these difficulties. Note that pylint checks that the number of % specs matches the number of args.

Real advantages of f-strings

- They do more clearly group arguments with specifiers.

- no more typing %.

- f-strings can be concatenated as usual, so line length doesn't matter much. Your example could be given as:

return (
    f
'GS: {g.shortFileName(self.path):20} '
    f
'{self.kind:7} = {val}'
)

Notice space at the end of the first f-string.

Summary

f-strings do have advantages, and there are tools to reformat % strings to f-string.

However, I don't see any urgent reason to back port Leo's existing code.

Edward

jkn

unread,
Sep 5, 2019, 5:31:05 AM9/5/19
to leo-editor


On Thursday, September 5, 2019 at 9:28:17 AM UTC+1, Edward K. Ream wrote:
IIUC, f-string formatting is *significantly* slower than old-style percentage usage.

It might not be terribly important for Leo; personally I too have not rushed to change in my own code...

Edward K. Ream

unread,
Sep 6, 2019, 5:39:53 AM9/6/19
to leo-editor
On Thu, Sep 5, 2019 at 4:31 AM jkn <jkn...@nicorp.f9.co.uk> wrote:

> IIUC, f-string formatting is *significantly* slower than old-style percentage usage.

Hmm. Somebody else says its faster.  I would think it would be slower, because it has to eval the arg.

> personally I too have not rushed to change in my own code...

I agree. f-strings add nothing new.

Edward

rengel

unread,
Sep 6, 2019, 6:10:01 AM9/6/19
to leo-editor
Faster or not faster? As programmers we don't need to speculate, do we? We can benchmark...

Reinhard

rengel

unread,
Sep 6, 2019, 6:25:39 AM9/6/19
to leo-editor
BTW:
 
It's a matter of preference, and I'm pretty stuck in my ways.

'Matter of prefence', ok, but the second part isn't even an excuse - given the pace you embrace one new technology after another... ;-)
I'm a little older than you and made the switch a year ago - easy, and quite a relief.

Reinhard

Edward K. Ream

unread,
Sep 6, 2019, 6:56:47 AM9/6/19
to leo-editor
On Fri, Sep 6, 2019 at 5:10 AM rengel <reinhard...@gmail.com> wrote:
Faster or not faster? As programmers we don't need to speculate, do we? We can benchmark...

Thanks for this.  Good to know.

Edward

Edward K. Ream

unread,
Sep 6, 2019, 6:58:29 AM9/6/19
to leo-editor
On Fri, Sep 6, 2019 at 5:25 AM rengel <reinhard...@gmail.com> wrote:
BTW:
 
It's a matter of preference, and I'm pretty stuck in my ways.

'Matter of prefernce', ok, but the second part isn't even an excuse

With your nudges, I'll use f-strings in new code.

Edward

jkn

unread,
Sep 6, 2019, 7:22:32 AM9/6/19
to leo-editor
I wasn't speculating, I was recalling ... someone who had benchmarked and found it much slower.

It looks like a new opcode has been added in 3.6 or so to improve matters (a lot, perhaps) - hurrah!

    Jon N

rengel

unread,
Sep 6, 2019, 8:50:10 AM9/6/19
to leo-editor
On Friday, September 6, 2019 at 12:58:29 PM UTC+2, Edward K. Ream wrote:


On Fri, Sep 6, 2019 at 5:25 AM rengel <reinhar...@gmail.com> wrote:
BTW:
 
It's a matter of preference, and I'm pretty stuck in my ways.

'Matter of prefernce', ok, but the second part isn't even an excuse

With your nudges, I'll use f-strings in new code.


Never met somebody before, who is so open to suggestions..., love it!

Edward

Edward K. Ream

unread,
Sep 6, 2019, 10:10:53 AM9/6/19
to leo-editor


On Friday, September 6, 2019 at 7:50:10 AM UTC-5, rengel wrote:

Never met somebody before, who is so open to suggestions..., love it!

I already strongly prefer f-strings :-)

Edward
Reply all
Reply to author
Forward
0 new messages