1

So I know python has the not operator, but how does the not() function come into play?

From some simple testing it appears that it has the signature of not(args[]), while at the same time not acting entirely like a normal function. For example:

x = True
not x # -> False
not(x) # -> False
x = False
not x # -> True
not(x) # -> True

not(0) # -> True
not(1) # -> False
not(0, 0, 0) # -> False
not("False") # -> False

function = not # -> Syntax Error

Why does this exist for "not", and not something like "or"? Is there a way I can capture the not function into a variable / do other manipulation with not as a function?

This question was mostly prompted by attempting to find a single function to invert a list in a map call, even if it is an internal function

delyeet
  • 168
  • 9
  • 6
    Spoiler alert: there is no `not` function – Chris_Rands Dec 18 '19 at 15:18
  • 1
    Who told to you that ``not`` is a function. Dont you see the color of that word in your IDE? Or why you are not try ``type(not)``? – Ekrem Dinçel Dec 18 '19 at 15:20
  • 1
    A unary operator (like `not`) applied to a parenthesized expression may *look* like a function call, but it is not. – chepner Dec 18 '19 at 15:30
  • @EkremDİNÇEL Not everyone uses an IDE with syntax highlighting, or the highlighting in use may not differentiate between functions and operators, and `type(not)` would produce a syntax error just like `function = not`, so that wouldn't really provide any new information. – chepner Dec 18 '19 at 15:31
  • @chepner You may be right about IDE topic. And I mean that Syntax Error too. Because it is a keyword, not an object. – Ekrem Dinçel Dec 18 '19 at 15:34
  • What should be done with this question? – AMC Dec 18 '19 at 18:42
  • It is not a genuine question? A bit misguided and so deep in looking for a solution I mixed up my understanding, but is this not something someone else might run into? Clearly I made this mistake – delyeet Dec 18 '19 at 18:48

4 Answers4

6

There is no not function. There is only the operator not. Adding parentheses is just adding parentheses around the expression; It is not a function call (i.e. not(x) is exactly the same thing as not x). not(0,0,0) is just the not operator applied to the tuple (0,0,0), which isn’t "falsey" so the result is false.

(Note that this is the situation in Python specifically, other languages may have not as a function or some other way to express not entirely).

Cubic
  • 14,902
  • 5
  • 47
  • 92
  • @EkremDİNÇEL [No, I meant what I wrote](https://english.stackexchange.com/questions/109996/is-it-falsy-or-falsey). – Cubic Dec 18 '19 at 15:21
  • To be clearer, the parentheses are part of the expression that the operator is applied to, not function-call syntax. – chepner Dec 18 '19 at 15:22
  • That still seems odd as most statements within python do not work with something immediately attached to them. For example or(1) would not work – delyeet Dec 18 '19 at 15:22
  • 2
    `or` isn't a unary operator; it's a binary operator. `(a) or (b)` would work just fine, with the two parenthesized expressions `(a)` and `(b)`. `or(1)` not working has nothing to do with the parentheses. – chepner Dec 18 '19 at 15:23
  • @EkremDİNÇEL It’s not even bad english, "falsey" and "truthy" are words that are really only used this way in CS as far as I know; It’s just slightly odd language because we needed some words to distinguish the property of "being true" from "being exactly the literal value true" (and equivalent for false). – Cubic Dec 18 '19 at 15:27
  • Okay cool. I've probably gotten a bit too lost trying to find a single function call to invert a list within a map call. Definitely makes sense though since the not operator is applied to a single item, rather than multiple items. The syntax also makes sense, though it seems off at first glance. It probably makes a bit more sense to look at it like the "~" operator – delyeet Dec 18 '19 at 15:28
2

There is no not function. Adding parentheses is totally redundant here, it's not a function call:

 >>> (1) == 1
True
>>> dis.dis('not(1)')
  1           0 LOAD_CONST               0 (1)
              2 UNARY_NOT
              4 RETURN_VALUE
>>> dis.dis('not 1')
  1           0 LOAD_CONST               0 (1)
              2 UNARY_NOT
              4 RETURN_VALUE

You can build a function of course def f(x): return not x but you can probably just use inverse truthy function(s), i.e. bool() or operator.truth()

Chris_Rands
  • 38,994
  • 14
  • 83
  • 119
  • Also ``not(0, 0, 0)`` creates a tuple. – Ekrem Dinçel Dec 18 '19 at 15:26
  • @EkremDİNÇEL `(0, 0, 0)` creates a tuple, yes of course- what's your point? – Chris_Rands Dec 18 '19 at 15:28
  • 1
    `not` has nothing to do with creating the tuple. The commas do that, but `not` has a higher precedence, so the parentheses allow you to apply `not` to the tuple `0, 0, 0`, rather than creating the tuple `True, 0, 0` (with `not` being applied to the first 0 first). – chepner Dec 18 '19 at 15:29
  • @Chris_Rands I mean a tuple which has atleast one element will be ``true`` as a boolean. – Ekrem Dinçel Dec 18 '19 at 15:32
  • @EkremDİNÇEL yes, i know, most objects are truthy apart from https://stackoverflow.com/a/39984051/6260170 – Chris_Rands Dec 18 '19 at 15:35
1

not is a keyword not an object. So you can't set it to variable.

List of Python keywords https://www.programiz.com/python-programming/keywo

Rob
  • 41
  • 5
0

As has already been said, there is no such thing as a negation function like it would be the case in other languages like Julia.

This question was mostly prompted by attempting to find a single function to invert a list in a map call, even if it is an internal function

If you want to a negate a list of booleans using a map call, you can simply use a lambda like this:

>>> mask = [True, False, True]
>>> list(map(lambda b: not b, mask))
[False, True, False]

Alternatively, you can apply Python's bitwise NOT ~ to a numpy array:

>>> import numpy as np
>>> mask = np.array([True, False, True])
>>> ~mask
array([False, True, False], dtype=bool)

Note that I used ~ instead of not. Logical operators are indeed not supported on numpy arrays so writing not mask would produce the following error:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Hope this can help someone!

Rostan
  • 809
  • 9
  • 25