So what is the difference between isinstance() and type() really?


#1

^ From here.

But I don’t understand what they mean by subclass and how it relates to isinstance()? When it checks subclass (or whatever) does it look outside of scope? What does the person mean by base?


#2

type() can only tell us an instance’s parent class.

>>> class Foo:
	pass

>>> class Bar(Foo):
	pass

>>> b = Bar()
>>> type(b)
<class '__main__.Bar'>
>>> type(b) == Bar
True
>>> type(b) == Foo
False
>>> 

This we know to be misleading, since b is a subclass instance of Foo.

>>> isinstance(b, Bar)
True
>>> isinstance(b, Foo)
True

#3

How is b a subclass of Foo in that statement? I’m not good at reading that


#4
class Bar(Foo):

Bar is a subclass of Foo as indicated in the parens. This says that Bar extends or inherits from Foo. Another way of describing the two is, Foo is the super class and Bar is the derived class. Any methods and attributes that Foo has, Bar will inherit.


#5

Oh ok. So does isinstance and type work with (for example) detecting integers that aren’t strictly integers?

Eg. In python 3, if a number is input by a user through an input() and then stored in a variable say input_mem. Would that be an integer if it’s checked with isinstance or type?


#6

Let’s check what happens…

>>> a = input('enter an integer: ')
enter an integer: 42
>>> type(a)
<class 'str'>
>>> isinstance(a, int)
False
>>> 

Sidebar

Do you have a Python shell on your computer, or do you keep a sandbox open (repl.it, etc.) to try out expressions and statements?


#7

No, actually I just use IDLE


#8

That’s the same shell I use. Is it Python 3?


A few days ago in another topic the discussion was centered around returning a number from user input. In Python there is no way to check if a string is a number without actually invoking the float() or the int() constructor and seeing if it raises an exception.

def get_int():
    while True:
        a = input('Enter an integer: ')
        try:
            return int(a)
        except ValueError:
            print ("Try again...")

When we attempt to return an integer, it will raise an exception if the value cannot be cast to an int object., which the except ValueError is able to divert to our instruction statement rather than halting the program and raising the error in the console.

User input is not something that we can relate to data type or class instance, being as it is, a string. Our program needs to validate and assign data that we know will fit our code model.


#9

Yeah, it’s python 3 indeed


#10

You won’t break your computer or the program if you run errant code. Keep the shell open and anytime you want to see if something works, try it. Read and study the error message and make the best of understanding what happened and what caused it.

Rather than write a whole program and then try to debug it, write snippets and test them in the shell. Supply random inputs and study the returns. Each snippet of code that you test and perfect can now become a solid component of your larger program.

A term that’s talked about a lot these days is functional programming. At my level of understanding I’m not going to preach. It boils down to pure functions that when given data will return something predictible and do not interact with any other objects in the namespace. Value in -> value out. The more your programs are written in this fashion the more you can trust the components you’ve written, assuming they pass muster.

def ab(a, b):
    return a * b

Simple, yes, but pure. No real extensive testing required and nothing to debug. No interaction with the namespace and no outside variables. Value in, value out.

The get_int function above qualifies as pure since it meets all the above criteria. We don’t know what it will return but we do know it will be an integer. We don’t have to test the return (save maybe range), just go ahead and use it in some other math or numeric process (such as an index).

Design your projects so that once you build a utility function you never have to change it. That little one above could be plugged into any program without causing any fuss.


#11

So I have a problem…

import time
import random

def get_int(a):
    while True:
        a = input('I will count up to a number kay?')
        try:
            return int(a)
        except ValueError:
            print ("Try again...")



x = 0
get_int(x)

for n in range(x):
    print(n)

There’s no error with input, but there’s no printing either.


#12

Did get_int take an argument? No. No argument. It was never intended to take one so why would you all of a sudden give it one? And why then, overwrite it? Do you see what you are doing?

In the shell, type,

>>> list(range(0))

#13

So why doesn’t get_int ever take an argument? I thought the following would work, but it doesn’t

def get_int(a):
    while True:
        try:
            return int(a)
        except ValueError:
            print ("Try again...")

x = input('I will count up to a number kay?')

get_int(x)

for n in range(x):
    print(n)



#14

Because it is only expected to return user input that meets the criteria. We don’t give it an argument, we expect its return. Call -> Return.

The user input supplies the working data, and that happens in the while loop. Once valid, the return value is an integer.

Remember how I said that once we have a trustworthy component we never have to change it? Never change get_int. It is a trustworthy component. If you mess with it you waste my time.


#15

How do I store a outside the function


#16

Assign the return value…

a = get_int()

#17

Now I feel dumb…


#18

Don’t feel too bad. Just remember a FAIL is a:
First
Attempt
In
Learning

As long as you know how to improve for the future, everything’s good.


#19

Ha… …brilliant.