Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #82286 > unrolled thread
| Started by | "ast" <nomail@invalid.com> |
|---|---|
| First post | 2014-12-10 16:14 +0100 |
| Last post | 2014-12-12 10:03 +1100 |
| Articles | 13 — 9 participants |
Back to article view | Back to comp.lang.python
How to detect that a function argument is the default one "ast" <nomail@invalid.com> - 2014-12-10 16:14 +0100
Re: How to detect that a function argument is the default one Skip Montanaro <skip.montanaro@gmail.com> - 2014-12-10 09:29 -0600
Re: How to detect that a function argument is the default one "ast" <nomail@invalid.com> - 2014-12-10 16:45 +0100
Re: How to detect that a function argument is the default one Marko Rauhamaa <marko@pacujo.net> - 2014-12-10 18:33 +0200
Re: How to detect that a function argument is the default one Chris Angelico <rosuav@gmail.com> - 2014-12-11 03:16 +1100
Re: How to detect that a function argument is the default one wxjmfauth@gmail.com - 2014-12-10 12:08 -0800
Re: How to detect that a function argument is the default one "ast" <nomail@invalid.com> - 2014-12-10 22:17 +0100
Re: How to detect that a function argument is the default one Ian Kelly <ian.g.kelly@gmail.com> - 2014-12-11 11:03 -0700
Re: How to detect that a function argument is the default one Ian Kelly <ian.g.kelly@gmail.com> - 2014-12-11 11:07 -0700
Re: How to detect that a function argument is the default one Ned Batchelder <ned@nedbatchelder.com> - 2014-12-10 11:19 -0500
Re: How to detect that a function argument is the default one Ian Kelly <ian.g.kelly@gmail.com> - 2014-12-10 09:20 -0700
Re: How to detect that a function argument is the default one Tony the Tiger <tony@tiger.invalid> - 2014-12-11 19:45 +0000
Re: How to detect that a function argument is the default one Ben Finney <ben+python@benfinney.id.au> - 2014-12-12 10:03 +1100
| From | "ast" <nomail@invalid.com> |
|---|---|
| Date | 2014-12-10 16:14 +0100 |
| Subject | How to detect that a function argument is the default one |
| Message-ID | <5488634e$0$2130$426a74cc@news.free.fr> |
Hello
Here is what I would like to implement
class Circle:
def __init__(center=(0,0), radius=10, mass=1)):
self.center = center
self.radius = radius
if "mass is the default one": <-----
self.mass = radius**2
else:
self.mass = mass
I cant just test if mass == 1: because if I call
C1 = Circle((0,0), 7, 1)
then in that case I want: self.mass = 1
If i call C2 = Circle((6,8), 8)
then in that case I want: self.mass = radius**2
I have the idea to write:
def __init__(center=(0,0), radius=10, mass=None)):
if mass == None:
self.mass = radius**2
else:
self.mass = mass
but maybe Python provides something clever.
Thx
[toc] | [next] | [standalone]
| From | Skip Montanaro <skip.montanaro@gmail.com> |
|---|---|
| Date | 2014-12-10 09:29 -0600 |
| Message-ID | <mailman.16809.1418225382.18130.python-list@python.org> |
| In reply to | #82286 |
On Wed, Dec 10, 2014 at 9:14 AM, ast <nomail@invalid.com> wrote:
> I have the idea to write:
>
> def __init__(center=(0,0), radius=10, mass=None)):
>
> if mass == None: self.mass = radius**2
> else:
> self.mass = mass
>
> but maybe Python provides something clever.
This is almost the correct idiom. In general, pick defaults from
values outside your valid domain. None is often perfect for
this. Since you're comparing to a singleton value, "is" is the usual
comparison, so your code becomes:
def __init__(center=(0,0), radius=10, mass=None)):
if mass is None:
self.mass = radius**2
else:
self.mass = mass
At the programming level, Python generally tries not to be too clever,
especially for real basic stuff. From the Zen of Python:
>>> import this
The Zen of Python, by Tim Peters
...
Explicit is better than implicit.
...
Guido could have been more clever here, but it wouldn't have likely
gained much (you'd still have to detect the default and set the value
appropriately), and perhaps made the code a (small) bit harder to
read.
Skip
[toc] | [prev] | [next] | [standalone]
| From | "ast" <nomail@invalid.com> |
|---|---|
| Date | 2014-12-10 16:45 +0100 |
| Message-ID | <54886aa0$0$2103$426a74cc@news.free.fr> |
| In reply to | #82287 |
"Skip Montanaro" <skip.montanaro@gmail.com> a écrit dans le message de news:mailman.16809.1418225382.18130.python-list@python.org... > On Wed, Dec 10, 2014 at 9:14 AM, ast <nomail@invalid.com> wrote: thx
[toc] | [prev] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2014-12-10 18:33 +0200 |
| Message-ID | <8761djjwgm.fsf@elektro.pacujo.net> |
| In reply to | #82287 |
Skip Montanaro <skip.montanaro@gmail.com>:
> On Wed, Dec 10, 2014 at 9:14 AM, ast <nomail@invalid.com> wrote:
>> I have the idea to write:
>>
>> def __init__(center=(0,0), radius=10, mass=None)):
>>
>> if mass == None: self.mass = radius**2
>> else:
>> self.mass = mass
>>
>> but maybe Python provides something clever.
>
> This is almost the correct idiom. In general, pick defaults from
> values outside your valid domain. None is often perfect for
> this. Since you're comparing to a singleton value, "is" is the usual
> comparison, so your code becomes:
>
> def __init__(center=(0,0), radius=10, mass=None)):
> if mass is None:
> self.mass = radius**2
> else:
> self.mass = mass
In this case, None works well. However, sometimes None is a valid input
value. Then, a sentinel object is the way out:
_OMITTED = object()
class SomeClass:
def __init__(self, center=(0,0), radius=10, mass=_OMITTED)):
if mass is _OMITTED:
self.mass = radius**2
else:
self.mass = mass
Marko
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-12-11 03:16 +1100 |
| Message-ID | <mailman.16814.1418228205.18130.python-list@python.org> |
| In reply to | #82286 |
On Thu, Dec 11, 2014 at 3:10 AM, Jean-Michel Pichavant <jeanmichel@sequans.com> wrote: > ----- Original Message ----- >> From: "ast" <nomail@invalid.com> >> I have the idea to write: >> >> def __init__(center=(0,0), radius=10, mass=None)): >> >> if mass == None: >> self.mass = radius**2 >> else: >> self.mass = mass >> >> but maybe Python provides something clever. >> >> Thx > > If you like one-liners, > > def __init__(self, center=(0,0), radius=10, mass=None): > self.center = center > self.radius = radius > self.mass = (mass is None and radius**2) or mass Leaving aside the obvious point that not everything needs to be a one-liner, there is a MUCH better way to spell this: the if/else ternary expression. self.mass = radius**2 if mass is None else mass > But there's an issue with that solution: self.mass being computed during the instance initialization, what if radius is changing ? > > c1 = Circle((0,0), 10, None) > print c1.mass > 20 > c1.radius = 20 > print c1.mass > 20 # that is unexpected > > Everytime an attribute is computed from another attribute, it should ring a python bell : property > > def __init__(self, center, radius, mass): > self.center = center > self.radius = radius > self._mass = mass > > @property > def mass(self): > return self._mass if self._mass is not None else self.radius*2 > > > c1 = Circle((0,0), 10, None) > print c1.mass > 20 > c1.radius = 20 > print c1.mass > 40 I think that juuuuuust miiiiight count as scope creep :) Though it does highlight an interesting point, namely that sometimes the state of "argument wasn't specified" needs to carry through into an object's "attribute wasn't specified". > Note : what is the mass of a circle ? Fortunately for us, this is a programming class, not a philosophical one. Maybe the circles in question are being cast in steel? :) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | wxjmfauth@gmail.com |
|---|---|
| Date | 2014-12-10 12:08 -0800 |
| Message-ID | <088efe53-3178-4f45-9be5-9d55fa96f1ff@googlegroups.com> |
| In reply to | #82293 |
Le mercredi 10 décembre 2014 17:17:03 UTC+1, Chris Angelico a écrit : > > Fortunately for us, this is a programming class, not a philosophical > one. Maybe the circles in question are being cast in steel? :) > I belong to those, who think thid kind of stuff is important. (I wrote enough simulation programs in the field of quantum chemistry to know how this kind of clarity is very relevant). self.mass [kg] =? radius ** 2 [m²] Today, there are people who are confusing character and code point... jmf
[toc] | [prev] | [next] | [standalone]
| From | "ast" <nomail@invalid.com> |
|---|---|
| Date | 2014-12-10 22:17 +0100 |
| Message-ID | <5488b874$0$2890$426a34cc@news.free.fr> |
| In reply to | #82293 |
"Chris Angelico" <rosuav@gmail.com> a écrit dans le message de news:mailman.16814.1418228205.18130.python-list@python.org... > On Thu, Dec 11, 2014 at 3:10 AM, Jean-Michel Pichavant > <jeanmichel@sequans.com> wrote: >> ----- Original Message ----- >>> From: "ast" <nomail@invalid.com> >> But there's an issue with that solution: self.mass being computed >> during the instance initialization, what if radius is changing ? You are going to laught because i had that bug ... LOL >> Everytime an attribute is computed from another attribute, it should ring a python bell : >> property yes > >> Note : what is the mass of a circle ? > In fact it's a ball moving in a plan. I will change that name.
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2014-12-11 11:03 -0700 |
| Message-ID | <mailman.16860.1418321042.18130.python-list@python.org> |
| In reply to | #82310 |
[Multipart message — attachments visible in raw view] — view raw
On Thu, Dec 11, 2014 at 3:02 AM, Jean-Michel Pichavant < jeanmichel@sequans.com> wrote: > I would advise to remove the the mass parameter of your Sphere initialization. It could be inconsistent with the radius. > To compute the mass you would need the radius and the volumetric mass density. You assume a three-dimensional universe. Clearly this is a two-dimensional "ball" with a density equal to pi/2 mass units per area unit.
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2014-12-11 11:07 -0700 |
| Message-ID | <mailman.16861.1418321314.18130.python-list@python.org> |
| In reply to | #82310 |
[Multipart message — attachments visible in raw view] — view raw
On Thu, Dec 11, 2014 at 11:03 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote: > > On Thu, Dec 11, 2014 at 3:02 AM, Jean-Michel Pichavant < jeanmichel@sequans.com> wrote: > > I would advise to remove the the mass parameter of your Sphere initialization. It could be inconsistent with the radius. > > To compute the mass you would need the radius and the volumetric mass density. > > You assume a three-dimensional universe. Clearly this is a two-dimensional "ball" with a density equal to pi/2 mass units per area unit. Er. 2/pi.
[toc] | [prev] | [next] | [standalone]
| From | Ned Batchelder <ned@nedbatchelder.com> |
|---|---|
| Date | 2014-12-10 11:19 -0500 |
| Message-ID | <mailman.16815.1418228392.18130.python-list@python.org> |
| In reply to | #82286 |
On 12/10/14 11:10 AM, Jean-Michel Pichavant wrote:
> self.mass = (mass is None and radius**2) or mass
When will this idiom die? We've had actual if-expressions for a while now:
self.mass = radius**2 if mass is None else mass
--
Ned Batchelder, http://nedbatchelder.com
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2014-12-10 09:20 -0700 |
| Message-ID | <mailman.16816.1418228498.18130.python-list@python.org> |
| In reply to | #82286 |
[Multipart message — attachments visible in raw view] — view raw
On Wed, Dec 10, 2014 at 9:10 AM, Jean-Michel Pichavant < jeanmichel@sequans.com> wrote: > If you like one-liners, > > def __init__(self, center=(0,0), radius=10, mass=None): > self.center = center > self.radius = radius > self.mass = (mass is None and radius**2) or mass If mass is None and radius is 0, then self.mass gets set to None. Use the actual ternary operator instead.
[toc] | [prev] | [next] | [standalone]
| From | Tony the Tiger <tony@tiger.invalid> |
|---|---|
| Date | 2014-12-11 19:45 +0000 |
| Message-ID | <5489f45d$0$53762$c3e8da3$3304c218@news.astraweb.com> |
| In reply to | #82286 |
On Wed, 10 Dec 2014 16:14:17 +0100, ast wrote:
> def __init__(center=(0,0), radius=10, mass=1)):
> self.center = center self.radius = radius
>
> if "mass is the default one": <-----
> self.mass = radius**2
How about:
radius='10', mass='1'
if radius == '10' ...
if mass == '1' ...
You could do int(radius) and int(mass) right after, or float().
/Grrr
--
___ ___
(\_--_/) | _ ._ _|_|_ _ |o _ _ ._
( 9 9 ) |(_)| |\/ |_| |(/_ ||(_|(/_|
stripes are forever - as overripe ferrets
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2014-12-12 10:03 +1100 |
| Message-ID | <mailman.16879.1418339026.18130.python-list@python.org> |
| In reply to | #82392 |
Tony the Tiger <tony@tiger.invalid> writes:
> radius='10', mass='1'
>
> if radius == '10' ...
>
> if mass == '1' ...
This ignores the problem as stated: The OP wants to distinguish between
a value that was explicitly set by the caller, versus a value that was
set by default because the caller did not specify the parameter.
The general solution to this is to choose a value outside the domain, a
<URL:https://en.wikipedia.org/wiki/Sentinel_value> which is different
from any value the caller would choose for that parameter.
Often, the Python singleton ‘None’ is good for the purpose. I think in
this case, where the domain is numeric, a default of ‘None’ would do
fine.
class Foo:
def __init__(centre=(0, 0), radius=None, mass=None):
if radius is None:
# Caller didn't specify. Set a default value.
radius = 10
if mass is None:
# Caller didn't specify. Set a default value.
mass = 1
self.centre = centre
self.radius = radius
self.mass = mass
In some other cases, ‘None’ is a valid value for the caller to set, and
so cannot be used as a sentinel to distinguish the default. For those
cases, creating a specific object instance to serve as the sentinel is
simple and clear:
class Foo:
_SENTINEL = object()
def __init__(centre=(0, 0), radius=_SENTINEL, mass=_SENTINEL):
if radius is _SENTINEL:
# Caller didn't specify. Set a default value.
radius = 10
if mass is _SENTINEL:
# Caller didn't specify. Set a default value.
mass = 1
self.centre = centre
self.radius = radius
self.mass = mass
Creating a new object specifically for the sentinel means there is no
chance some other value will compare identical. Choosing a
leading-underscore name indicates to the reader that this is not part of
the public API.
--
\ “Odious ideas are not entitled to hide from criticism behind |
`\ the human shield of their believers' feelings.” —Richard M. |
_o__) Stallman |
Ben Finney
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web