title: Python 3 - Check class attribute without calling __getattr__
body: <p>TL;DR: Are there alternatives to <code>hasattr</code> which don't trigger property getters?</p>
  
  <p>I'm writing a Python interface to some existing code where I am getting and setting values for various shape and section classes. Due to a large number of possible combinations, I currently create new classes dynamically, subclassing a <code>SectionHandler</code> class and shape class, such as <code>Circle</code>. Each has specific methods that I want to preserve.</p>
  
  <p>As this API will be used in scripts and interactively, I want to make sure that any attributes modified after class instantiation already exists (so that new attributes can't be created from typos and the user is warned when a non-existent attribute is specified). Since this check needs to 'skip' all the new attributes being added during sub-classing, I preload the attributes into the new class using the attributes dictionary in the <code>type</code> function (represented below by the <code>name</code> and <code>index</code> attributes).</p>
  
  <p>I'm using <code>hasattr</code> to check if the attribute exists in the created class by overriding <code>__setattr__</code>, as suggested in <a href="https://stackoverflow.com/questions/3137558/python-can-a-class-forbid-clients-setting-new-attributes">this SO post</a>. This works when the attribute does not exist but the issue is when the attribute does exist - since <code>hasattr</code> seems to work by calling the property getter, I get extraneous logging calls from the getter, which pollutes the log over many attribute modifications (especially for longer messages).</p>
  
  <p>Is there another way to check for a class attribute in dynamically generated classes? I tried looking in <code>self.__dict__</code> instead of using <code>hasattr</code> but that dictionary is empty at class creation time. What alternatives are there?</p>
  
  <p>I've tried to give a minimal working example that reflects the structure I'm working with below:</p>
  
  <pre><code>import logging
  
  class CurveBase:
      """Base class for all curves/shapes."""
      def __setattr__(self, attr, value):
          """Restrict to setting of existing attributes only."""
          if hasattr(self, attr):
              return super().__setattr__(attr, value)
          else:
              raise AttributeError(f'{attr} does not exist in {self.__class__.__name__}')
  
  
  class Circle(CurveBase):
      """Circle-type shape base class."""
      @property
      def diameter(self):
          logging.info(f'Getting {self.name} section {self.index} diameter')
          # diameter = external_getter("Circle_Diameter")
          # return diameter
  
      @diameter.setter
      def diameter(self, diameter):
          logging.info(f'Setting {self.name} section {self.index} diameter to: {diameter}')
          # external_setter("Circle_Diameter", diameter)
  
  
  class SectionHandler:
      def __init__(self):
          # Minimal example init
          self.name = 'section_1'
          self.index = 1
  
  
  if __name__ == '__main__':
      # This is set up by the API code
      logging.basicConfig(level='INFO', format='%(asctime)s - %(levelname)s - %(message)s')
      shape = 'circle'
      attribute_dict = {'name': None, 'index': None}  # Generated based on classes used.
      NewSectionClass = type(f'{shape.capitalize()}Section',
                             (SectionHandler, Circle),
                             attribute_dict)
      section = NewSectionClass()
  
  
      # This is an example of API usage
      print(section.diameter)
      # Returns:
      # 2018-12-04 18:53:07,805 - INFO - Getting section_1 section 1 diameter
      # None  # &lt;-- this would be a value from external_getter
  
      section.diameter = 5
      # Returns:
      # 2018-12-04 18:53:07,805 - INFO - Getting section_1 section 1 diameter  # &lt;-- extra getter call from hasattr()!!!
      # 2018-12-04 18:53:07,805 - INFO - Setting section_1 section 1 diameter to: 5
  
      section.non_existent
      # Correctly returns:
      # Traceback (most recent call last):
      #   File "scratch_1.py", line 50, in &lt;module&gt;
      #     section.non_existent
      # AttributeError: 'CircleSection' object has no attribute 'non_existent'
  </code></pre>