Re: Set a flag on the function or a global?

2015-06-17 Thread Steven D'Aprano
On Wed, 17 Jun 2015 09:51 am, Cameron Simpson wrote:

 On 16Jun2015 18:18, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info
 wrote:
On Tuesday 16 June 2015 10:35, MRAB wrote:
 On 2015-06-16 01:24, sohcahto...@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

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-17 Thread Laura Creighton
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

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-17 Thread Steven D'Aprano
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

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Michael Torrie
On 06/15/2015 06:20 PM, Ben Finney wrote:
 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.

Of course it has access, and it's obvious and easy as well:

def foo():
foo.flag = True

The only thing I'm not sure of is a clean way to test for the
attribute's existence.  The __init__.py of a package, or the
initialization code of the module could preset the attribute, though.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Oscar Benjamin
On 16 June 2015 at 09:18, Steven D'Aprano
steve+comp.lang.pyt...@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.counta.extend   a.indexa.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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Peter Otten
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.


In general I'm wary of routines that take flags (such as 'swapped')
that really mean use a different version of the function -- these
flags are almost always passed from constants and so it would be more
efficient to have a second name for the variant function.

http://legacy.python.org/search/hypermail/python-1994q2/0852.html


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Michael Torrie
On 06/15/2015 06:19 PM, Ethan Furman wrote:
 Setting a global on the module (which I may not have, and probably
 didn't, import) for only one function is overkill.

What do you mean?  Even if you pull in just one function from the
module on an import, the module's initialization code still runs.




-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Ethan Furman

On 06/16/2015 06:56 AM, Michael Torrie wrote:

On 06/15/2015 06:19 PM, Ethan Furman wrote:


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


What do you mean?  Even if you pull in just one function from the
module on an import, the module's initialization code still runs.


For me, an appropriate use of globals requires that it will be used by many 
other pieces of code in that module.  If only one piece of code is using it, 
it's not really global.

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Steven D'Aprano
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.pyt...@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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Cameron Simpson

On 16Jun2015 18:18, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info 
wrote:

On Tuesday 16 June 2015 10:35, MRAB wrote:

On 2015-06-16 01:24, sohcahto...@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 c...@zip.com.au

All who love Liberty are enemies of the State.  - Karl Hess
--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Mark Lawrence

On 16/06/2015 00:57, 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.




For interactive use I'd be perfectly happy with just the keyword 
argument.  Why bother toggling something when I can explicitly set it in 
the call each and every time?  If I have to choose it's a flag on the 
object, just no competition.


--
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Steven D'Aprano
On Tuesday 16 June 2015 10:35, MRAB wrote:

 On 2015-06-16 01:24, sohcahto...@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

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Steven D'Aprano
On Tuesday 16 June 2015 10:24, Ron Adam wrote:

 Another way is to make it an object with a __call__ method.
 
 The the attribute can be accessed from both outside and inside dependably.

That's what functions are, objects with a __call__ method:


py (lambda: None).__call__
method-wrapper '__call__' of function object at 0xb7301a04


One slight disadvantage is that functions don't take a self parameter by 
default, which means they have to refer to themselves by name:

def spam():
print spam.attr


Here's a fun hack:

py from types import MethodType
py def physician(func):
... # As in, Physician, Know Thyself :-)
... return MethodType(func, func)
... 
py @physician
... def spam(this, n):
... return this.food * n
... 
py spam.__func__.food = spam-and-eggs 
py spam(3)
'spam-and-eggs spam-and-eggs spam-and-eggs '


Alas, you cannot write directly to the method object itself :-(



-- 
Steve

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Steven D'Aprano
On Tuesday 16 June 2015 10:20, Ben Finney wrote:

 Chris Angelico ros...@gmail.com writes:
 
 On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano
 steve+comp.lang.pyt...@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

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Steven D'Aprano
On Tuesday 16 June 2015 16:06, Mark Lawrence wrote:

 On 16/06/2015 00:57, Steven D'Aprano wrote:
[...]
 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.


 
 For interactive use I'd be perfectly happy with just the keyword
 argument.  Why bother toggling something when I can explicitly set it in
 the call each and every time?  If I have to choose it's a flag on the
 object, just no competition.

The idea is to set the default behaviour: does edir(obj) display dunder 
methods by default or not? I've found that many people don't want to see the 
dunder methods, and find dir() less pleasant or useful because it shows 
them. Others disagree and want to see them. So you can set the default 
behaviour you want, and then only worry about giving an explicit argument 
when you want the opposite.

There is no intention for people to toggle the flag between calls!

# don't do this!
edir.dunders = True
edir(x)
edir.dunders = False
edir(y)


# do this instead
edir.dunders = True  # if that is your preferred setting
edir(x)
edir(y, dunders=False)




-- 
Steve

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Ron Adam



On 06/16/2015 05:15 AM, Steven D'Aprano wrote:

On Tuesday 16 June 2015 10:24, Ron Adam wrote:


Another way is to make it an object with a __call__ method.

The the attribute can be accessed from both outside and inside dependably.

That's what functions are, objects with a __call__ method:


py (lambda: None).__call__
method-wrapper '__call__' of function object at 0xb7301a04


Yes ;-)



One slight disadvantage is that functions don't take a self parameter by
default, which means they have to refer to themselves by name:

def spam():
 print spam.attr


Here's a fun hack:

py from types import MethodType
py def physician(func):
... # As in, Physician, Know Thyself:-)
... return MethodType(func, func)
...
py @physician
... def spam(this, n):
... return this.food * n
...
py spam.__func__.food = spam-and-eggs 
py spam(3)
'spam-and-eggs spam-and-eggs spam-and-eggs'



How about this?:  (paste it into your console)

#-
import sys
class EDir:
long = False
def __call__(self, obj=None):
if obj == None:
d = sys._getframe(1).f_locals
else:
d = dir(obj)
return [x for x in d if self.long or not x.startswith(_)]


edir = EDir()

edir()

edir(edir)

edir.long = True
edir(edir)

edir.long = False
edir(edir)
#--


I didn't test how that works from other modules or in nested scopes.  Also 
replacing None with a unique sentinel object may be better so dir(None) 
will work.


Cheers,
   Ron







--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Steven D'Aprano
On Tuesday 16 June 2015 10:37, Paul Rubin wrote:

 Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes:
 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.
 
 Both are bad.  More state to remember, ugh.  Instead have separate entry
 points for filtering or not filtering the dunders.  Something like:
 
   edir(obj) = no dunders
   edir_(obj) = dunders.

I certainly wouldn't call it edir_ but I'd maybe call it edir2 or ddir 
(Dunderless DIR) or just_like_builtin_dir_only_better. wink

Normally I would agree with you, as a matter of principle, functions which 
differ only by an argument called as a constant, particular when that 
argument is a flag, should be split into multiple functions.

That is, instead of foo(x, flag=True) and foo(x, flag=False), have foo(x) 
and foo2(x).

One disadvantage of this, though, is that it may not be self-evident which 
function does what. Who remembers the difference between all the os.exec* 
functions? Speaking of which:

py dir(os, 'exec*')
['execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 
'execvpe']


But in this case, because [e]dir is intended to be run interactively, I 
think that the convenience of a single function is more important. Most 
people will set the default setting to whatever they prefer and then 95% of 
the time just use it as given, only occasionally giving the dunders keyword 
argument when they need the opposite setting.

Or at least, that's how *I* use it.

-- 
Steve

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-16 Thread Jonas Wielicki
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA512



On 16.06.2015 01:57, Steven D'Aprano wrote:
 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.

I like a flag on the object, and this would be my implementation:

```
def edir_impl():
# implementation of edir
pass

class Edir(object):
def __init__(self):
self.kwargs = {}

def __getattr__(self, name):
return self.kwargs[name]

def __setattr__(self, name, value):
self.kwargs[name] = value

def __delattr__(self, name):
del self.kwargs[name]

def __call__(self, *args, **kwargs):
kwargs_to_use = self.kwargs.copy()
kwargs_to_use.update(kwargs)
edir_impl(*args, **kwargs_to_use)

edir = Edir()
```
(untested, but you get the idea, hopefully)

This also allows to have several versions of edir around in a shell
with different default settings.

regards,
jwi
-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iQIcBAEBCgAGBQJVf/PLAAoJEMBiAyWXYliKFM4P/jf/ZDZFacrRuk29tNzNFjA2
6UT4GURF6UX+C129gGgaqxpDY9oD9herfUpqbFxfNWq4Rye9MX+xkv3uQUsP5BXE
G7VjrSC0qd1GmdwFxdIQEb1fa6LgMmOnnYe/sIw5XWF2Rtbkqlisw7ZO3YDsWT9d
cadoEh0ShFbM6z4MUDEd8tu6RQ/j61v906TwsVgY+4uI8WWOzqHumM7pkWHxP2ns
3b/2ijQJNNLwH3UfbPBo3YhJWt0c+ACzuxr5MamVHUJBZpNatcszti3mkn2CtDCb
m5Kc0gO0RxHVaHV4RWrjYlcllhysQ/zeAuOz1PHEqevlitj8z1cBy3p4sfz8GOZe
XAKChaZHVAq7eTGzgtLksBQ0dujLxy9zLWiHfeLfMnTyZoYFKVCM2rlSYutnkI0f
7VdaaKStVpqkXeJHX1n1LvHBOroQCFtUFn2F0FylpR/nBA7ar9epZYiCWbrb21xO
DYs8T7dC7DI1waLeXJ2JbXiXqh6cQ9Fy86fm+VE1lmkJ6LvboRCN9eWMQ1o1+RtM
Dla6CvH2zxgW2u3HZCIoU9TusYaNLR9kSxqCMc2yLuMiUQpj0HfjZCR+ZP2/9phS
wx+qZx+5X25ybXlCZRtlvzb409BclOJ7JOynboX4MU4M9sSCPJhb5/ZcM79r7nJa
o0y06nE5eReu71TMwmDW
=r9uV
-END PGP SIGNATURE-
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Ethan Furman

On 06/15/2015 05:37 PM, Paul Rubin wrote:

Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes:

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.


Both are bad.  More state to remember, ugh.  Instead have separate entry
points for filtering or not filtering the dunders.  Something like:

   edir(obj) = no dunders
   edir_(obj) = dunders.


`edir_` ?  What a horrible name.  I hate trailing underscores.  Too easy to 
miss.

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread MRAB

On 2015-06-16 01:53, Ethan Furman wrote:

On 06/15/2015 05:37 PM, Paul Rubin wrote:

Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes:

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.


Both are bad.  More state to remember, ugh.  Instead have separate entry
points for filtering or not filtering the dunders.  Something like:

   edir(obj) = no dunders
   edir_(obj) = dunders.


`edir_` ?  What a horrible name.  I hate trailing underscores.  Too easy to 
miss.


Especially when there's also `edir`! :-)

--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Paul Rubin
Ethan Furman et...@stoneleaf.us writes:
edir_(obj) = dunders.
 `edir_` ?  What a horrible name.  I hate trailing underscores.  Too easy to 
 miss.

They've worked ok for me at various times.  edir_u (for unfiltered) is
another idea.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Chris Angelico
On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano
steve+comp.lang.pyt...@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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Ethan Furman

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~
--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Ben Finney
Chris Angelico ros...@gmail.com writes:

 On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano
 steve+comp.lang.pyt...@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

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Ethan Furman

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~
--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread sohcahtoa82
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.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Ron Adam



On 06/15/2015 08:07 PM, Chris Angelico wrote:

On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano
steve+comp.lang.pyt...@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,


Or inside callers either.  You can't be sure of the name and there is no self.



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.



Another way is to make it an object with a __call__ method.

The the attribute can be accessed from both outside and inside dependably.

Cheers,
   Ron

--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Chris Angelico
On Tue, Jun 16, 2015 at 10:20 AM, Ben Finney ben+pyt...@benfinney.id.au wrote:
 Chris Angelico ros...@gmail.com writes:

 On Tue, Jun 16, 2015 at 9:57 AM, Steven D'Aprano
 steve+comp.lang.pyt...@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?

Custom function attributes (as in, those not set by the interpreter
itself) are pretty rare, but I've usually seen them only being defined
by the module that created them. Setting that kind of attribute
externally, from a different module, seems odd - and undiscoverable.
But for interactive work, that should be fine.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread MRAB

On 2015-06-16 01:24, sohcahto...@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.
--
https://mail.python.org/mailman/listinfo/python-list


Re: Set a flag on the function or a global?

2015-06-15 Thread Paul Rubin
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes:
 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.

Both are bad.  More state to remember, ugh.  Instead have separate entry
points for filtering or not filtering the dunders.  Something like:

  edir(obj) = no dunders
  edir_(obj) = dunders.  

If you also support the keyword arg, then you could have

  edir_(obj)=functools.partial(edir,dunders=True).
-- 
https://mail.python.org/mailman/listinfo/python-list