Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #92644 > unrolled thread

Set a flag on the function or a global?

Started bySteven D'Aprano <steve+comp.lang.python@pearwood.info>
First post2015-06-15 23:57 +0000
Last post2015-06-16 07:57 -0700
Articles 20 on this page of 37 — 18 participants

Back to article view | Back to comp.lang.python


Contents

  Set a flag on the function or a global? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-06-15 23:57 +0000
    Re: Set a flag on the function or a global? Chris Angelico <rosuav@gmail.com> - 2015-06-16 10:07 +1000
    Re: Set a flag on the function or a global? Ethan Furman <ethan@stoneleaf.us> - 2015-06-15 17:19 -0700
    Re: Set a flag on the function or a global? Ben Finney <ben+python@benfinney.id.au> - 2015-06-16 10:20 +1000
      Re: Set a flag on the function or a global? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-06-16 19:07 +1000
    Re: Set a flag on the function or a global? Ethan Furman <ethan@stoneleaf.us> - 2015-06-15 17:21 -0700
    Re: Set a flag on the function or a global? sohcahtoa82@gmail.com - 2015-06-15 17:24 -0700
      Re: Set a flag on the function or a global? MRAB <python@mrabarnett.plus.com> - 2015-06-16 01:35 +0100
        Re: Set a flag on the function or a global? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-06-16 18:18 +1000
          Re: Set a flag on the function or a global? Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2015-06-16 13:45 +0100
            Re: Set a flag on the function or a global? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-06-16 22:46 +0000
          Re: Set a flag on the function or a global? Cameron Simpson <cs@zip.com.au> - 2015-06-17 09:51 +1000
            Re: Set a flag on the function or a global? Steven D'Aprano <steve@pearwood.info> - 2015-06-18 00:59 +1000
              Re: Set a flag on the function or a global? Laura Creighton <lac@openend.se> - 2015-06-17 17:06 +0200
                Re: Set a flag on the function or a global? Steven D'Aprano <steve@pearwood.info> - 2015-06-18 01:55 +1000
                  Documenting a function signature (was: Set a flag on the function or a global?) Ben Finney <ben+python@benfinney.id.au> - 2015-06-18 10:04 +1000
                  Re: Documenting a function signature (was: Set a flag on the function or a global?) Ian Kelly <ian.g.kelly@gmail.com> - 2015-06-17 18:10 -0600
                  Re: Documenting a function signature (was: Set a flag on the function or a global?) Chris Angelico <rosuav@gmail.com> - 2015-06-18 10:14 +1000
                  Re: Documenting a function signature (was: Set a flag on the function or a global?) random832@fastmail.us - 2015-06-18 08:37 -0400
                  Re: Documenting a function signature (was: Set a flag on the function or a global?) Laura Creighton <lac@openend.se> - 2015-06-18 23:38 +0200
                  Re: Documenting a function signature Ben Finney <ben+python@benfinney.id.au> - 2015-06-19 10:41 +1000
    Re: Set a flag on the function or a global? Ron Adam <ron3200@gmail.com> - 2015-06-15 20:24 -0400
      Re: Set a flag on the function or a global? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-06-16 19:15 +1000
        Re: Set a flag on the function or a global? Ron Adam <ron3200@gmail.com> - 2015-06-16 07:02 -0400
    Re: Set a flag on the function or a global? Chris Angelico <rosuav@gmail.com> - 2015-06-16 10:32 +1000
    Re: Set a flag on the function or a global? Paul Rubin <no.email@nospam.invalid> - 2015-06-15 17:37 -0700
      Re: Set a flag on the function or a global? Ethan Furman <ethan@stoneleaf.us> - 2015-06-15 17:53 -0700
        Re: Set a flag on the function or a global? Paul Rubin <no.email@nospam.invalid> - 2015-06-15 19:04 -0700
      Re: Set a flag on the function or a global? MRAB <python@mrabarnett.plus.com> - 2015-06-16 02:15 +0100
      Re: Set a flag on the function or a global? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-06-16 18:30 +1000
    Re: Set a flag on the function or a global? Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-06-16 07:06 +0100
      Re: Set a flag on the function or a global? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-06-16 19:28 +1000
    Re: Set a flag on the function or a global? Jonas Wielicki <jonas@wielicki.name> - 2015-06-16 12:00 +0200
    Re: Set a flag on the function or a global? Michael Torrie <torriem@gmail.com> - 2015-06-16 07:44 -0600
    Re: Set a flag on the function or a global? Michael Torrie <torriem@gmail.com> - 2015-06-16 07:56 -0600
    Re: Set a flag on the function or a global? Peter Otten <__peter__@web.de> - 2015-06-16 15:59 +0200
    Re: Set a flag on the function or a global? Ethan Furman <ethan@stoneleaf.us> - 2015-06-16 07:57 -0700

Page 1 of 2  [1] 2  Next page →


#92644 — Set a flag on the function or a global?

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-06-15 23:57 +0000
SubjectSet a flag on the function or a global?
Message-ID<557f6676$0$21718$c3e8da3@news.astraweb.com>
I have a function in a module which is intended to be used by importing 
that name alone, then used interactively:

    from module import edir
    edir(args)


edir is an enhanced version of dir, and one of the enhancements is that 
you can filter out dunder methods. I have reason to believe that people 
are split on their opinion on whether dunder methods should be shown by 
default or not: some people want to see them, others do not. Since edir 
is meant to be used interactively, I want to give people a setting to 
control whether they get dunders by default or not.

I have two ideas for this, a module-level global, or a flag set on the 
function object itself. Remember that the usual way of using this will be 
"from module import edir", there are two obvious ways to set the global:

import module
module.dunders = False

# -or-

edir.__globals__['dunders'] = False


Alternatively, I can use a flag set on the function object itself:

edir.dunders = False


Naturally you can always override the default by explicitly specifying a 
keyword argument edir(obj, dunders=flag).

Thoughts and feedback? Please vote: a module global, or a flag on the 
object? Please give reasons, and remember that the function is intended 
for interactive use.


-- 
Steven D'Aprano

[toc] | [next] | [standalone]


#92645

FromChris Angelico <rosuav@gmail.com>
Date2015-06-16 10:07 +1000
Message-ID<mailman.488.1434413280.13271.python-list@python.org>
In reply to#92644
On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> I have two ideas for this, a module-level global, or a flag set on the
> function object itself. Remember that the usual way of using this will be
> "from module import edir", there are two obvious ways to set the global:
>
> import module
> module.dunders = False
>
> # -or-
>
> edir.__globals__['dunders'] = False
>
>
> Alternatively, I can use a flag set on the function object itself:
>
> edir.dunders = False
>

For most situations, the last one is extremely surprising - attributes
on functions aren't normally meant to be changed by outside callers,
it always feels wrong (they belong to the function itself). But since
this is interactive, I'd advise going for the absolute simplest, which
this would be. Go for the function attribute IMO.

ChrisA

[toc] | [prev] | [next] | [standalone]


#92646

FromEthan Furman <ethan@stoneleaf.us>
Date2015-06-15 17:19 -0700
Message-ID<mailman.489.1434414016.13271.python-list@python.org>
In reply to#92644
On 06/15/2015 04:57 PM, Steven D'Aprano wrote:

> Thoughts and feedback? Please vote: a module global, or a flag on the
> object? Please give reasons, and remember that the function is intended
> for interactive use.

Function attribute.

Setting a global on the module (which I may not have, and probably didn't, import) for only one function is overkill.

   edir.dunders = False # or True

is simple, elegant, easier to type, and perfectly in keeping with Python's dynamic nature.

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#92647

FromBen Finney <ben+python@benfinney.id.au>
Date2015-06-16 10:20 +1000
Message-ID<mailman.490.1434414054.13271.python-list@python.org>
In reply to#92644
Chris Angelico <rosuav@gmail.com> writes:

> On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
> > I can use a flag set on the function object itself:
> >
> > edir.dunders = False
>
> For most situations, the last one is extremely surprising - attributes
> on functions aren't normally meant to be changed by outside callers,
> it always feels wrong (they belong to the function itself).

I'm surprised by your assertion. To my mind, outside callers get simple
and direct access to the attribute, whereas the code of the function
itself does not have such easy access; unlike ‘self’ for the current
instance of a class, there's no obvious name to use for referring to the
function object within the function object's own code.

In what sense do they “belong to” the function itself *more than* to
outside callers?

-- 
 \       “It's easy to play any musical instrument: all you have to do |
  `\       is touch the right key at the right time and the instrument |
_o__)                        will play itself.” —Johann Sebastian Bach |
Ben Finney

[toc] | [prev] | [next] | [standalone]


#92665

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-06-16 19:07 +1000
Message-ID<557fe755$0$2827$c3e8da3$76491128@news.astraweb.com>
In reply to#92647
On Tuesday 16 June 2015 10:20, Ben Finney wrote:

> Chris Angelico <rosuav@gmail.com> writes:
> 
>> On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano
>> <steve+comp.lang.python@pearwood.info> wrote:
>> > I can use a flag set on the function object itself:
>> >
>> > edir.dunders = False
>>
>> For most situations, the last one is extremely surprising - attributes
>> on functions aren't normally meant to be changed by outside callers,
>> it always feels wrong (they belong to the function itself).
> 
> I'm surprised by your assertion. To my mind, outside callers get simple
> and direct access to the attribute, whereas the code of the function
> itself does not have such easy access; unlike ‘self’ for the current
> instance of a class, there's no obvious name to use for referring to the
> function object within the function object's own code.
> 
> In what sense do they “belong to” the function itself *more than* to
> outside callers?

I won't answer for Chris, but speaking for myself, I think that an attribute 
attached to a function is very clearly "part of" the function object in a 
way that a global is not.

A bare global gives no hint as to which function(s) it will affect:

dunders = True

We can simulate a namespace by giving the name a prefix:

edir_dunders = True
hasattr(edir, "dunders")  # False, despite the simulated namespace


but using a real namespace is much better:

edir.dunders = True
hasattr(edir, "dunders")  # True


But having said that, I think that especially in Python the implication here 
is that such an attribute is public and intended for outsiders to at least 
read, if not write.

Adding public attributes to functions is deliberately supported in Python, 
but it is greatly under-utilized.


-- 
Steve

[toc] | [prev] | [next] | [standalone]


#92648

FromEthan Furman <ethan@stoneleaf.us>
Date2015-06-15 17:21 -0700
Message-ID<mailman.491.1434414113.13271.python-list@python.org>
In reply to#92644
On 06/15/2015 05:07 PM, Chris Angelico wrote:
> On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano wrote:

>> I have two ideas for this, a module-level global, or a flag set on the
>> function object itself. Remember that the usual way of using this will be
>> "from module import edir", there are two obvious ways to set the global:
>>
>> import module
>> module.dunders = False
>>
>> # -or-
>>
>> edir.__globals__['dunders'] = False
>>
>>
>> Alternatively, I can use a flag set on the function object itself:
>>
>> edir.dunders = False
>>
>
> For most situations, the last one is extremely surprising - attributes
> on functions aren't normally meant to be changed by outside callers,

I find this viewpoint surprising, since function attributes are fairly rare.

> it always feels wrong (they belong to the function itself).

This seems silly -- a function is just another instance of some class.

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#92649

Fromsohcahtoa82@gmail.com
Date2015-06-15 17:24 -0700
Message-ID<4449bc52-4dba-486c-b426-7095e228a316@googlegroups.com>
In reply to#92644
On Monday, June 15, 2015 at 4:57:53 PM UTC-7, Steven D'Aprano wrote:
> I have a function in a module which is intended to be used by importing 
> that name alone, then used interactively:
> 
>     from module import edir
>     edir(args)
> 
> 
> edir is an enhanced version of dir, and one of the enhancements is that 
> you can filter out dunder methods. I have reason to believe that people 
> are split on their opinion on whether dunder methods should be shown by 
> default or not: some people want to see them, others do not. Since edir 
> is meant to be used interactively, I want to give people a setting to 
> control whether they get dunders by default or not.
> 
> I have two ideas for this, a module-level global, or a flag set on the 
> function object itself. Remember that the usual way of using this will be 
> "from module import edir", there are two obvious ways to set the global:
> 
> import module
> module.dunders = False
> 
> # -or-
> 
> edir.__globals__['dunders'] = False
> 
> 
> Alternatively, I can use a flag set on the function object itself:
> 
> edir.dunders = False
> 
> 
> Naturally you can always override the default by explicitly specifying a 
> keyword argument edir(obj, dunders=flag).
> 
> Thoughts and feedback? Please vote: a module global, or a flag on the 
> object? Please give reasons, and remember that the function is intended 
> for interactive use.
> 
> 
> -- 
> Steven D'Aprano

Using a keyword argument for the edir function is the most intuitive and easy to read, IMO.

Also, if two people are working on the same script, it could create problems if one person wants to filter them, but the other doesn't.  That would create a state that they would both have to monitor and keep setting back and forth, rather than each one just setting an argument on their calls.

[toc] | [prev] | [next] | [standalone]


#92652

FromMRAB <python@mrabarnett.plus.com>
Date2015-06-16 01:35 +0100
Message-ID<mailman.494.1434414969.13271.python-list@python.org>
In reply to#92649
On 2015-06-16 01:24, sohcahtoa82@gmail.com wrote:
> On Monday, June 15, 2015 at 4:57:53 PM UTC-7, Steven D'Aprano wrote:
>> I have a function in a module which is intended to be used by
>> importing that name alone, then used interactively:
>>
>> from module import edir edir(args)
>>
>>
>> edir is an enhanced version of dir, and one of the enhancements is
>> that you can filter out dunder methods. I have reason to believe
>> that people are split on their opinion on whether dunder methods
>> should be shown by default or not: some people want to see them,
>> others do not. Since edir is meant to be used interactively, I want
>> to give people a setting to control whether they get dunders by
>> default or not.
>>
>> I have two ideas for this, a module-level global, or a flag set on
>> the function object itself. Remember that the usual way of using
>> this will be "from module import edir", there are two obvious ways
>> to set the global:
>>
>> import module module.dunders = False
>>
>> # -or-
>>
>> edir.__globals__['dunders'] = False
>>
>>
>> Alternatively, I can use a flag set on the function object itself:
>>
>> edir.dunders = False
>>
>>
>> Naturally you can always override the default by explicitly
>> specifying a keyword argument edir(obj, dunders=flag).
>>
>> Thoughts and feedback? Please vote: a module global, or a flag on
>> the object? Please give reasons, and remember that the function is
>> intended for interactive use.
>>
>>
>> -- Steven D'Aprano
>
> Using a keyword argument for the edir function is the most intuitive
> and easy to read, IMO.
>
> Also, if two people are working on the same script, it could create
> problems if one person wants to filter them, but the other doesn't.
> That would create a state that they would both have to monitor and
> keep setting back and forth, rather than each one just setting an
> argument on their calls.
>
But it's meant to be used interactively. If they're using it in a
script, they'd most likely set the argument appropriately.

[toc] | [prev] | [next] | [standalone]


#92662

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-06-16 18:18 +1000
Message-ID<557fdbd6$0$11097$c3e8da3@news.astraweb.com>
In reply to#92652
On Tuesday 16 June 2015 10:35, MRAB wrote:

> On 2015-06-16 01:24, sohcahtoa82@gmail.com wrote:

>> Using a keyword argument for the edir function is the most intuitive
>> and easy to read, IMO.

edir() has a keyword argument: edir(x, dunders=False) suppresses the return 
of dunder names. But since the primary purpose of [e]dir is, in my opinion, 
to be used interactively, needing to type an extra 15 characters to hide 
dunders is too inconvenient.


>> Also, if two people are working on the same script, it could create
>> problems if one person wants to filter them, but the other doesn't.
>> That would create a state that they would both have to monitor and
>> keep setting back and forth, rather than each one just setting an
>> argument on their calls.
>>
> But it's meant to be used interactively. If they're using it in a
> script, they'd most likely set the argument appropriately.

Yes.

The primary use-case (at least *my* use-case, and hopefully others) is to 
have "from module import edir as dir" in their Python startup file. That 
means that when running interactively, they will get the enhanced version of 
dir, but when running a script or an application they'll just get the 
regular one.

(Ideally, the regular one will eventually gain the same superpowers as edir 
has, but that's a discussion for another day.)

Besides, apart from the inspect module, which probably shouldn't, who uses 
dir() programmatically?

(If you do, you'll be glad to hear that edir() behaves the same as regular 
dir() by default.)


-- 
Steve

[toc] | [prev] | [next] | [standalone]


#92674

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2015-06-16 13:45 +0100
Message-ID<mailman.510.1434458729.13271.python-list@python.org>
In reply to#92662
On 16 June 2015 at 09:18, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
>
> The primary use-case (at least *my* use-case, and hopefully others) is to
> have "from module import edir as dir" in their Python startup file. That
> means that when running interactively, they will get the enhanced version of
> dir, but when running a script or an application they'll just get the
> regular one.
>
> (Ideally, the regular one will eventually gain the same superpowers as edir
> has, but that's a discussion for another day.)
>
> Besides, apart from the inspect module, which probably shouldn't, who uses
> dir() programmatically?
>
> (If you do, you'll be glad to hear that edir() behaves the same as regular
> dir() by default.)

What's the point in giving edir two modes if one of them is the same
as dir? You could just do "from module import edir" and then use
dir/edir as desired.

Personally I just use ipython's tab-completion instead of dir. It
shows the dunders if you first type underscores but hides them
otherwise e.g.:

In [1]: a = []

In [2]: a.<tab>
a.append   a.count    a.extend   a.index    a.insert   a.pop
a.remove   a.reverse  a.sort

In [2]: a.__<tab>
a.__add__           a.__format__        a.__imul__          a.__new__
         a.__setslice__
a.__class__         a.__ge__            a.__init__
a.__reduce__        a.__sizeof__
a.__contains__      a.__getattribute__  a.__iter__
a.__reduce_ex__     a.__str__
a.__delattr__       a.__getitem__       a.__le__            a.__repr__
         a.__subclasshook__
a.__delitem__       a.__getslice__      a.__len__           a.__reversed__
a.__delslice__      a.__gt__            a.__lt__            a.__rmul__
a.__doc__           a.__hash__          a.__mul__           a.__setattr__
a.__eq__            a.__iadd__          a.__ne__            a.__setitem__


--
Oscar

[toc] | [prev] | [next] | [standalone]


#92705

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-06-16 22:46 +0000
Message-ID<5580a72a$0$1667$c3e8da3$5496439d@news.astraweb.com>
In reply to#92674
On Tue, 16 Jun 2015 13:45:01 +0100, Oscar Benjamin wrote:

> On 16 June 2015 at 09:18, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
>>
>> The primary use-case (at least *my* use-case, and hopefully others) is
>> to have "from module import edir as dir" in their Python startup file.
>> That means that when running interactively, they will get the enhanced
>> version of dir, but when running a script or an application they'll
>> just get the regular one.
>>
>> (Ideally, the regular one will eventually gain the same superpowers as
>> edir has, but that's a discussion for another day.)
>>
>> Besides, apart from the inspect module, which probably shouldn't, who
>> uses dir() programmatically?
>>
>> (If you do, you'll be glad to hear that edir() behaves the same as
>> regular dir() by default.)
> 
> What's the point in giving edir two modes if one of them is the same as
> dir? You could just do "from module import edir" and then use dir/edir
> as desired.

Oh ye of little faith :-)

I practically live in the Python interactive interpreter, and this has 
evolved from functionality I have wished dir has. It's a lot more than 
just whether or not dunders are displayed by default.

The most important feature of edir() is that it supports globbing and 
substring matches:


py> dir("", "low")
['islower', 'lower']
py> dir('', '*er')
['center', 'isidentifier', 'islower', 'isupper', 'lower', 'upper']


By default, globs are case-insensitive, but you can force them to be case-
sensitive with a metachar. I added this because I kept coming across 
classes with methods that used CamelCase when I expected lowercase. It 
understands the standard metacharacters ? * and [] as well as prefixes ! 
to invert the match and = to force case-sensitivity.

It also optionally includes the metaclass of the object. This was 
requested by somebody else as standard behaviour for dir, on python-ideas 
and the bug tracker, but rejected.

The reason this was requested is that dir() intentionally doesn't return 
all the attributes visible from an object:

py> "mro" in dir(str)
False
py> str.mro
<built-in method mro of type object at 0x81db360>


I thought it seemed like an interesting idea, and added it as an option 
with a keyword-only argument:

py> "mro" in dir(str, meta=True)
True


but frankly I'm not entirely sure this feature is useful. Time will tell.


> Personally I just use ipython's tab-completion instead of dir. It shows
> the dunders if you first type underscores but hides them otherwise e.g.:

Tab completion is great, but it solves a different problem. One with some 
overlap, admittedly, but still different.


-- 
Steven D'Aprano

[toc] | [prev] | [next] | [standalone]


#92711

FromCameron Simpson <cs@zip.com.au>
Date2015-06-17 09:51 +1000
Message-ID<mailman.530.1434500492.13271.python-list@python.org>
In reply to#92662
On 16Jun2015 18:18, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
>On Tuesday 16 June 2015 10:35, MRAB wrote:
>> On 2015-06-16 01:24, sohcahtoa82@gmail.com wrote:
>>> Using a keyword argument for the edir function is the most intuitive
>>> and easy to read, IMO.
>
>edir() has a keyword argument: edir(x, dunders=False) suppresses the return
>of dunder names. But since the primary purpose of [e]dir is, in my opinion,
>to be used interactively, needing to type an extra 15 characters to hide
>dunders is too inconvenient.

I'm just catching up here, but have now read the whole thread.

I am personally against a global (==> single variable affecting all callers) of 
any kind, be it a function attribute or whatever. Why? For that same reason 
that we discourage use of functions like os.chdir or os.umask except in rare 
circumstances: the single call inevitably affects the entire program behaviour.

Your intended use case may be interactive, where I agree the convenience looks 
nice. However, I think it inevitable that someone imports your edir function as 
an aid to writing friendly debugging messages is a larger program, and thus is 
escapes into noninteractive use. (As an example, I have a class named "O" which 
I use as a base class for many classes, especially in the debugging phase; its 
major semantic is friendlier __str__ and __repr__ for exactly the same reasons 
you wrote "edir", and with similar effect.)

On that basis (avoiding global state) my preference would be strongly to rely 
entirely on your keyword argument (dunder=False) and to offer two flavors, such 
as the "edir" and "edir_" suggested elsewhere. The user can always import 
"edir_ as edir_noisy" if they are of the mindset which dislikes single trailing 
underscores.

[...]
>> But it's meant to be used interactively. If they're using it in a
>> script, they'd most likely set the argument appropriately.
>
>Yes.

Ideally yes. "Most likely"? I have less confidence there.

>The primary use-case (at least *my* use-case, and hopefully others) is to
>have "from module import edir as dir" in their Python startup file. That
>means that when running interactively, they will get the enhanced version of
>dir, but when running a script or an application they'll just get the
>regular one.

This fits well with two functions, then they can import "edir" or "edir_" as 
dir as they see fit.

>Besides, apart from the inspect module, which probably shouldn't, who uses
>dir() programmatically?

Directly, perhaps rarely. But I use my O.__str__ method implicitly quite a lot, 
and it has a similar purpose to your edir. (It is not the same, so the parallel 
is not perfect.)

Cheers,
Cameron Simpson <cs@zip.com.au>

All who love Liberty are enemies of the State.  - Karl Hess

[toc] | [prev] | [next] | [standalone]


#92757

FromSteven D'Aprano <steve@pearwood.info>
Date2015-06-18 00:59 +1000
Message-ID<55818b3c$0$1665$c3e8da3$5496439d@news.astraweb.com>
In reply to#92711
On Wed, 17 Jun 2015 09:51 am, Cameron Simpson wrote:

> On 16Jun2015 18:18, Steven D'Aprano <steve+comp.lang.python@pearwood.info>
> wrote:
>>On Tuesday 16 June 2015 10:35, MRAB wrote:
>>> On 2015-06-16 01:24, sohcahtoa82@gmail.com wrote:
>>>> Using a keyword argument for the edir function is the most intuitive
>>>> and easy to read, IMO.
>>
>>edir() has a keyword argument: edir(x, dunders=False) suppresses the
>>return of dunder names. But since the primary purpose of [e]dir is, in my
>>opinion, to be used interactively, needing to type an extra 15 characters
>>to hide dunders is too inconvenient.
> 
> I'm just catching up here, but have now read the whole thread.

Thanks for doing so before commenting :-)


> I am personally against a global (==> single variable affecting all
> callers) of any kind, be it a function attribute or whatever. Why? For
> that same reason that we discourage use of functions like os.chdir or
> os.umask except in rare circumstances: the single call inevitably affects
> the entire program behaviour.

Well yes. And I would normally agree. But I think a better analogy here is
with print. By default, print outputs to stdout. You can customise that by
giving an extra argument to print:


print(spam, file=sys.stderr)  # Python 3
print >>sys.stderr, spam  # Python 2


or you can re-direct sys.stdout. Both are allowed. But doing the later is
potentially more disruptive, and should be done with care. Nevertheless, it
is supported, and Python will set up stdout to the appropriate file for you
when you start.

Although I think you're being overly cautious, I've changed the behaviour:

- the default is dunders=True, always;

- you can manually override the default with an optional, explicit dunders
keyword-only argument, always;

- you can change the default to dunders=False by setting an attribute, only
when running in interactive mode.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#92760

FromLaura Creighton <lac@openend.se>
Date2015-06-17 17:06 +0200
Message-ID<mailman.556.1434553624.13271.python-list@python.org>
In reply to#92757
To figure out what I like, I would need to play with edir, and the
suite that it comes with.

I suspect there is command like:

stop_showing_me_all_this_uninteresting_stuff = True

in my future, and dunders is only a small part of that.

Laura

[toc] | [prev] | [next] | [standalone]


#92767

FromSteven D'Aprano <steve@pearwood.info>
Date2015-06-18 01:55 +1000
Message-ID<55819878$0$1658$c3e8da3$5496439d@news.astraweb.com>
In reply to#92760
On Thu, 18 Jun 2015 01:06 am, Laura Creighton wrote:

> To figure out what I like, I would need to play with edir, and the
> suite that it comes with.
> 
> I suspect there is command like:
> 
> stop_showing_me_all_this_uninteresting_stuff = True
> 
> in my future, and dunders is only a small part of that.


The full signature is:

edir([object [, glob=''] [, dunders=True] [, meta=False]])

All four arguments are optional, and dunders and meta are keyword-only. It
is intended to work with Python 2.4 or better. It may not work in Jython on
IronPython, depending on whether or not sys._getframe is supported.

The glob argument is the most interesting, in my opinion. If you give a
non-empty glob, only names matching that glob are returned:

py> dir('', 'is*')
['isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper']


If the glob contains no metacharacters, a plain substring match is done:

py> dir('', 'up')
['isupper', 'upper']


Matches are case-insensitive by default, but can be made case-sensitive by
using a prefix "=". To invert the match (return names which don't match),
use "!" as the prefix. You can use "!=" as a combined prefix.

I haven't yet released this as an independent package as yet, but you can
find it here:

https://code.google.com/p/my-startup-file/

in the "enhanced_dir.py" module.

Consider it beta quality and free for personal use; if anyone wishes a more
formal licence, either wait until I publish it independently, or contact me
off list.




-- 
Steven

[toc] | [prev] | [next] | [standalone]


#92793 — Documenting a function signature (was: Set a flag on the function or a global?)

FromBen Finney <ben+python@benfinney.id.au>
Date2015-06-18 10:04 +1000
SubjectDocumenting a function signature (was: Set a flag on the function or a global?)
Message-ID<mailman.571.1434585912.13271.python-list@python.org>
In reply to#92767
Steven D'Aprano <steve@pearwood.info> writes:

> The full signature is:
>
> edir([object [, glob=''] [, dunders=True] [, meta=False]])
>
> All four arguments are optional, and dunders and meta are
> keyword-only.

The official documentation seems to prefer this style::

    edit(object, glob='', *, dunders=True, meta=False)

(I think that's the style, anyway.)

I like that it gets rid of square brackets; with the notation showing a
default value, that already communicates that a parameter is optional.

Since the introduction of keyword-only arguments in Python functions,
the question arises of how to communicate this in documentation.

The lone asterisk showing the separation of keyword-only arguments from
the rest is confusing to me. Not least because it is (if I understand
correctly) invalid syntax to actually have that in Python code.

What are your thoughts, dear reader, on the documentation style for
showing a Python function signature, now that we have not only default
arguments but also keyword-only arguments?

-- 
 \      “It is difficult to get a man to understand something when his |
  `\   salary depends upon his not understanding it.” —Upton Sinclair, |
_o__)                                                             1935 |
Ben Finney

[toc] | [prev] | [next] | [standalone]


#92795 — Re: Documenting a function signature (was: Set a flag on the function or a global?)

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-06-17 18:10 -0600
SubjectRe: Documenting a function signature (was: Set a flag on the function or a global?)
Message-ID<mailman.573.1434586294.13271.python-list@python.org>
In reply to#92767
On Wed, Jun 17, 2015 at 6:04 PM, Ben Finney <ben+python@benfinney.id.au> wrote:
> Steven D'Aprano <steve@pearwood.info> writes:
>
>> The full signature is:
>>
>> edir([object [, glob=''] [, dunders=True] [, meta=False]])
>>
>> All four arguments are optional, and dunders and meta are
>> keyword-only.
>
> The official documentation seems to prefer this style::
>
>     edit(object, glob='', *, dunders=True, meta=False)
>
> (I think that's the style, anyway.)
>
> I like that it gets rid of square brackets; with the notation showing a
> default value, that already communicates that a parameter is optional.
>
> Since the introduction of keyword-only arguments in Python functions,
> the question arises of how to communicate this in documentation.
>
> The lone asterisk showing the separation of keyword-only arguments from
> the rest is confusing to me. Not least because it is (if I understand
> correctly) invalid syntax to actually have that in Python code.

No, this is valid syntax in Python 3. It means the same thing to the
compiler -- the remaining arguments are keyword-only -- that it means
in the documentation.

[toc] | [prev] | [next] | [standalone]


#92796 — Re: Documenting a function signature (was: Set a flag on the function or a global?)

FromChris Angelico <rosuav@gmail.com>
Date2015-06-18 10:14 +1000
SubjectRe: Documenting a function signature (was: Set a flag on the function or a global?)
Message-ID<mailman.574.1434586497.13271.python-list@python.org>
In reply to#92767
On Thu, Jun 18, 2015 at 10:04 AM, Ben Finney <ben+python@benfinney.id.au> wrote:
> Steven D'Aprano <steve@pearwood.info> writes:
>
>> The full signature is:
>>
>> edir([object [, glob=''] [, dunders=True] [, meta=False]])
>>
>> All four arguments are optional, and dunders and meta are
>> keyword-only.
>
> The official documentation seems to prefer this style::
>
>     edit(object, glob='', *, dunders=True, meta=False)

Mostly. That would imply that object is a mandatory parameter, which
AIUI isn't the case for Steven's edir. The downside of this kind of
signature is that it's hard to show the parameters that have unusual
defaults (either sentinel objects and custom code to cope, or they're
pulled out of *a or **kw).

> The lone asterisk showing the separation of keyword-only arguments from
> the rest is confusing to me. Not least because it is (if I understand
> correctly) invalid syntax to actually have that in Python code.

It's perfectly valid, and it does exactly what it looks like. What's
not valid syntax is the slash that comes up in some Argument Clinic
functions:

>>> help(list.__init__)
__init__(self, /, *args, **kwargs)
    Initialize self.  See help(type(self)) for accurate signature.

> What are your thoughts, dear reader, on the documentation style for
> showing a Python function signature, now that we have not only default
> arguments but also keyword-only arguments?

I like the executable form when it's fairly simple. If you have a
boolean that defaults to True but you can set it to false, saying
"dunders=True" is awesomely clear. It's a bit harder when you want to
do something more complicated, but so far as it's possible, I'd like
to see signatures that look like they were copied and pasted straight
from the function definition.

ChrisA

[toc] | [prev] | [next] | [standalone]


#92826 — Re: Documenting a function signature (was: Set a flag on the function or a global?)

Fromrandom832@fastmail.us
Date2015-06-18 08:37 -0400
SubjectRe: Documenting a function signature (was: Set a flag on the function or a global?)
Message-ID<mailman.598.1434631036.13271.python-list@python.org>
In reply to#92767
On Wed, Jun 17, 2015, at 20:14, Chris Angelico wrote:
> Mostly. That would imply that object is a mandatory parameter, which
> AIUI isn't the case for Steven's edir. The downside of this kind of
> signature is that it's hard to show the parameters that have unusual
> defaults (either sentinel objects and custom code to cope, or they're
> pulled out of *a or **kw).

My instinct would be to put =... for that case and explain in the
documentation "If foo is not provided, [behavior]".

Of course, that runs the risk of people thinking you actually mean
Ellipsis, or that providing Ellipsis explicitly will give the same
behavior as the default.

[toc] | [prev] | [next] | [standalone]


#92854 — Re: Documenting a function signature (was: Set a flag on the function or a global?)

FromLaura Creighton <lac@openend.se>
Date2015-06-18 23:38 +0200
SubjectRe: Documenting a function signature (was: Set a flag on the function or a global?)
Message-ID<mailman.613.1434663725.13271.python-list@python.org>
In reply to#92767
In a message of Thu, 18 Jun 2015 10:04:46 +1000, Ben Finney writes:
>Since the introduction of keyword-only arguments in Python functions,
>the question arises of how to communicate this in documentation.

I suppose it is way too late to scream "I hate keyword-only arguments"!

>The lone asterisk showing the separation of keyword-only arguments from
>the rest is confusing to me. Not least because it is (if I understand
>correctly) invalid syntax to actually have that in Python code.

Me too.

Laura

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.python


csiph-web