Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Usefulness of the "not in" operator

105 views
Skip to first unread message

candide

unread,
Oct 8, 2011, 6:42:58 AM10/8/11
to
Python provides

-- the not operator, meaning logical negation
-- the in operator, meaning membership

On the other hand, Python provides the not in operator meaning
non-membership. However, it seems we can reformulate any "not in"
expression using only "not" and "in" operation. For instance

>>> 'th' not in "python"
False

>>> not ('th' in "python")
False
>>>


So what is the usefulness of the "not in" operator ? Recall what Zen of
Python tells

There should be one-- and preferably only one --obvious way to do it.

Jon Clements

unread,
Oct 8, 2011, 6:50:00 AM10/8/11
to

You would seriously prefer the later?

Guess I'll have to start writing stuff like:

10 - 5 as 10 + -5 (as obviously the - is redundant as an operation),
and 10 / 2 as int(10 * .5) or something, who needs a divide!?

Jokely yours,

Jon.

Stefaan Himpe

unread,
Oct 8, 2011, 7:12:42 AM10/8/11
to

>
> So what is the usefulness of the "not in" operator ? Recall what Zen of
> Python tells
>
> There should be one-- and preferably only one --obvious way to do it.

the zen of python also says (amongst other things):

...
Readability counts.
...
Although practicality beats purity
...

Best regards,
Stefaan.

Steven D'Aprano

unread,
Oct 8, 2011, 8:01:05 AM10/8/11
to
candide wrote:

> So what is the usefulness of the "not in" operator ? Recall what Zen of
> Python tells
>
> There should be one-- and preferably only one --obvious way to do it.

And "not in" is the obvious way to do it.


"If the key is not in the ignition, you won't be able to start the car."

"If not the key is in the ignition, you won't be able to start the car."


Who like that second one speaks?


--
Steven

Alain Ketterlin

unread,
Oct 8, 2011, 8:41:06 AM10/8/11
to
candide <can...@free.invalid> writes:

> Python provides
>
> -- the not operator, meaning logical negation
> -- the in operator, meaning membership
>
> On the other hand, Python provides the not in operator meaning
> non-membership. However, it seems we can reformulate any "not in"
> expression using only "not" and "in" operation.

Sure, but note that you can also reformulate != using not and ==, <
using not and >=, etc. Operators like "not in" and "is not" should
really be considered single tokens, even though they seem to use "not".
And I think they are really convenient.

-- Alain.

Mel

unread,
Oct 8, 2011, 8:41:35 AM10/8/11
to
Steven D'Aprano wrote:

:)
"If the key is not in the ignition, you will be able to start the car, not."

Mel.

Jussi Piitulainen

unread,
Oct 8, 2011, 9:07:12 AM10/8/11
to
Mel writes:

Oh, be consistent.

"If not the key is in the ignition, not you will be able to start the car."

But both negations can be avoided by modus tollens.

"If you are able to start the car, the key is in the ignition."

And one could express "x not in s" as "(x in s) implies False" without
making the "not" explicit if "implies" was in the language. (I know
about <= but I also witnessed an unpleasant thread in another
newsgroup where people insisted that <= should not be defined for
truth values at all, and I also happen to like Python's "not in".)

Roy Smith

unread,
Oct 8, 2011, 9:31:10 AM10/8/11
to
In article <87ehyn8...@dpt-info.u-strasbg.fr>,
Alain Ketterlin <al...@dpt-info.u-strasbg.fr> wrote:

> Sure, but note that you can also reformulate != using not and ==, <
> using not and >=, etc. Operators like "not in" and "is not" should
> really be considered single tokens, even though they seem to use "not".
> And I think they are really convenient.

If you want to take it one step further, all the boolean operators can
be derived from nand (the dualists would insist on using nor).

candide

unread,
Oct 8, 2011, 10:40:58 AM10/8/11
to
Le 08/10/2011 14:41, Alain Ketterlin a écrit :

> Operators like "not in" and "is not" should
> really be considered single tokens, even though they seem to use "not".
> And I think they are really convenient.

I realize that I was confused by the lexical form of the "not in"
operator : it is made by juxtaposing two other operators. Operators
composed from two other operators exist, for instance != but the two
cannot be separated, for instance

2 ! = 3

is not a valid expression. Said in another way, in Python syntax,
usually a "lexically juxtaposed operator" is seen as a whole. This is
not the case for an operator such as "is not" or "not in" because for
example

>>> 2 is not 3

is a valid statement.

A notin operator or isnot operator would be less confusing (at least in
my case ;) ).

candide

unread,
Oct 8, 2011, 10:41:11 AM10/8/11
to
Le 08/10/2011 12:42, candide a �crit :


> >>> not ('th' in "python")
> False
> >>>

After browsing source code, I realize that parenthesis are not necessary
("not" has higher precedence than "in").

candide

unread,
Oct 8, 2011, 10:41:43 AM10/8/11
to
Le 08/10/2011 12:50, Jon Clements a �crit :

> 10 - 5 as 10 + -5 (as obviously the - is redundant as an operation),
> and 10 / 2 as int(10 * .5) or something, who needs a divide!?

OK, I see your point but I was supposing non-membershipness seldom
needed and in fact one can suppose that test membership is heavily more
used than test non-membership.

In fact, it seems that most Python operators have an "antonym" operator,
for instance :

== vs !=
< vs >=
is vs is not
+ vs -

etc

candide

unread,
Oct 8, 2011, 10:41:51 AM10/8/11
to
Le 08/10/2011 14:01, Steven D'Aprano a �crit :

> And "not in" is the obvious way to do it.
>
>

Obvious ? Not so. I performed some code mining and it appears that even
good sources make use of "not (foo in bar)" expressions.


******** begin examples ***************

from drpython/drPluginDialog.py
-----------------------------
if not (plugin in self.parent.pluginstoremove):


from numpy/f2py/crackfortran.py
-------------------------------
if not (l[0] in spacedigits):


from crunchy1.0alpha1/crunchy/src/plugins/vlam_editor.py
----------------------------------------------------------
if (("no_copy" in vlam) and not ("no_pre" in vlam)) or (not python_code):


from Cpython/Python-3.1a1/Lib/logging/__init__.py
--------------------------------------------------
if not (hdlr in self.handlers):

from Cpython/Python-2.6.2/Lib/idlelib/configHandler.py
-------------------------------------------------------
if not (configType in ('main','extensions','highlight','keys')):
raise InvalidConfigType, 'Invalid configType specified'

from
pygtk-2.22.0/gtk/webkitgtk/WebKit-r93015/Source/JavaScriptCore/KeywordLookupGenerator.py
---------------------------------------------------------------------------------------------
if not (key[0] in self.keys):

from pypy/pypy-pypy-release-1.6/lib-python/2.7/logging/__init__.py
------------------------------------------------------------------
if not (hdlr in self.handlers):

******** end examples ***************

_Many_ more examples of this type are avalaible.

The obviousness of an "is not" operator is very debatable. Do you have
standard functions or method such as
isnotinstance, isnotsubset, isnotdir, isnotfile, isnotalpha, etc ?

In my case, It took a long time to realize the existence of a "true"
"not in" operator as I explain in my response to Alain.


Imagine, /Dive Into Python/ book doesn't describe this operator per se
and provides only one source file using it. Official Python tutorial at
python.org didn't provide even one.

> "If the key is not in the ignition, you won't be able to start the car."
>
> "If not the key is in the ignition, you won't be able to start the car."
>
>
> Who like that second one speaks?
>


Depends if you are aware of negative form conjugation.


Chris Angelico

unread,
Oct 8, 2011, 10:51:03 AM10/8/11
to pytho...@python.org
On Sun, Oct 9, 2011 at 1:40 AM, candide <can...@free.invalid> wrote:
> A notin operator or isnot operator would be less confusing (at least in my
> case ;) ).
>

Let's replace both of them.

in --> foo extant bar
not in --> foo extinct bar

That would solve the problem, wouldn't it?

*ducking for cover*

ChrisA

Thorsten Kampe

unread,
Oct 8, 2011, 11:13:18 AM10/8/11
to
* candide (Sat, 08 Oct 2011 16:41:11 +0200)

> After browsing source code, I realize that parenthesis are not
> necessary ("not" has higher precedence than "in").

Lower precedence.

Thorsten

Dave Angel

unread,
Oct 8, 2011, 11:16:54 AM10/8/11
to candide, pytho...@python.org
On 01/-10/-28163 02:59 PM, candide wrote:
> Le 08/10/2011 12:42, candide a écrit :
>
>
>> >>> not ('th' in "python")
>> False
>> >>>
>
>
>
> After browsing source code, I realize that parenthesis are not
> necessary ("not" has higher precedence than "in").
>
You should say
"... parenthesis are not necessary ("not" has LOWER precedence than
"in")."

--

DaveA

candide

unread,
Oct 8, 2011, 11:18:23 AM10/8/11
to
Le 08/10/2011 17:13, Thorsten Kampe a �crit :

Ooops, thanks.

Chris Angelico

unread,
Oct 8, 2011, 11:20:01 AM10/8/11
to pytho...@python.org
On Sun, Oct 9, 2011 at 2:16 AM, Dave Angel <d...@davea.name> wrote:
> You should say

>    "... parenthesis are not necessary ("not" has LOWER precedence than
> "in")."
>

Is "are not" an operator in English, or should this be "not
parentheses are necessary"?

ChrisA

Grant Edwards

unread,
Oct 8, 2011, 11:28:17 AM10/8/11
to

Yoda.

--
Grant Edwards grant.b.edwards Yow! ... I don't like FRANK
at SINATRA or his CHILDREN.
gmail.com

candide

unread,
Oct 8, 2011, 12:05:08 PM10/8/11
to
Le 08/10/2011 17:16, Dave Angel a �crit :

> You should say
> "... parenthesis are not necessary ("not" has LOWER precedence than "in")."
>


I should, yes, I confess ;)


In my defense, I must tell that Python document reference here :

http://docs.python.org/reference/expressions.html#summary


has an anti-iconic way to display the order precedence.


If an operator OP1 has higher precedence than an operator OP2 , it means
that, at evaluation time, you execute OP1 FIRST and operator OP2 later.
So, its seems very natural to present FIRST operator with stronger
precedence.


So, if you iconically present this material in a tabular display, you
present FIRST (ie at the top because usually we process tabular material
starting on the upper part) what you need to calculate FIRST and, again,
you present

at the TOP the HIGHer precedence

and

at the BOTTOM the LOWer precedence.

Documentations usually provide the table in this order (higher to
lower), cf. the table in K&R book for C programing language or here for
the C++ PL :

http://en.cppreference.com/w/cpp/language/operator_precedence

or again there for the Java PL :

http://download.oracle.com/javase/tutorial/java/nutsandbolts/operators.html


Steven D'Aprano

unread,
Oct 8, 2011, 12:08:35 PM10/8/11
to
Roy Smith wrote:

> If you want to take it one step further, all the boolean operators can
> be derived from nand (the dualists would insist on using nor).

Let's define the boolean values and operators using just two functions:

def true(x, y):
return x

def false(x, y):
return y


That's all we need to define all of Boolean algebra. Unfortunately, it's a
bit ugly in Python:

>>> true
<function true at 0xb7c3a36c>

So let's add a helper function to prettify the output:

def pr(b):
print(b(true, false).__name__)

>>> pr(true)
true

Much nicer!


Now define NAND:

def Nand(a, b):
return (lambda c: lambda x, y: c(y, x))(a(b, a))


and we're done. All of boolean algebra can now be derived from Nand.


>>> def Not(b):
... return Nand(b, b)
...
>>> pr(Not(true))
false
>>> pr(Not(false))
true


>>> def And(a, b):
... return Nand(Nand(a, b), Nand(a, b))
...
>>> pr(And(true, false))
false
>>> pr(And(true, true))
true


>>> def Or(a, b):
... return Nand(Nand(a, a), Nand(b, b))
...
>>> pr(Or(true, false))
true
>>> pr(Or(false, false))
false


>>> def Xor(a, b):
... return And(Nand(a, b), Or(a, b))
...
>>> pr(Xor(true, false))
true
>>> pr(Xor(true, true))
false


and so forth.

--
Steven

Steven D'Aprano

unread,
Oct 8, 2011, 12:18:36 PM10/8/11
to
candide wrote:

> Le 08/10/2011 14:01, Steven D'Aprano a écrit :
>
> > And "not in" is the obvious way to do it.
>
> Obvious ? Not so. I performed some code mining and it appears that even
> good sources make use of "not (foo in bar)" expressions.

All that proves is that even expert Python developers can, on occasion,
write non-idiomatic Python -- or that they accept code contributed by
non-expert Python developers, and don't bother adjusting trivial stylistic
flaws.

When I learned Pascal 20+ years ago, it took me a long time to stop
writing "x not in y" and learn the non-English-like "not x in y". Then I
learned Python, and it took me a while to stop writing Pascal code in
Python. Bad habits take a while to disappear.

(I never added superfluous semi-colons after each line though!)



--
Steven

rusi

unread,
Oct 8, 2011, 12:31:59 PM10/8/11
to
On Oct 8, 6:31 pm, Roy Smith <r...@panix.com> wrote:
> In article <87ehyn8xlp....@dpt-info.u-strasbg.fr>,
^^^^^^^^^^^^
????

Roy Smith

unread,
Oct 8, 2011, 12:34:42 PM10/8/11
to
In article <4e906108$0$27980$426a...@news.free.fr>,
candide <can...@free.invalid> wrote:

> After browsing source code, I realize that parenthesis are not necessary
> ("not" has higher precedence than "in").

Here's my take on parenthesis: If you need to look up whether they're
necessary or not, they are :-)

Chris Angelico

unread,
Oct 8, 2011, 12:43:31 PM10/8/11
to pytho...@python.org
On Sun, Oct 9, 2011 at 3:31 AM, rusi <rusto...@gmail.com> wrote:
>> If you want to take it one step further, all the boolean operators can
>> be derived from nand (the dualists would insist on using nor).
>                        ^^^^^^^^^^^^
> ????
>

I'm not sure what you're questioning, but it's possible to derive all
boolean operators from either nand or nor. Most hardware these days is
built out of silicon NAND gates, but there's no reason not to do it as
NOR gates.

ChrisA

Roy Smith

unread,
Oct 8, 2011, 12:44:35 PM10/8/11
to
In article
<acd018ad-8428-4c3d...@x31g2000prd.googlegroups.com>,
rusi <rusto...@gmail.com> wrote:

Dualist (noun): a made up word referring to wrong-thinking people who
have rejected the teachings of the Prophet Nand and believe the nor is
the One True Operation on which all over operations can be constructed.

Tim Roberts

unread,
Oct 8, 2011, 7:35:50 PM10/8/11
to

Amen. +1
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Alexander Kapps

unread,
Oct 8, 2011, 8:17:53 PM10/8/11
to pytho...@python.org
On 09.10.2011 01:35, Tim Roberts wrote:
> Roy Smith<r...@panix.com> wrote:
>> In article<4e906108$0$27980$426a...@news.free.fr>,
>> candide<can...@free.invalid> wrote:
>>
>>> After browsing source code, I realize that parenthesis are not necessary
>>> ("not" has higher precedence than "in").
>>
>> Here's my take on parenthesis: If you need to look up whether they're
>> necessary or not, they are :-)
>
> Amen. +1

So LISP (Lots of Irritating Superfluous Parentheses) was right all
the time and is now finally vindicated? ;-)

Chris Angelico

unread,
Oct 8, 2011, 9:29:45 PM10/8/11
to pytho...@python.org
I sent this email twelve hours ago but to the wrong mailing list
*blush*. Since nobody else has raised the point, I'll repost it.

On Sun, Oct 9, 2011 at 12:07 AM, Jussi Piitulainen
<jpii...@ling.helsinki.fi> wrote:
> But both negations can be avoided by modus tollens.
>
> "If you are able to start the car, the key is in the ignition."
>

But this translation implies looking at the result and ascertaining
the state, which is less appropriate to a programming language. It's
more like:

"If you found that you were able to start the car, the key must have
been in the ignition."

and is thus quite inappropriate to the imperative style. A functional
language MAY be able to use this style, but Python wants to have the
condition and then the action.

ChrisA

Roy Smith

unread,
Oct 8, 2011, 9:41:03 PM10/8/11
to
In article <mailman.1841.1318123...@python.org>,
Chris Angelico <ros...@gmail.com> wrote:

The key is in the ignition if you are able to start the car else you
hot-wired it.

Albert van der Horst

unread,
Oct 9, 2011, 12:33:37 PM10/9/11
to
In article <qotr52n...@ruuvi.it.helsinki.fi>,

Jussi Piitulainen <jpii...@ling.helsinki.fi> wrote:
>Mel writes:
>
>> Steven D'Aprano wrote:
>>
>> > candide wrote:
>> >
>> >> So what is the usefulness of the "not in" operator ? Recall what Zen of
>> >> Python tells
>> >>
>> >> There should be one-- and preferably only one --obvious way to do it.
>> >
>> > And "not in" is the obvious way to do it.
>> >
>> >
>> > "If the key is not in the ignition, you won't be able to start the car."
>> >
>> > "If not the key is in the ignition, you won't be able to start the car."
>> >
>> >
>> > Who like that second one speaks?
>>
>> :)
>> "If the key is not in the ignition, you will be able to start the car, not."
>
>Oh, be consistent.
>
>"If not the key is in the ignition, not you will be able to start the car."
>
>But both negations can be avoided by modus tollens.
>
>"If you are able to start the car, the key is in the ignition."

This is not normal speach. The connotation of an if sentence is
that the condition is something you have more control over
than over the result.

I sometime write
if 0 == i :
and get complaints, as if both sides of an identity are not
equivalent.
OTOH
if i == j :
and nobody cares it I wrote
if j == i :

>
>And one could express "x not in s" as "(x in s) implies False" without
>making the "not" explicit if "implies" was in the language. (I know
>about <= but I also witnessed an unpleasant thread in another
>newsgroup where people insisted that <= should not be defined for
>truth values at all, and I also happen to like Python's "not in".)

Groetjes Albert


--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

Westley Martínez

unread,
Oct 9, 2011, 4:48:14 PM10/9/11
to pytho...@python.org

So we don't need precedence charts in the bathroom?

Alexander Kapps

unread,
Oct 8, 2011, 8:25:27 PM10/8/11
to pytho...@python.org
On 08.10.2011 18:08, Steven D'Aprano wrote:

> Let's define the boolean values and operators using just two functions:

[SNIP]

Have you just explained Church booleans in an understandable
language? Awesome. I still have to chew on this, but I think this is
the first time where I might understand it. Thanks!

Even if it's off-topic, could you add some similar explanations for
Church numerals (maybe Lambda calculus it isn't too much?)

John Ladasky

unread,
Oct 10, 2011, 4:06:40 AM10/10/11
to
On Oct 8, 5:01 am, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:

> Who like that second one speaks?

Yoda his name is. Programs in Forth he must.

Alec Taylor

unread,
Oct 10, 2011, 8:16:55 AM10/10/11
to Steven D'Aprano, pytho...@python.org

Alain Ketterlin

unread,
Oct 10, 2011, 9:01:16 AM10/10/11
to
Alec Taylor <alec.t...@gmail.com> writes:

> On Sun, Oct 9, 2011 at 3:08 AM, Steven D'Aprano
> <steve+comp....@pearwood.info> wrote:

>> def true(x, y):
>>    return x
>>
>> def false(x, y):
>>    return y

[...]


>> def Nand(a, b):
>>    return (lambda c: lambda x, y: c(y, x))(a(b, a))
>>

>> and we're done. [...]

> Awesome

Yes, that's how Church defined booleans in the lambda calculus. See
http://en.wikipedia.org/wiki/Church_encoding for encodings of natural
numbers and lists.

-- Alain.

Alec Taylor

unread,
Oct 10, 2011, 9:36:25 AM10/10/11
to Alain Ketterlin, pytho...@python.org
Unfortunately I don't know lambda [or for that matter, regular] calculus...
> --
> http://mail.python.org/mailman/listinfo/python-list
>

candide

unread,
Oct 10, 2011, 9:58:01 AM10/10/11
to
Le 10/10/2011 10:06, John Ladasky a �crit :

>> Who like that second one speaks?
>
> Yoda his name is. Programs in Forth he must.


;)


We can add to the list :

-- Tarzan
-- Geronimo
-- don Alexandro de la Vega dying in the arms of Zorro
...

Nobody

unread,
Oct 10, 2011, 1:29:49 PM10/10/11
to
On Sun, 09 Oct 2011 02:25:27 +0200, Alexander Kapps wrote:

> Even if it's off-topic, could you add some similar explanations for
> Church numerals (maybe Lambda calculus it isn't too much?)

The Church numeral for N is a function of two arguments which applies its
first argument N times to its second, i.e. (f^N)(x) = f(f(...(f(x))...)).

IOW:

def zero(f, x):
return x

def one(f, x):
return f(x)

def two(f, x):
return f(f(x))

def three(f, x):
return f(f(f(x)))

And so on.

In general:

def applyN(n, f, x):
for i in xrange(n):
x = f(x)
return x

def church(n):
return lambda f, x: applyN(n, f, x)

seven = church(7) # this is the Church numeral for 7

> seven(lambda x: x + 1, 0)
7
> seven(lambda x: x * 2, 1)
128
> seven(lambda x: x + ".", "")
'.......'


Chris Angelico

unread,
Oct 10, 2011, 1:33:43 PM10/10/11
to pytho...@python.org
On Tue, Oct 11, 2011 at 4:29 AM, Nobody <nob...@nowhere.com> wrote:
>
> The Church numeral for N is a function of two arguments which applies its
> first argument N times to its second, i.e. (f^N)(x) = f(f(...(f(x))...)).
>

Thanks - nice clear explanation. Appreciated. For an encore, can you
give an example of where this is actually useful? It seems a pretty
narrow utility.

ChrisA

Ian Kelly

unread,
Oct 10, 2011, 1:55:37 PM10/10/11
to Chris Angelico, pytho...@python.org
On Mon, Oct 10, 2011 at 11:33 AM, Chris Angelico <ros...@gmail.com> wrote:
> On Tue, Oct 11, 2011 at 4:29 AM, Nobody <nob...@nowhere.com> wrote:
>>
>> The Church numeral for N is a function of two arguments which applies its
>> first argument N times to its second, i.e. (f^N)(x) = f(f(...(f(x))...)).
>>
>
> Thanks - nice clear explanation. Appreciated. For an encore, can you
> give an example of where this is actually useful? It seems a pretty
> narrow utility.

It's useful for writing mathematical theorems about computability with
regard to the natural numbers using lambda calculus.

Terry Reedy

unread,
Oct 10, 2011, 3:35:24 PM10/10/11
to pytho...@python.org
On 10/10/2011 1:55 PM, Ian Kelly wrote:
> On Mon, Oct 10, 2011 at 11:33 AM, Chris Angelico<ros...@gmail.com> wrote:
>> On Tue, Oct 11, 2011 at 4:29 AM, Nobody<nob...@nowhere.com> wrote:
>>>
>>> The Church numeral for N is a function of two arguments which applies its
>>> first argument N times to its second, i.e. (f^N)(x) = f(f(...(f(x))...)).
>>>
>>
>> Thanks - nice clear explanation. Appreciated. For an encore, can you
>> give an example of where this is actually useful? It seems a pretty
>> narrow utility.
>
> It's useful for writing mathematical theorems about computability with
> regard to the natural numbers using lambda calculus.

Whereas pure set theorists define counts as sets so they can work with
counts within the context of pure set theory (in which everything is a
set). Other mathematicians use an axiomatic definition which pretty much
abstracts the common features of the set and function definitions.

--
Terry Jan Reedy

Tim Roberts

unread,
Oct 11, 2011, 1:50:39 AM10/11/11
to
Yes, we do, because I'm always reading code from other people that didn't
follow that rule.

Steven D'Aprano

unread,
Oct 11, 2011, 2:44:31 AM10/11/11
to
Tim Roberts wrote:

> Westley Martínez <anik...@gmail.com> wrote:
>>On Sat, Oct 08, 2011 at 12:34:42PM -0400, Roy Smith wrote:
>>>
>>> Here's my take on parenthesis: If you need to look up whether they're
>>> necessary or not, they are :-)
>>
>>So we don't need precedence charts in the bathroom?
>
> Yes, we do, because I'm always reading code from other people that didn't
> follow that rule.

No no no, they *do* follow the rule. They just have a better memory for
operator precedence than you do :)


--
Steven

Nobody

unread,
Oct 11, 2011, 4:28:51 AM10/11/11
to
On Tue, 11 Oct 2011 04:33:43 +1100, Chris Angelico wrote:

>> The Church numeral for N is a function of two arguments which applies its
>> first argument N times to its second, i.e. (f^N)(x) = f(f(...(f(x))...)).
>>
>
> Thanks - nice clear explanation. Appreciated. For an encore, can you
> give an example of where this is actually useful? It seems a pretty
> narrow utility.

It's useful insofar as it allows you to define "numbers" given nothing
other than abstraction and application, which are the only operations
available in the lambda calculus.

The particular formulation makes it easy to define addition, which is
just composition:

(f^(M+N))(x) = (f^M)((f^N)(x))

I.e.:

def church_add(a, b):
return lambda f, x: a(f, b(f, x))

Chris Angelico

unread,
Oct 11, 2011, 4:46:58 AM10/11/11
to pytho...@python.org
On Tue, Oct 11, 2011 at 7:28 PM, Nobody <nob...@nowhere.com> wrote:
> It's useful insofar as it allows you to define "numbers" given nothing
> other than abstraction and application, which are the only operations
> available in the lambda calculus.
>

Heh. This is why mathematicians ALWAYS make use of previously-defined
objects! In pure lambda calculus, constants are even more painful than
in SPL[1]...

ChrisA
[1] http://shakespearelang.sourceforge.net/report/shakespeare/shakespeare.html#SECTION00045000000000000000

Alec Taylor

unread,
Oct 11, 2011, 8:11:10 AM10/11/11
to Chris Angelico, pytho...@python.org
As you see, this way of writing constants gives you much more poetic
freedom than in other programming languages.

On Tue, Oct 11, 2011 at 7:46 PM, Chris Angelico <ros...@gmail.com> wrote:
> On Tue, Oct 11, 2011 at 7:28 PM, Nobody <nob...@nowhere.com> wrote:

>> It's useful insofar as it allows you to define "numbers" given nothing
>> other than abstraction and application, which are the only operations
>> available in the lambda calculus.
>>
>

> Heh. This is why mathematicians ALWAYS make use of previously-defined
> objects! In pure lambda calculus, constants are even more painful than
> in SPL[1]...
>
> ChrisA
> [1] http://shakespearelang.sourceforge.net/report/shakespeare/shakespeare.html#SECTION00045000000000000000

> --
> http://mail.python.org/mailman/listinfo/python-list
>

Jussi Piitulainen

unread,
Oct 13, 2011, 4:19:16 AM10/13/11
to
Chris Angelico writes:

> On Sun, Oct 9, 2011 at 12:07 AM, Jussi Piitulainen wrote:
> > But both negations can be avoided by modus tollens.
> >
> > "If you are able to start the car, the key is in the ignition."
>
> But this translation implies looking at the result and ascertaining
> the state, which is less appropriate to a programming language. It's
> more like:
>
> "If you found that you were able to start the car, the key must have
> been in the ignition."
>
> and is thus quite inappropriate to the imperative style. A
> functional language MAY be able to use this style, but Python wants
> to have the condition and then the action.

This is not in an imperative context. The context is (generalized)
Boolean expressions, where there should not be any action, just
expressions returning values that are combined to produce a
(generalized) Boolean value.

Defined order of evaluation and short-circuiting complicate the
picture, but as a matter of style, I think there should not be any
action part in such an expression. Usually.

And "not in" is fine as far as I am concerned.

Alexander Kapps

unread,
Oct 15, 2011, 3:48:54 PM10/15/11
to pytho...@python.org
On 10.10.2011 19:29, Nobody wrote:
> On Sun, 09 Oct 2011 02:25:27 +0200, Alexander Kapps wrote:
>
>> Even if it's off-topic, could you add some similar explanations for
>> Church numerals (maybe Lambda calculus it isn't too much?)
>
> The Church numeral for N is a function of two arguments which applies its
> first argument N times to its second, i.e. (f^N)(x) = f(f(...(f(x))...)).

[SNIP]

Thanks! That's a lot more understandable than Wikipedia. Some
brain-food for the winter. ;-)

DevPlayer

unread,
Oct 15, 2011, 6:04:24 PM10/15/11
to
On Oct 8, 8:41 am, Alain Ketterlin <al...@dpt-info.u-strasbg.fr>
wrote:
> candide <cand...@free.invalid> writes:
> > Python provides
>
> >     -- the not operator, meaning logical negation
> >     -- the in operator, meaning membership
>
> > On the other hand, Python provides the not in operator meaning
> > non-membership. However, it seems we can reformulate any "not in"
> > expression using only "not" and "in" operation.
>
> Sure, but note that you can also reformulate != using not and ==, <
> using not and >=, etc. Operators like "not in" and "is not" should
> really be considered single tokens, even though they seem to use "not".
> And I think they are really convenient.
>
> -- Alain.

1. I thought "x not in y" was later added as syntax sugar for "not x
in y"
meaning they used the same set of tokens. (Too lazy to check the
actual tokens)

2. "x not in y" ==>> (True if y.__call__(x) else False)
class Y(object):
def __contains__(self, x):
for item in y:
if x == y:
return True
return False

And if you wanted "x not in y" to be a different token you'd have to
ADD

class Y(object):
def __not_contained__(self, x):
for item in self:
if x == y:
return False
return True

AND with __not_contained__() you'd always have to iterate the entire
sequence to make sure even the last item doesn't match.

SO with one token "x not in y" you DON'T have to itterate through the
entire sequence thus it is more effiecient.

Steven D'Aprano

unread,
Oct 16, 2011, 1:05:25 AM10/16/11
to
On Sat, 15 Oct 2011 15:04:24 -0700, DevPlayer wrote:

> 1. I thought "x not in y" was later added as syntax sugar for "not x in
> y"
> meaning they used the same set of tokens. (Too lazy to check the actual
> tokens)

Whether the compiler has a special token for "not in" is irrelevant.
Perhaps it uses one token, or two, or none at all because a pre-processor
changes "x not in y" to "not x in y". That's an implementation detail.
What's important is whether it is valid syntax or not, and how it is
implemented.

As it turns out, the Python compiler does not distinguish the two forms:

>>> from dis import dis
>>> dis(compile('x not in y', '', 'single'))
1 0 LOAD_NAME 0 (x)
3 LOAD_NAME 1 (y)
6 COMPARE_OP 7 (not in)
9 PRINT_EXPR
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> dis(compile('not x in y', '', 'single'))
1 0 LOAD_NAME 0 (x)
3 LOAD_NAME 1 (y)
6 COMPARE_OP 7 (not in)
9 PRINT_EXPR
10 LOAD_CONST 0 (None)
13 RETURN_VALUE


Also for what it is worth, "x not in y" goes back to at least Python 1.5,
and possibly even older. (I don't have any older versions available to
test.)



> 2. "x not in y" ==>> (True if y.__call__(x) else False)

y.__call__ is irrelevant. But for what it's worth:

(1) Instead of writing "y.__call__(x)", write "y(x)"

(2) Instead of writing "True if blah else False", write "bool(blah)".


> class Y(object):
> def __contains__(self, x):
> for item in y:
> if x == y:
> return True
> return False

You don't have to define a __contains__ method if you just want to test
each item sequentially. All you need is to obey the sequence protocol and
define a __getitem__ that works in the conventional way:


>>> class Test:
... def __init__(self, args):
... self._data = list(args)
... def __getitem__(self, i):
... return self._data[i]
...
>>> t = Test("abcde")
>>> "c" in t
True
>>> "x" in t
False

Defining a specialist __contains__ method is only necessary for non-
sequences, or if you have some fast method for testing whether an item is
in the object quickly. If all you do is test each element one at a time,
in numeric order, don't bother writing __contains__.


> And if you wanted "x not in y" to be a different token you'd have to ADD

Tokens are irrelevant. "x not in y" is defined to be the same as "not x
in y" no matter what. You can't define "not in" to do something
completely different.


> class Y(object):
> def __not_contained__(self, x):
> for item in self:
> if x == y:
> return False
> return True
>
> AND with __not_contained__() you'd always have to iterate the entire
> sequence to make sure even the last item doesn't match.
>
> SO with one token "x not in y" you DON'T have to itterate through the
> entire sequence thus it is more effiecient.

That's not correct.




--
Steven

DevPlayer

unread,
Nov 6, 2011, 6:23:02 PM11/6/11
to
On Oct 16, 12:05 am, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:
> On Sat, 15 Oct 2011 15:04:24 -0700, DevPlayer wrote:
> > I thought "x not in y" was later added as syntax sugar for "not x in y"
> > meaning they used the same set of tokens. (Too lazy to check the actual
> > tokens)
Stated in response to OP wanting a seperate token for "not in" verse
"is not".

> Whether the compiler has a special token for "not in" is irrelevant.
I don't know.

> Perhaps it uses one token, or two, or none at all because a
> pre-processor changes "x not in y" to "not x in y". That's
> an implementation detail.
I agree.

> What's important is whether it is valid syntax or not, and how it is
> implemented.
I agree.

> As it turns out, the Python compiler does not distinguish the two forms:
>
> >>> from dis import dis
> >>> dis(compile('x not in y', '', 'single'))
>
>   1           0 LOAD_NAME                0 (x)
>               3 LOAD_NAME                1 (y)
>               6 COMPARE_OP               7 (not in)
>               9 PRINT_EXPR
>              10 LOAD_CONST               0 (None)
>              13 RETURN_VALUE        >>> dis(compile('not x in y', '', 'single'))
>
>   1           0 LOAD_NAME                0 (x)
>               3 LOAD_NAME                1 (y)
>               6 COMPARE_OP               7 (not in)
>               9 PRINT_EXPR
>              10 LOAD_CONST               0 (None)
>              13 RETURN_VALUE

So cool! Thanks for showing how to do that.

I tried to say implementing a seperate method was not efficient.

> Also for what it is worth, "x not in y" goes back to at least Python 1.5,
> and possibly even older. (I don't have any older versions available to
> test.)
So "not in" was added as an alternative (just a long time ago).
I too am glad they added it.

> (2) Instead of writing "True if blah else False", write "bool(blah)".
Good tip! I like.

>
> > class Y(object):
> >     def __contains__(self, x):
> >         for item in y:
> >         if x == y:
> >             return True
> >         return False
>
> You don't have to define a __contains__ method if you just want to test
> each item sequentially. All you need is to obey the sequence protocol and
> define a __getitem__ that works in the conventional way:

Didn't intend to show how to implement __contains__ using "==" and
__not_contains__ "<>" in python but to show that python didn't benefit
from the not_in loop as much as for example assembly language does
it's loop (x86 LOOPE/LOOPZ vs LOOPNZ/LOOPNE).

>
> >>> class Test:
>
> ...     def __init__(self, args):
> ...             self._data = list(args)
> ...     def __getitem__(self, i):
> ...             return self._data[i]
> ...>>> t = Test("abcde")
> >>> "c" in t
> True
> >>> "x" in t
> False
Another new thing for me.

>
> Defining a specialist __contains__ method is only necessary for non-
> sequences, or if you have some fast method for testing whether an item is
> in the object quickly. If all you do is test each element one at a time,
> in numeric order, don't bother writing __contains__.
>
> > And if you wanted "x not in y" to be a different token you'd have to ADD
>
> Tokens are irrelevant. "x not in y" is defined to be the same as "not x
> in y" no matter what.
> You can't define "not in" to do something completely different.
I agree they are not implemented differently.
I agree that they shouldn't be implemented differently.
I disagree they can not be implemented differently. I think they can.
But I see no reason too.

> > class Y(object):
> >     def __not_contained__(self, x):
> >         for item in self:
> >             if x == y:
> >                 return False
> >         return True
>
> > AND with __not_contained__() you'd always have to iterate the entire
> > sequence to make sure even the last item doesn't match.
> > SO with one token "x not in y" you DON'T have to itterate through the
> > entire sequence thus it is more effiecient.
> That's not correct.
> Steven
I tried to prove my point and failded and instead proved (to myself)
you are correct. It is not more efficient. Also I should have used if
<> y: continue to have better tried to make the point but it wouldn't
have mattered. I still would have been wrong.

But I did walk away from this topic with some goodie tips. Thanks
Steven.


0 new messages