[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Is it explicitly specified?

mario

2/3/2008 11:00:00 AM


Is there any way to tell between whether a keyword arg has been explicitly
specified (to the same value as the default for it) or not... For example:

def func(key=None):
do something with key

But the following two usages give same results:

func()
func(key=None)

It may sometimes be useful to make use of the conceptual difference between
these two cases, that is that in one case the user did not specify any key
and in the other the user explicitly specified the key to be None.

Is there any way to tell this difference from within the called function?
And if so, would there be any strong reasons to not rely on this
difference? Would it be maybe a little abusive of what a keyword arg
actually is?

mario



18 Answers

Jorge Godoy

2/3/2008 11:19:00 AM

0

mario ruggier wrote:

> Is there any way to tell between whether a keyword arg has been explicitly
> specified (to the same value as the default for it) or not... For example:
>
> def func(key=None):
> do something with key
>
> But the following two usages give same results:
>
> func()
> func(key=None)
>
> It may sometimes be useful to make use of the conceptual difference
> between these two cases, that is that in one case the user did not specify
> any key and in the other the user explicitly specified the key to be None.
>
> Is there any way to tell this difference from within the called function?
> And if so, would there be any strong reasons to not rely on this
> difference? Would it be maybe a little abusive of what a keyword arg
> actually is?

If you change the idiom you use to:

>>> def myfunc(**kwargs):
.... something = kwargs.get('something', None)
.... print something
....
>>> myfunc()
None
>>> myfunc(something='Something')
Something
>>>

Then you can test if 'something' is in kwargs dict or not. If it isn't,
then you used the default value. If it is, then the user
supplied 'something' to you, no matter what its value is.


Arnaud Delobelle

2/3/2008 11:31:00 AM

0

On Feb 3, 11:00 am, mario ruggier <ma...@ruggier.org> wrote:
> Is there any way to tell between whether a keyword arg has been explicitly
> specified (to the same value as the default for it) or not... For example:
>
> def func(key=None):
>     do something with key
>
> But the following two usages give same results:
>
> func()
> func(key=None)
>
> It may sometimes be useful to make use of the conceptual difference between
> these two cases, that is that in one case the user did not specify any key
> and in the other the user explicitly specified the key to be None.
>
> Is there any way to tell this difference from within the called function?
> And if so, would there be any strong reasons to not rely on this
> difference? Would it be maybe a little abusive of what a keyword arg
> actually is?
>
> mario

One way is to create an object which is only ever used as the default
arguement:

nokey = object()

def func(key=nokey):
if key is nokey:
# key not given
else:
# key given

--
Arnaud

TeroV

2/3/2008 11:36:00 AM

0

Jorge Godoy wrote:
> mario ruggier wrote:
>
>> Is there any way to tell between whether a keyword arg has been explicitly
>> specified (to the same value as the default for it) or not... For example:
>>
>> def func(key=None):
>> do something with key
>>
>> But the following two usages give same results:
>>
>> func()
>> func(key=None)
>>
>> It may sometimes be useful to make use of the conceptual difference
>> between these two cases, that is that in one case the user did not specify
>> any key and in the other the user explicitly specified the key to be None.
>>
>> Is there any way to tell this difference from within the called function?
>> And if so, would there be any strong reasons to not rely on this
>> difference? Would it be maybe a little abusive of what a keyword arg
>> actually is?
>
> If you change the idiom you use to:
>
>>>> def myfunc(**kwargs):
> ... something = kwargs.get('something', None)
> ... print something
> ...
>>>> myfunc()
> None
>>>> myfunc(something='Something')
> Something
>
> Then you can test if 'something' is in kwargs dict or not. If it isn't,
> then you used the default value. If it is, then the user
> supplied 'something' to you, no matter what its value is.
>
>

Exactly, and if you use idiom func(*args, **kwargs) you can distinguish
all the usage cases:

>>> def func(*args, **kwargs):
.... print(args, kwargs)
....
>>> func()
() {}
>>> func(key='alabama')
() {'key': 'alabama'}
>>> func('alabama')
('alabama',) {}

mario

2/3/2008 11:45:00 AM

0

On Feb 3, 12:35 pm, TeroV <te...@nowhere.invalid> wrote:
> Jorge Godoy wrote:
> > mario ruggier wrote:
>
> >> Is there any way to tell between whether a keyword arg has been explicitly
> >> specified (to the same value as the default for it) or not... For example:
>
> >> def func(key=None):
> >> do something with key
>
> >> But the following two usages give same results:
>
> >> func()
> >> func(key=None)
>
> >> It may sometimes be useful to make use of the conceptual difference
> >> between these two cases, that is that in one case the user did not specify
> >> any key and in the other the user explicitly specified the key to be None.
>
> >> Is there any way to tell this difference from within the called function?
> >> And if so, would there be any strong reasons to not rely on this
> >> difference? Would it be maybe a little abusive of what a keyword arg
> >> actually is?
>
> > If you change the idiom you use to:
>
> >>>> def myfunc(**kwargs):
> > ... something = kwargs.get('something', None)
> > ... print something
> > ...
> >>>> myfunc()
> > None
> >>>> myfunc(something='Something')
> > Something
>
> > Then you can test if 'something' is in kwargs dict or not. If it isn't,
> > then you used the default value. If it is, then the user
> > supplied 'something' to you, no matter what its value is.
>
> Exactly, and if you use idiom func(*args, **kwargs) you can distinguish
> all the usage cases:
>
> >>> def func(*args, **kwargs):
> ... print(args, kwargs)
> ...
> >>> func()
> () {}
> >>> func(key='alabama')
> () {'key': 'alabama'}
> >>> func('alabama')
> ('alabama',) {}

Nice... but I would still like to be able to specify the key's default
value in the func signature, and in this case this would not be
possible:

>>> def func(key=None, *args, **kwargs):
.... print(key, args, kwargs)
....
>>> func()
(None, (), {})
>>> func(None)
(None, (), {})
>>> func(key=None)
(None, (), {})
>>>

I would still need an additional object, as Arnaud suggests.

mario

Bjoern Schliessmann

2/3/2008 12:35:00 PM

0

mario ruggier wrote:

> It may sometimes be useful to make use of the conceptual
> difference between these two cases, that is that in one case the
> user did not specify any key and in the other the user explicitly
> specified the key to be None.

Do you have an example where this might be useful?

> Is there any way to tell this difference from within the called
> function? And if so, would there be any strong reasons to not rely
> on this difference?

IMHO, it's "magic".

> Would it be maybe a little abusive of what a keyword arg actually
> is?

No, but you'd have to explain to users why it behaves like this. I
wouldn't expect this behaviour. If the function signature says the
default value for "key" is None, I expect it to behave the same no
matter if I leave out "key" or if I set it explicitly.

Regards,


Björn

--
BOFH excuse #307:

emissions from GSM-phones

Steve Holden

2/3/2008 2:33:00 PM

0

Bjoern Schliessmann wrote:
> mario ruggier wrote:
>
>> It may sometimes be useful to make use of the conceptual
>> difference between these two cases, that is that in one case the
>> user did not specify any key and in the other the user explicitly
>> specified the key to be None.
>
> Do you have an example where this might be useful?
>
Yes, a use case *would* be interesting.

>> Is there any way to tell this difference from within the called
>> function? And if so, would there be any strong reasons to not rely
>> on this difference?
>
> IMHO, it's "magic".
>
>> Would it be maybe a little abusive of what a keyword arg actually
>> is?
>
> No, but you'd have to explain to users why it behaves like this. I
> wouldn't expect this behaviour. If the function signature says the
> default value for "key" is None, I expect it to behave the same no
> matter if I leave out "key" or if I set it explicitly.
>
Well, quite: the whole point of a default is to provide a value to be
used when the caller doesn't explicitly provide one. The use of a
sentinel object() instance is the only sane way to perform this ever so
slightly insane task. If the argument value isn't the sentinel then the
function has to set it to the required default.

But this isn't the strict requirement as stated by the OP, of course,
who wants to be able to explicitly detect when the sentinel object is
passed in as an actual keyword (or positional) argument. I don't believe
that's possible without large amounts of heavyweight introspection.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.hold...

Diez B. Roggisch

2/3/2008 2:53:00 PM

0

Bjoern Schliessmann schrieb:
> mario ruggier wrote:
>
>> It may sometimes be useful to make use of the conceptual
>> difference between these two cases, that is that in one case the
>> user did not specify any key and in the other the user explicitly
>> specified the key to be None.
>
> Do you have an example where this might be useful?

Any situation in which there would otherwise lots of documentation
needed to inform the user that the sentinel value is something else than
None.

Take something like this as an example:

def update_user(some, values, nullable_value=sentinel):
# first, work with some and values
...
# then, on something actually being passed to nullable_value
if nullable_value is not sentinel:
connection.cursor().execute("update table set value = ?",
nullable_value)



I've seen this before, in code from e.g. Alex Martelli.

Diez

Steve Holden

2/3/2008 3:19:00 PM

0

Diez B. Roggisch wrote:
> Bjoern Schliessmann schrieb:
>> mario ruggier wrote:
>>
>>> It may sometimes be useful to make use of the conceptual
>>> difference between these two cases, that is that in one case the
>>> user did not specify any key and in the other the user explicitly
>>> specified the key to be None.
>> Do you have an example where this might be useful?
>
> Any situation in which there would otherwise lots of documentation
> needed to inform the user that the sentinel value is something else than
> None.
>
> Take something like this as an example:
>
> def update_user(some, values, nullable_value=sentinel):
> # first, work with some and values
> ...
> # then, on something actually being passed to nullable_value
> if nullable_value is not sentinel:
> connection.cursor().execute("update table set value = ?",
> nullable_value)
>
>
>
> I've seen this before, in code from e.g. Alex Martelli.
>
Sure, but the OP's question was "Is there any way to tell between
whether a keyword arg has been explicitly specified (to the same value
as the default for it)". We've drifted a long way from that, since the
code you demonstrate doesn't detect an explicit call with
nullable_value==sentinel -- the reason being, I submit, that there is no
use case for such code.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.hold...

mario

2/3/2008 3:42:00 PM

0

On Feb 3, 4:19 pm, Steve Holden <st...@holdenweb.com> wrote:
> Diez B. Roggisch wrote:
> > Bjoern Schliessmann schrieb:
> >> mario ruggier wrote:
>
> >>> It may sometimes be useful to make use of the conceptual
> >>> difference between these two cases, that is that in one case the
> >>> user did not specify any key and in the other the user explicitly
> >>> specified the key to be None.
> >> Do you have an example where this might be useful?
>
> > Any situation in which there would otherwise lots of documentation
> > needed to inform the user that the sentinel value is something else than
> > None.
>
> > Take something like this as an example:
>
> > def update_user(some, values, nullable_value=sentinel):
> > # first, work with some and values
> > ...
> > # then, on something actually being passed to nullable_value
> > if nullable_value is not sentinel:
> > connection.cursor().execute("update table set value = ?",
> > nullable_value)
>
> > I've seen this before, in code from e.g. Alex Martelli.
>
> Sure, but the OP's question was "Is there any way to tell between
> whether a keyword arg has been explicitly specified (to the same value
> as the default for it)". We've drifted a long way from that, since the
> code you demonstrate doesn't detect an explicit call with
> nullable_value==sentinel -- the reason being, I submit, that there is no
> use case for such code.

I think you are all very much on target, and not drifted at all. The
real issue with this situation is None, as there is ambiguity there,
whether a caller wants something to be None or whtehr it is simpy None
because it is not set...

My use case is that I have an object that is part of a collection. The
collection sets what the preferred defaults are for specific object
attributes, but individual objects may override some of these. Thus,
if an object does not set any of these attributes, then the default as
per the collection's settings is to be used.

In one case, the collection attributes a specific meaning to
attr=None, but the actual default for attr is something else. However,
if an object explicitly wants to state that his attr=None (that is a
valid value, and has specific meaning) I would like to use that as
value, but if no value is supplied for attr by the object, then I
would like to use the default value from the collection.

mario

Terry Reedy

2/3/2008 11:07:00 PM

0


"mario" <mario@ruggier.org> wrote in message
news:9d3145c0-1128-4f7e-a9b5-2789f9231f34@1g2000hsl.googlegroups.com...
| My use case is that I have an object that is part of a collection. The
| collection sets what the preferred defaults are for specific object
| attributes, but individual objects may override some of these. Thus,
| if an object does not set any of these attributes, then the default as
| per the collection's settings is to be used.
|
| In one case, the collection attributes a specific meaning to
| attr=None, but the actual default for attr is something else. However,
| if an object explicitly wants to state that his attr=None (that is a
| valid value, and has specific meaning) I would like to use that as
| value, but if no value is supplied for attr by the object, then I
| would like to use the default value from the collection.

In Python, a function parameter default value, in the narrow sense, is a
value (object) that you can and do calculate (construct) *when the function
is defined* (if necessary, with a helper function). If the 'default value'
cannot be calculated until later, then, for function definition purposes,
you only have a 'default behavior'.

If you have multiple optional keywords with default behaviors when they are
not specified, the usually mechanism is the **keywords mechanism. If you
have just one, that may seem like overkill and some people prefer the
pseudo-default or sentinal value approach given by Arnaud. The only change
I would make from his post is to add at least an underscore to the sentinal
name to indicate that it is private to the module and not for use of
importers (and excluded from 'import *').

tjr