title: Can I restrict objects in Python3 so that only attributes that I make a setter for are allowed?
body: <p>I have something called a Node.  Both Definition and Theorem are a type of node, but only Definitions should be allowed to have a <code>plural</code> attribute:</p>
  
  <pre><code>class Definition(Node):
  
  
      def __init__(self,dic):
          self.type = "definition"
          super(Definition, self).__init__(dic)
          self.plural = move_attribute(dic, {'plural', 'pl'}, strict=False)
  
  
      @property
      def plural(self):
          return self._plural
  
      @plural.setter
      def plural(self, new_plural):
          if new_plural is None:
              self._plural = None
          else:
              clean_plural = check_type_and_clean(new_plural, str)
              assert dunderscore_count(clean_plural)&gt;=2
              self._plural = clean_plural
  
  
  class Theorem(Node):
  
  
      def __init__(self, dic):
          self.type = "theorem"
          super().__init__(dic)
          self.proofs = move_attribute(dic, {'proofs', 'proof'}, strict=False)
          # theorems CANNOT have plurals:
          # if 'plural' in self:
          #   raise KeyError('Theorems cannot have plurals.')
  </code></pre>
  
  <p>As you can see, Definitions have a <code>plural.setter</code>, but theorems do not.  However, the code</p>
  
  <pre><code>theorem = Theorem(some input)
  theorem.plural = "some plural"
  </code></pre>
  
  <p>runs just fine and raises no errors.  But I <em>want</em> it to raise an error.  As you can see, I tried to check for plurals manually at the bottom of my code shown, but this would only be a patch.  I would like to block the setting of ANY attribute that is not expressly defined.  What is the best practice for this sort of thing?</p>
  
  <hr>
  
  <p>I am looking for an answer that satisfies the "<a href="https://stackoverflow.com/questions/31906893/can-i-restrict-objects-in-python3-so-that-only-attributes-that-i-make-a-setter-f#comment51728732_31906987">chicken" requirement</a>:</p>
  
  <blockquote>
    <p>I do not think this solves my issue. In both of your solutions, I can
    append the code t.chicken = 'hi'; print(t.chicken), and it prints hi
    without error. I do not want users to be able to make up new
    attributes like chicken.</p>
  </blockquote>