TypeError with classes


Since methods are functions in a class I can assume that they have the same behavior as what I tested in test_type_error_w_positional_arguments, test_type_error_w_keyword_arguments and test_type_error_w_args_and_kwargs.


preview

I have these tests by the end of the chapter

type_error/tests/test_type_error.py
  1import src.type_error
  2
  3
  4def test_type_error_w_positional_arguments():
  5    src.type_error.function_00('a')
  6    src.type_error.function_01('a', 'b')
  7    src.type_error.function_02('a', 'b', 'c')
  8    src.type_error.function_03('a', 'b', 'c', 'd')
  9    src.type_error.function_04('a')
 10    src.type_error.function_05('a', 'b')
 11    src.type_error.function_06('a', 'b', 'c')
 12    src.type_error.function_07('a', 'b', 'c', 'd')
 13    src.type_error.function_08('last', 'one')
 14
 15
 16def test_type_error_w_keyword_arguments():
 17    src.type_error.function_00(the_input=0)
 18    src.type_error.function_01(
 19        first='first',
 20        second={'key': 'value'},
 21    )
 22    src.type_error.function_02(
 23        third=(0, 1, 2, 'n'),
 24        second=[0, 1, 2, 'n'],
 25        first={0, 1, 2, 'n'},
 26    )
 27    src.type_error.function_03(
 28        first=None,
 29        second=False,
 30        third=True,
 31        fourth=4,
 32    )
 33    src.type_error.function_04(argument='value')
 34    src.type_error.function_05(
 35        argument_0='value_1',
 36        argument_1=(0, 1, 2, 'n'),
 37    )
 38    src.type_error.function_06(
 39        argument_0='value_1',
 40        argument_1=(0, 1, 2, 'n'),
 41        argument_2=[0, 1, 2, 'n'],
 42    )
 43    src.type_error.function_07(
 44        argument_0=(0, 1, 2, 'n'),
 45        argument_1=[0, 1, 2, 'n'],
 46        argument_2={0, 1, 2, 'n'},
 47        argument_n={'key': 'value'},
 48    )
 49    src.type_error.function_08(
 50        argument='positional',
 51        name='keyword',
 52    )
 53
 54
 55def test_type_error_w_args_and_kwargs():
 56    src.type_error.function_00('argument')
 57    src.type_error.function_01(1, 0)
 58    src.type_error.function_02(
 59        third=True, second=False,
 60        first=None,
 61    )
 62    src.type_error.function_03(
 63        second=[0, 1, 2, 'n'],
 64        first=(0, 1, 2, 'n'),
 65        third={0, 1, 2, 'n'},
 66        fourth={'key': 'value'},
 67    )
 68    src.type_error.function_04('value')
 69    src.type_error.function_05(
 70        (0, 1, 2, 'n'),
 71        [0, 1, 2, 'n'],
 72    )
 73    src.type_error.function_06(
 74        (0, 1, 2, 'n'),
 75        [0, 1, 2, 'n'],
 76        argument_2={0, 1, 2, 'n'},
 77    )
 78    src.type_error.function_07(
 79        argument_n={'key': 'value'},
 80        argument_2={0, 1, 2, 'n'},
 81        argument_0=(0, 1, 2, 'n'),
 82        argument_1=[0, 1, 2, 'n'],
 83    )
 84    src.type_error.function_08(
 85        'positional',
 86        argument='keyword',
 87    )
 88
 89
 90def test_type_error_w_class_methods():
 91    src.type_error.AClass.method_00()
 92    src.type_error.AClass().method_01()
 93    src.type_error.AClass().method_02()
 94    src.type_error.AClass.method_03()
 95    src.type_error.AClass.method_04()
 96    src.type_error.AClass().method_05()
 97    src.type_error.AClass().method_06()
 98    src.type_error.AClass().method_07()
 99    src.type_error.AClass().method_08()
100    src.type_error.AClass().method_09()
101
102
103def test_type_error_w_the_uncallables():
104    src.type_error.none()
105    src.type_error.false()
106    src.type_error.true()
107    src.type_error.an_integer()
108    src.type_error.a_float()
109    src.type_error.a_string()
110    src.type_error.a_tuple()
111    src.type_error.a_list()
112    src.type_error.a_set()
113    src.type_error.a_dictionary()
114
115
116# Exceptions seen
117# AssertionError
118# NameError
119# TypeError
120# ModuleNotFoundError
121# AttributeError

questions about TypeError with classes

Questions to think about as I go through the chapter


open the project


test_type_error_w_class_methods

RED: make it fail


I add a test with a call to AClass.method from test_type_error.py

84      src.type_error.function_08(
85          'positional',
86          argument='keyword',
87      )
88
89
90  def test_type_error_w_class_methods():
91      src.type_error.AClass.method_00()
92
93
94  # Exceptions seen

the terminal is my friend, and shows AttributeError

AttributeError: module 'src.type_error'
                has no attribute 'AClass'

because AClass is not defined in type_error.py.


GREEN: make it pass


  • I open type_error/__init__.py from the src folder

  • I add a class definition for AClass to type_error.py

    40def function_08(name, argument):
    41    return None
    42
    43
    44class AClass(object):
    45
    46    pass
    

    the terminal is my friend, and shows AttributeError

    AttributeError: type object 'AClass' has no attribute 'method_00'
    

    because there is nothing named method_00 in AClass.

  • I add the name to the class definition

    44class AClass(object):
    45
    46    # pass
    47    method_00
    

    the terminal is my friend, and shows NameError

    NameError: name 'method_00' is not defined
    
  • I define method_00 by pointing it to None

    44class AClass(object):
    45
    46    # pass
    47    # method_00
    48    method_00 = None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'NoneType' object is not callable
    

    because method_00 points to None and I cannot call None like a function.

  • I change method_00 to a method

    44class AClass(object):
    45
    46    # pass
    47    # method_00
    48    # method_00 = None
    49    def method_00(): return None
    

    the test passes.


REFACTOR: make it better


  • I remove the commented lines

    44class AClass(object):
    45
    46    def method_00(): return None
    
  • I add a call to src.type_error.AClass().method_01 from test_type_error.py

    90def test_type_error_w_class_methods():
    91    src.type_error.AClass.method_00()
    92    src.type_error.AClass().method_01()
    93
    94
    95# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: 'AClass' object
                    has no attribute 'method_01'.
                    Did you mean: 'method_00'?
    
  • I add a method definition for method_01 to AClass in type_error.py

    44class AClass(object):
    45
    46    def method_00(): return None
    47    def method_01(): return None
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_01() takes
               0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add @staticmethod to method_01

    class AClass(object):
    
        def method_00(): return None
    
        @staticmethod
        def method_01(): return None
    

    the test passes because I can use the staticmethod decorator if I do not want to add self to the method definition whenit does not use anything that belongs to the class.

    Both methods look the same. The difference is in how I call them AClass.method_00() vs AClass().method_01().

  • I add a call to src.type_error.AClass().method_02 from test_type_error.py

    90def test_type_error_w_class_methods():
    91    src.type_error.AClass.method_00()
    92    src.type_error.AClass().method_01()
    93    src.type_error.AClass().method_02()
    94
    95
    96# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: 'AClass' object
                    has no attribute 'method_02'.
                    Did you mean: 'method_00'?
    
  • I add a definition for method_02 to AClass in type_error.py

    44class AClass(object):
    45
    46    def method_00(): return None
    47
    48    @staticmethod
    49    def method_01(): return None
    50
    51    def method_02(): return self.method_01()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_02() takes
               0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add @staticmethod to method_02

    48    @staticmethod
    49    def method_01(): return None
    50
    51    @staticmethod
    52    def method_02(): return self.method_01()
    

    the terminal is my friend, and shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses of method_02

    51    @staticmethod
    52    # def method_02(): return self.method_01()
    53    def method_02(self):
    54        return self.method_01()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_02() missing
               1 required positional argument: 'self'
    
  • I comment out the staticmethod decorator

    51    # @staticmethod
    52    # def method_02(): return self.method_01()
    53    def method_02(self):
    54        return self.method_01()
    

    the test passes because a method of an instance takes the instance of the class (self) it belongs to as the first argument which allows it to use things that belong to the class.

  • I add a call to src.type_error.AClass.method_03 from test_type_error.py

    90def test_type_error_w_class_methods():
    91    src.type_error.AClass.method_00()
    92    src.type_error.AClass().method_01()
    93    src.type_error.AClass().method_02()
    94    src.type_error.AClass.method_03()
    95
    96
    97# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: type object 'AClass'
                    has no attribute 'method_03'.
                    Did you mean: 'method_00'?
    
  • I add a definition for method_03 to AClass in type_error.py

    51    # @staticmethod
    52    # def method_02(): return self.method_01()
    53    def method_02(self):
    54        return self.method_01()
    55
    56    def method_03():
    57        return method_02()
    

    the terminal is my friend, and shows NameError

    NameError: name 'method_02' is not defined
    
  • I add AClass. before method_02

    56    def method_03():
    57        # return method_02()
    58        return AClass.method_02()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_02() missing
               1 required positional argument: 'self'
    

    because

  • I use an instance of the class to call the method

    56    def method_03():
    57        # return method_02()
    58        # return AClass.method_02()
    59        return AClass().method_02()
    

    the test passes. This is a silly example because I used AClass() inside a method of AClass. I could just use self. I would only need this if I was calling a method of a different class.

  • Here is another silly example. I add a call to src.type_error.AClass.method_04 from test_type_error.py

    93    src.type_error.AClass().method_02()
    94    src.type_error.AClass.method_03()
    95    src.type_error.AClass.method_04()
    96
    97
    98# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: type object 'AClass'
                    has no attribute 'method_04'.
                    Did you mean: 'method_00'?
    
  • I add a method definition for method_04 to AClass in type_error.py

    56    def method_03():
    57        # return method_02()
    58        # return AClass.method_02()
    59        return AClass().method_02()
    60
    61    def method_04():
    62        return AClass.method_02()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_02() missing
               1 required positional argument: 'self'
    

    because

  • I pass AClass as input in the call to method_02

    61    def method_04():
    62        # return AClass.method_02()
    63        return AClass.method_02(AClass)
    

    the test passes. I called a method of AClass and passed AClass as input. I can use self.

  • I add a call to src.type_error.AClass().method_05 from test_type_error.py

    94    src.type_error.AClass.method_03()
    95    src.type_error.AClass.method_04()
    96    src.type_error.AClass().method_05()
    97
    98
    99# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: 'AClass' object
                    has no attribute 'method_05'.
                    Did you mean: 'method_00'?
    
  • I add a method definition for method_05 to AClass in type_error.py

    61    def method_04():
    62        # return AClass.method_02()
    63        return AClass.method_02(AClass)
    64
    65    def method_05():
    66        return method_02()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_05() takes
               0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add self to the parentheses of method_05

    65    # def method_05():
    66    def method_05(self):
    67        return method_02()
    

    the terminal is my friend, and shows NameError

    NameError: name 'method_02' is not defined
    

    because there is no method_02 at the module level of type_error.py. It is inside AClass in type_error.py, I have to be specific.

  • I add self. before method_02

    65    # def method_05():
    66    def method_05(self):
    67        # return method_02()
    68        return self.method_02()
    

    the test passes.

  • I add a call to src.type_error.AClass().method_06 from test_type_error.py

     95    src.type_error.AClass.method_04()
     96    src.type_error.AClass().method_05()
     97    src.type_error.AClass().method_06()
     98
     99
    100# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: 'AClass' object
                    has no attribute 'method_06'.
                    Did you mean: 'method_00'?
    
  • I add a method definition for method_06 to AClass

    65    # def method_05():
    66    def method_05(self):
    67        # return method_02()
    68        return self.method_02()
    69
    70    def method_06():
    71        return self.method_01()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_06() takes
               0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add self to the parentheses of method_06

    70    # def method_06():
    71    def method_06(self):
    72        return self.method_01()
    

    the test passes.

  • I add a call to src.type_error.AClass().method_07 from test_type_error.py

     96    src.type_error.AClass().method_05()
     97    src.type_error.AClass().method_06()
     98    src.type_error.AClass.method_07()
     99
    100
    101# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: type object 'AClass'
                    has no attribute 'method_07'.
                    Did you mean: 'method_00'?
    
  • I add a method definition for method_07 to AClass in type_error.py

    70    # def method_06():
    71    def method_06(self):
    72        return self.method_01()
    73
    74    def method_07(self):
    75        return self.method_00()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_07() missing
               1 required positional argument: 'self'
    

    because

  • I use an instance of the class to call the method from test_type_error.py

     96    src.type_error.AClass().method_05()
     97    src.type_error.AClass().method_06()
     98    # src.type_error.AClass.method_07()
     99    src.type_error.AClass().method_07()
    100
    101
    102# Exceptions seen
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_00() takes
               0 positional arguments but 1 was given
    

    because

  • I add the staticmethod decorator to method_00 of AClass in type_error.py

    44class AClass(object):
    45
    46    @staticmethod
    47    def method_00(): return None
    

    the test passes. I can use the staticmethod decorator if I do not want to add self to the method definition whenit does not use anything that belongs to the class.

  • I add a call to src.type_error.AClass.method_08() from test_type_error.py

     98    # src.type_error.AClass.method_07()
     99    src.type_error.AClass().method_07()
    100    src.type_error.AClass.method_08()
    101
    102
    103# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: type object 'AClass'
                    has no attribute 'method_08'.
                    Did you mean: 'method_00'?
    
  • I add a method definition for method_08 to AClass in type_error.py

    75    def method_07(self):
    76        return self.method_00()
    77
    78    def method_08(self):
    79        return self.method_04()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_08() missing
               1 required positional argument: 'self'
    

    because I called method_08 like a staticmethod and it is defined as an instance method (It expects self as input).

  • I use an instance of the class to call the method from test_type_error.py

     98    # src.type_error.AClass.method_07()
     99    src.type_error.AClass().method_07()
    100    # src.type_error.AClass.method_08()
    101    src.type_error.AClass().method_08()
    102
    103
    104# Exceptions seen
    

    the terminal shows TypeError

    TypeError: AClass.method_04() takes
               0 positional arguments but 1 was given
    

    because

  • I add the staticmethod decorator to method_04 of AClass in type_error.py

    57    def method_03():
    58        # return method_02()
    59        # return AClass.method_02()
    60        return AClass().method_02()
    61
    62    @staticmethod
    63    def method_04():
    64        # return AClass.method_02()
    65        return AClass.method_02(AClass)
    66
    67    # def method_05():
    68    def method_05(self):
    69        # return method_02()
    70        return self.method_02()
    

    the test passes.

  • I add a call to src.type_error.AClass.method_09() from test_type_error.py

    100    # src.type_error.AClass.method_08()
    101    src.type_error.AClass().method_08()
    102    src.type_error.AClass().method_09()
    103
    104
    105# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: 'AClass' object
                    has no attribute 'method_09'.
                    Did you mean: 'method_00'?
    
  • I add a method definition for method_09 to AClass in type_error.py

    79    def method_08(self):
    80        return self.method_04()
    81
    82    def method_09(self):
    83        return self.method_03()
    

    the terminal is my friend, and shows TypeError

    TypeError: AClass.method_03() takes
               0 positional arguments but 1 was given
    

    because

  • I add the @staticmethod to method_03 of AClass in type_error.py

    52    # @staticmethod
    53    # def method_02(): return self.method_01()
    54    def method_02(self):
    55        return self.method_01()
    56
    57    @staticmethod
    58    def method_03():
    59        # return method_02()
    60        # return AClass.method_02()
    61        return AClass().method_02()
    62
    63    @staticmethod
    64    def method_04():
    65        # return AClass.method_02()
    66        return AClass.method_02(AClass)
    

    the test passes.

  • I remove the commented lines from type_error.py

    44class AClass(object):
    45
    46    @staticmethod
    47    def method_00(): return None
    48
    49    @staticmethod
    50    def method_01(): return None
    
    52    def method_02(self):
    53        return self.method_01()
    54
    55    @staticmethod
    56    def method_03():
    57        return AClass().method_02()
    
    59    @staticmethod
    60    def method_04():
    61        return AClass.method_02(AClass)
    62
    63    def method_05(self):
    64        return self.method_02()
    
    66    def method_06(self):
    67        return self.method_01()
    68
    69    def method_07(self):
    70        return self.method_00()
    
    72    def method_08(self):
    73        return self.method_04()
    74
    75    def method_09(self):
    76        return self.method_03()
    
  • I remove the commented lines from test_type_error.py

     90def test_type_error_w_class_methods():
     91    src.type_error.AClass.method_00()
     92    src.type_error.AClass().method_01()
     93    src.type_error.AClass().method_02()
     94    src.type_error.AClass.method_03()
     95    src.type_error.AClass.method_04()
     96    src.type_error.AClass().method_05()
     97    src.type_error.AClass().method_06()
     98    src.type_error.AClass().method_07()
     99    src.type_error.AClass().method_08()
    100    src.type_error.AClass().method_09()
    101
    102
    103# Exceptions seen
    
  • I open a new terminal then make sure I am in the type_error folder

    cd type_error
    
  • I add a git commit message in the other terminal

    git commit --all --message \
    'add test_type_error_w_class_methods'
    

test_type_error_w_the_uncallables

Is every object callable?


RED: make it fail


  • I go back to the terminal that is running the tests.

  • I add a test to test_type_error.py

    100    src.type_error.AClass().method_09()
    101
    102
    103def test_type_error_w_the_uncallables():
    104    src.type_error.none()
    105
    106
    107# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'none'
    

    there is nothing named none in type_error.py in the src folder yet


GREEN: make it pass


  • I add none and point it to None

    1none = None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'NoneType' object is not callable
    
    • the () to the right of src.type_error.none makes it a call

    • the name none points to None which is NOT callable. Using substitution

      none = None   # point the name to the object
      none()        # call the name
      None()        # substitute the value for the name
      

      None() raises TypeError because I cannot call None like a function.

  • I make none a function in type_error.py to make it callable

    1# none = None
    2def none(): return None
    3
    4
    5def function_00(the_input):
    6    return None
    

    the test passes.

I can call a function, I cannot call None


REFACTOR: make it better


  • I add a call to false in test_type_error.py

    103def test_type_error_w_the_uncallables():
    104    src.type_error.none()
    105    src.type_error.false()
    106
    107
    108# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'false'
    

    false is not in type_error.py

  • I add false to type_error.py and point it to False

    1# none = None
    2def none(): return None
    3false = False
    4
    5
    6def function_00(the_input):
    7    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'bool' object is not callable
    

    false points to False which is NOT callable. Using substitution

    false = False
    false()
    False()
    

    False() raises TypeError because I cannot call a boolean like a function

  • I change false from a variable to a function to make it callable

    1# none = None
    2def none(): return None
    3# false = False
    4def false(): return False
    5
    6
    7def function_00(the_input):
    8    return None
    

    the test is green again.

  • I add a call to the other boolean in test_type_error.py

    103def test_type_error_w_the_uncallables():
    104    src.type_error.none()
    105    src.type_error.false()
    106    src.type_error.true()
    107
    108
    109# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'true'
    

    there is nothing named true in type_error.py

  • I add true and point it to True in type_error.py

    3# false = False
    4def false(): return False
    5true = True
    6
    7
    8def function_00(the_input):
    9    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'bool' object is not callable
    
  • I change true from a variable to a function to make it callable

     3# false = False
     4def false(): return False
     5# true = True
     6def true(): return True
     7
     8
     9def function_00(the_input):
    10    return None
    

    the test passes. I can call a function, I cannot call a boolean or None


  • I add a call to an integer, in test_type_error.py

    105    src.type_error.false()
    106    src.type_error.true()
    107    src.type_error.an_integer()
    108
    109
    110# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'an_integer'
    
  • I add an_integer and point it to 1234 in type_error.py

     5# true = True
     6def true(): return True
     7an_integer = 1234
     8
     9
    10def function_00(the_input):
    11    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'int' object is not callable
    

    the name an_integer points to an integer (1234) which is NOT callable. Using substitution

    an_integer = 1234  # point the name to the object
    an_integer()       # call the name
    1234()             # substitute the value for the name
    

    1234() raises TypeError because I cannot call an integer like a function.

  • I change an_integer from a variable to a function to make it callable

     5# true = True
     6def true(): return True
     7# an_integer = 1234
     8def an_integer(): return 1234
     9
    10
    11def function_00(the_input):
    12    return None
    

    the test passes. I can call a function, I cannot call an integer, a boolean or None.

  • I add a call to a float in test_type_error.py

    106    src.type_error.true()
    107    src.type_error.an_integer()
    108    src.type_error.a_float()
    109
    110
    111# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'a_float'
    
  • I add a_float and point it to 5.678 in type_error.py

     7# an_integer = 1234
     8def an_integer(): return 1234
     9a_float = 5.678
    10
    11
    12def function_00(the_input):
    13    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'float' object is not callable
    

    a_float points to a float (5.678) which is NOT callable. Using substitution

    a_float = 5.678
    a_float()
    5.678()
    

    5.678() raises TypeError because I cannot call a float like a function.

  • I change a_float from a variable to a function to make it callable

     7# an_integer = 1234
     8def an_integer(): return 1234
     9# a_float = 5.678
    10def a_float(): return 5.678
    11
    12
    13def function_00(the_input):
    14    return None
    

    the test passes. I can call a function, I cannot call a float, integer, boolean or None.

  • I add a call to a string (anything in quotes) in test_type_error.py

    107    src.type_error.an_integer()
    108    src.type_error.a_float()
    109    src.type_error.a_string()
    110
    111
    112# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'a_string'
    
  • I add a_string and point it to 'a string' in type_error.py

     9# a_float = 5.678
    10def a_float(): return 5.678
    11a_string = 'a string'
    12
    13
    14def function_00(the_input):
    15    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'str' object is not callable
    

    the name a_string points to a string ('a string') which is NOT callable. Using substitution

    a_string = 'a string' # point the name to the object
    a_string()            # call the name
    'a string'()          # substitute the value for the name
    

    'a string'() raises TypeError because I cannot call a string like a function.

  • I change a_string from a variable to a function to make it callable

    10# a_float = 5.678
    11def a_float(): return 5.678
    12# a_string = 'a string'
    13def a_string(): return 'a string'
    14
    15
    16def function_00(the_input):
    17    return None
    

    the test passes. I can call a function. I cannot call a string, float, integer, boolean or None.

  • I add a call to a tuple (anything in parentheses (), separated by a comma) in test_type_error.py

    108    src.type_error.a_float()
    109    src.type_error.a_string()
    110    src.type_error.a_tuple()
    111
    112
    113# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'a_tuple'
    
  • I add a_tuple and point it to (0, 1, 2, 'n') in type_error.py

    11# a_string = 'a string'
    12def a_string(): return 'a string'
    13a_tuple = (0, 1, 2, 'n')
    14
    15
    16def function_00(the_input):
    17    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'tuple' object is not callable
    

    the name a_tuple points to a tuple ((0, 1, 2, 'n')) which is NOT callable. Using substitution

    a_tuple = (0, 1, 2, 'n')
    a_tuple()
    (0, 1, 2, 'n')()
    

    (0, 1, 2, 'n')() raises TypeError because I cannot call a tuple like a function.

  • I change a_tuple from a variable to a function to make it callable

    11# a_string = 'a string'
    12def a_string(): return 'a string'
    13# a_tuple = (0, 1, 2, 'n')
    14def a_tuple(): return (0, 1, 2, 'n')
    15
    16
    17def function_00(the_input):
    18    return None
    

    the test passes. I can call a function. I cannot call a tuple, string, float, integer, boolean or None.

  • I add a call to a list in test_type_error.py

    109    src.type_error.a_string()
    110    src.type_error.a_tuple()
    111    src.type_error.a_list()
    112
    113
    114# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'a_list'
    
  • I add a_list and point it to [0, 1, 2, 'n'] in type_error.py

    13# a_tuple = (0, 1, 2, 'n')
    14def a_tuple(): return (0, 1, 2, 'n')
    15a_list = [0, 1, 2, 'n']
    16
    17
    18def function_00(the_input):
    19    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'list' object is not callable
    

    a_list points to a list ([0, 1, 2, 'n']) which is NOT callable. Using substitution

    a_list = [0, 1, 2, 'n']
    a_list()
    [0, 1, 2, 'n']()
    

    [0, 1, 2, 'n']() raises TypeError because I cannot call a list like a function.

  • I change a_list from a variable to a function to make it callable

    13# a_tuple = (0, 1, 2, 'n')
    14def a_tuple(): return (0, 1, 2, 'n')
    15# a_list = [0, 1, 2, 'n']
    16def a_list(): return [0, 1, 2, 'n']
    17
    18
    19def function_00(the_input):
    20    return None
    

    the test passes. I can call a function, I cannot call a list, tuple, string, float, integer, boolean or None.

  • I add a call to a set in test_type_error.py

    110    src.type_error.a_tuple()
    111    src.type_error.a_list()
    112    src.type_error.a_set()
    113
    114
    115# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'a_set'
    
  • I add a_set and point it to {0, 1, 2, 'n'} in type_error.py

    15# a_list = [0, 1, 2, 'n']
    16def a_list(): return [0, 1, 2, 'n']
    17a_set = {0, 1, 2, 'n'}
    18
    19
    20def function_00(the_input):
    21    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'set' object is not callable
    

    a_set points to a set ({0, 1, 2, 'n'}) which is NOT callable. Using substitution

    a_set = {0, 1, 2, 'n'}
    a_set()
    {0, 1, 2, 'n'}()
    

    {0, 1, 2, 'n'}() raises TypeError because I cannot call a set like a function.

  • I change a_set from a variable to a function to make it callable

    15# a_list = [0, 1, 2, 'n']
    16def a_list(): return [0, 1, 2, 'n']
    17# a_set = {0, 1, 2, 'n'}
    18def a_set(): return {0, 1, 2, 'n'}
    19
    20
    21def function_00(the_input):
    22    return None
    

    the test passes. I can call a function, I cannot call a set, list, tuple, string, float, integer, boolean or None.

  • I add a call to a dictionary in test_type_error.py

    111    src.type_error.a_list()
    112    src.type_error.a_set()
    113    src.type_error.a_dictionary()
    114
    115
    116# Exceptions seen
    117# AssertionError
    118# NameError
    119# TypeError
    120# ModuleNotFoundError
    121# AttributeError
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.type_error'
                    has no attribute 'a_dictionary'
    
  • I add a_dictionary and point it to {'key': 'value'} in type_error.py

    17# a_set = {0, 1, 2, 'n'}
    18def a_set(): return {0, 1, 2, 'n'}
    19a_dictionary = {'key': 'value'}
    20
    21
    22def function_00(the_input):
    23    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: 'dict' object is not callable
    

    a_dictionary points to a dictionary ({'key': 'value'}) which is NOT callable. Using substitution

    a_dictionary = {'key': 'value'}
    a_dictionary()
    {'key': 'value'}()
    

    {'key': 'value'}() raises TypeError because I cannot call a dictionary like a function.

  • I change a_dictionary from a variable to a function to make it callable

    17# a_set = {0, 1, 2, 'n'}
    18def a_set(): return {0, 1, 2, 'n'}
    19# a_dictionary = {'key': 'value'}
    20def a_dictionary(): return {'key': 'value'}
    21
    22
    23def function_00(the_input):
    24    return None
    

    the test is green again. I can call a function, I cannot call a dictionary, set, list, tuple, string, float, integer, boolean or None.

  • I remove the commented lines

     1def none(): return None
     2def false(): return False
     3def true(): return True
     4def an_integer(): return 1234
     5def a_float(): return 5.678
     6def a_string(): return 'a string'
     7def a_tuple(): return (0, 1, 2, 'n')
     8def a_list(): return [0, 1, 2, 'n']
     9def a_set(): return {0, 1, 2, 'n'}
    10def a_dictionary(): return {'key': 'value'}
    11
    12
    13def function_00(the_input):
    14    return None
    
  • I add a git commit message in the other terminal

    git commit --all --message \
    'add test_type_error_w_the_uncallables'
    

close the project

  • I close tests/test_type_error.py and src/type_error.py

  • I click in the terminal where the tests are running

  • I use q on the keyboard to leave the tests. The terminal goes back to the command line.

  • I change directory to the parent of type_error

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory.


review

The tests show that

All the tests so far show that I get TypeError when I call an object in a way that is different from its definition.

How many questions can you answer about TypeError with classes?


code from the chapter

Do you want to see all the CODE I typed in this chapter?


what is next?

Would you like to see another way to write tests?


rate pumping python

If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too.