Question about None

P

Paul LaFollette

Kind people,

Using Python 3.0 on a Gatesware machine (XP).
I am building a class in which I want to constrain the types that can
be stored in various instance variables. For instance, I want to be
certain that self.loc contains an int. This is straightforward (as
long as I maintain the discipline of changing loc through a method
rather than just twiddling it directly.

def setLoc(lo):
assert isinstance(lo, int), "loc must be an int"
self.loc = lo

does the trick nicely.

However, I also want to constrain self.next to be either an instance
of class Node, or None. I would think that the following should work
but it doesn't.

def setNext(nxt):
assert isinstance(nxt, (Node, NoneType)), "next must be a Node"
self.next = nxt

since type(Node) responds with <class, 'NoneType'> but the assertion
above gives "name 'NoneType' is not defined" suggesting that NoneType
is some sort of quasi-class.

def setNext(nxt):
assert nxt==None or isinstance(nxt, Node), "next must be a Node"
self.next = nxt

works ok, but it's uglier than it ought to be.

So, I have three questions.

1) Why doesn't isinstance(nxt, (Node, NoneType)) work?
2) is their a less ugly alternative that what I am using?
3) (this is purely philosophical but I am curious) Would it not be
more intuitive if
isinstance(None, <anything at all>) returned true?

Thank you for your kind attention.
Paul
 
B

Bruno Desthuilliers

Paul LaFollette a écrit :
Kind people,

Using Python 3.0 on a Gatesware machine (XP).
I am building a class in which I want to constrain the types that can
be stored in various instance variables.

This somehow goes against the whole philosophy of dynamic typing Python
is based upon... But there are indeed cases where it makes sense and I
assume you know what you're doing !-)
For instance, I want to be
certain that self.loc contains an int. This is straightforward (as
long as I maintain the discipline of changing loc through a method
rather than just twiddling it directly.

def setLoc(lo):
assert isinstance(lo, int), "loc must be an int"
self.loc = lo

does the trick nicely.

Did you considered using properties (or custom descriptors) instead ?

(snip - others already answered)
 
J

Jeff McNeil

Kind people,

Using Python 3.0 on a Gatesware machine (XP).
I am building a class in which I want to constrain the types that can
be stored in various instance variables.  For instance, I want to be
certain that self.loc contains an int.  This is straightforward (as
long as I maintain the discipline of changing loc through a method
rather than just twiddling it directly.

  def setLoc(lo):
    assert isinstance(lo, int), "loc must be an int"
    self.loc = lo

does the trick nicely.

However, I also want to constrain self.next to be either an instance
of class Node, or None.  I would think that the following should work
but it doesn't.

  def setNext(nxt):
    assert isinstance(nxt, (Node, NoneType)), "next must be a Node"
    self.next = nxt

since type(Node) responds with <class, 'NoneType'> but the assertion
above gives "name 'NoneType' is not defined" suggesting that NoneType
is some sort of quasi-class.

  def setNext(nxt):
    assert nxt==None or isinstance(nxt, Node), "next must be a Node"
    self.next = nxt

works ok, but it's uglier than it ought to be.

So, I have three questions.

1) Why doesn't isinstance(nxt, (Node, NoneType)) work?
2) is their a less ugly alternative that what I am using?
3) (this is purely philosophical but I am curious)  Would it not be
more intuitive if
isinstance(None, <anything at all>) returned true?

Thank you for your kind attention.
Paul

1. The problem is described clearly by that Exception. The 'NoneType'
name isn't bound to any objects at that current scope. I know that
with 2.6, you can import 'types.NoneType' but I don't believe the 3.0
types module includes NoneType. Someone else will have to clarify
that as I don't have 3.0 installed.

2. A less ugly alternative? You could use the accepted method of
testing against None:

if var is None:
do_stuff()

The use of the 'is' operator checks whether objects are exactly the
same (id(var) == id(None)) as opposed to 'isinstance' or '==.'

You might also try defining descriptors in order to make your type
checks slightly more transparent. That might be confusing to other
users of your class, though. Not many people expect a TypeError from
an attribute assignment.

3. None is an instance of NoneType. Why should isinstance return True
when it's tested against other types?

HTH,

Jeff
mcjeff.blogspot.com
 
J

Javier Collado

Hello,

You're right, types.NoneType is not available in python 3.0, I wasn't
aware of that change. Thanks for pointing it out.

Best regards,
Javier
 
S

Steven D'Aprano

Paul said:
3) (this is purely philosophical but I am curious) Would it not be
more intuitive if
isinstance(None, <anything at all>) returned true?

Good grief no!!!

None is an object. It has a type, NoneType. It's *not* a string, or a float,
or an int, or a list, so why would you want isinstance() to *lie* and say
that it is?


Python is good for testing these sorts of ideas:
.... if obj is None: return True
.... return _isinstance(obj, type)
........ print x.upper()
....
PARROT....
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'upper'
 
J

John Yeung

Good grief no!!!

None is an object. It has a type, NoneType. It's *not* a
string, or a float, or an int, or a list, so why would
you want isinstance() to *lie* and say that it is?

Because you might want None to behave as though it were nothing at
all.

Paul LaFollette is probably thinking along the lines of formal logic
or set theory. It's a little bit confused because programming isn't
quite the same as math, and so it's a common question when designing
and implementing programming languages how far to take certain
abstractions. In some languages, nil, null, or none will try to
behave as mathematically close to "nothing" (complete absence of
anything) as possible, even though in reality they have to have some
concrete implementation, such as perhaps being a singleton object.
But mathematically speaking, it's intuitive that "nothing" would match
any type.

I find that it's somewhat like the confusion that often occurs
regarding the all() function. Some people are surprised that all([])
returns True, but it's the same logic behind the truth of the
statement "every element of the empty set is an integer". It's also
true that every element of the empty set is a float. Or an elephant.

John
 
P

Paul Rubin

John Yeung said:
Because you might want None to behave as though it were nothing at all.

Sure, you might also want strings to behave as if they were ints, but
wishing doesn't make it so.
But mathematically speaking, it's intuitive that "nothing" would match
any type.

Completely wrong. The concept you're thinking of in denotational
semantics is called "bottom", but bottom is not a value that functions
can compute and return. It is really the absence of a value. We
would say that a function semantically returns bottom, if calling does
something like loop forever (never return), or it makes the program
crash, or something like that. None is a value which in Haskell has a
particular type. In some other languages, there are None-like values
in more than one type, like in Haskell, for any type there is a
Nothing for the Maybe of that type, but they all are of differing
types, just like Python has an integer 0 and a floating point 0 that
are of differing types.
I find that it's somewhat like the confusion that often occurs
regarding the all() function.

It's the other way though, all([])=True makes sense,
isinstance(None,int) does not.
 
P

Paul Rubin

Paul Rubin said:
crash, or something like that. None is a value which in Haskell has a

I got ahead of myself, of course I meant Python (the *next* sentence
was going to mention Haskell). The corresponding concept in Haskell
is called Nothing, which lives in a type functor called Maybe. I
don't have time to go into it right now but there is a notion among
language weenies these days that the presence of something like None
(in Python) or Null (in Java, SQL, etc) is a wart in a language and
that it's preferable to have something like Maybe.
 
P

Piet van Oostrum

PR> I got ahead of myself, of course I meant Python (the *next* sentence
PR> was going to mention Haskell). The corresponding concept in Haskell
PR> is called Nothing, which lives in a type functor called Maybe. I
PR> don't have time to go into it right now but there is a notion among
PR> language weenies these days that the presence of something like None
PR> (in Python) or Null (in Java, SQL, etc) is a wart in a language and
PR> that it's preferable to have something like Maybe.

The reason is that in Haskell the type system doesn't have union types.
Instead it has the disjoint sum, and Maybe is just one of them.
Otherwise you could have used the union of Nothing and any other type.
In Python there is no reason to use a disjoint sum as Python doesn't use
static typing. You can use unions of types at your hearts desire. So I
don't think there is not much difference between None and Nothing,
except for the type system.

Java, on the other hand does have static typing but does not have
disjoint sums. So they have not much choice but to put null in every
class-based type.
 
S

Steven D'Aprano

John said:
Paul LaFollette is probably thinking along the lines of formal logic
or set theory. It's a little bit confused because programming isn't
quite the same as math, and so it's a common question when designing
and implementing programming languages how far to take certain
abstractions. In some languages, nil, null, or none will try to
behave as mathematically close to "nothing" (complete absence of
anything) as possible, even though in reality they have to have some
concrete implementation, such as perhaps being a singleton object.
But mathematically speaking, it's intuitive that "nothing" would match
any type.

I think you're wrong. Mathematically, you can't mix types like real numbers
and sets: while 1+0 = 1, you can't expect to get a sensible result from
1+{} or {1}∩0. (If that character between the set and zero ends up missing,
it's meant to be INTERSECTION u'\u2229'.)

Similarly, you can't add a scalar to a vector or matrix, even if one or the
other is null.

I find that it's somewhat like the confusion that often occurs
regarding the all() function. Some people are surprised that all([])
returns True, but it's the same logic behind the truth of the
statement "every element of the empty set is an integer". It's also
true that every element of the empty set is a float. Or an elephant.

So-called "vacuous truth". It's often useful to have all([]) return true,
but it's not *always* useful -- there are reasonable cases where the
opposite behaviour would be useful:

if all(the evidence points to the Defendant's guilt) then:
the Defendant is guilty
execute(the Defendant)

sadly means that if there is no evidence that a crime has been committed,
the person accused of committing the imaginary crime will be executed.
 
A

Andre Engels

Paul LaFollette is probably thinking along the lines of formal logic
or set theory.  It's a little bit confused because programming isn't
quite the same as math, and so it's a common question when designing
and implementing programming languages how far to take certain
abstractions.  In some languages, nil, null, or none will try to
behave as mathematically close to "nothing" (complete absence of
anything) as possible, even though in reality they have to have some
concrete implementation, such as perhaps being a singleton object.
But mathematically speaking, it's intuitive that "nothing" would match
any type.

I don't see why that would be the case. Something of the type "thingy"
is ONE thingy. Nothing is ZERO thingies, so it is not something of the
type "thingy". A car is a single car. Nothing is zero cars, which is
not a car, just like two cars is not a car.
 
A

Arnaud Delobelle

Steven D'Aprano said:
So-called "vacuous truth". It's often useful to have all([]) return true,
but it's not *always* useful -- there are reasonable cases where the
opposite behaviour would be useful:

if all(the evidence points to the Defendant's guilt) then:
the Defendant is guilty
execute(the Defendant)

sadly means that if there is no evidence that a crime has been committed,
the person accused of committing the imaginary crime will be executed.

This is a bad example. Someone is not convicted of a crime just because
all the available evidence points towards their guilt. There may be
very little evidence altogether, or it might just be circumstancial, or
unconvincing. Even though it may all point towards the defendent's
guilt, it doesn't mean they will be convicted. There needs to be enough
evidence to convince the jury. So it would be something like:

if sum(guilt_weight(e) for e in evidence) > GUILT_THRESHOLD:
the defendant is guilty
...
 
P

Paul Rubin

Andre Engels said:
I don't see why that would be the case. Something of the type "thingy"
is ONE thingy. Nothing is ZERO thingies, so it is not something of the
type "thingy". A car is a single car. Nothing is zero cars, which is
not a car, just like two cars is not a car.

That seems to confuse values with collections of them. A car is not
the same as a one-element list of cars. Nothing is not the same as a
zero-element list of cars.
 
A

Andre Engels

That seems to confuse values with collections of them.  A car is not
the same as a one-element list of cars.  Nothing is not the same as a
zero-element list of cars.

So you are of the opinion that "nothing" _is_ a car?
 
P

Paul Rubin

Andre Engels said:
So you are of the opinion that "nothing" _is_ a car?

Eh? No of course not. a != b and b != c does not mean a==c.
I don't understand what you're getting at.
 
A

Andre Engels

Eh?  No of course not.  a != b and b != c does not mean a==c.
I don't understand what you're getting at.

I was making a point that I don't agree that "nothing" would match any
type. The reason was that anything of the type car is one car, not two
cars or zero cars, but "nothing" is zero cars. You don't agree with
me, so apparently you are of the opinion that "nothing" would be a
car.
 
P

Paul Rubin

Andre Engels said:
I was making a point that I don't agree that "nothing" would match any
type. The reason was that anything of the type car is one car, not two
cars or zero cars, but "nothing" is zero cars. You don't agree with
me, so apparently you are of the opinion that "nothing" would be a car.

I don't agree that "nothing" is "zero cars". Just like I don't agree
that the empty set, the empty list, and the empty string are the same
thing.
 
T

Terry Reedy

Steven said:
So-called "vacuous truth". It's often useful to have all([]) return
true, but it's not *always* useful -- there are reasonable cases
where the opposite behaviour would be useful:

if all(the evidence points to the Defendant's guilt) then: the
Defendant is guilty execute(the Defendant)

sadly means that if there is no evidence that a crime has been
committed, the person accused of committing the imaginary crime will
be executed.

It seems to me that the absurd conclusion implied by the theorem
invalidates the theorem rather than supporting your point. No evidence
is only the endpoint of a continuum. Suppose that 'all' is one teensy
weensy bit of evidence. A drunked bystander gives a vague description
that fits. Or twenty years before, the defendent argued with the
deceased and said 'I wish you were dead'. Should the person be executed?
I say not. You?

Of course, a person would only be a defendant in the absence of evidence
under a depraved regime that would not much care if there were.

Try finding another 'reasonable case'.

Terry Jan Reedy
 
A

Aaron Brady

That seems to confuse values with collections of them.  A car is not
the same as a one-element list of cars.  Nothing is not the same as a
zero-element list of cars.

Collections are a mathematical (ideal, cognitive) construct.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,142
Latest member
arinsharma
Top