title: How does __setattr__ work with class attributes?
body: <p>I am trying to understand how exactly __setattr__ works with class attributes. This question came about when I had attempted to override __setattr__ to prevent attributes from being written to in a simple class.</p>
  
  <p>My first attempt used instance level attributes as follows:</p>
  
  <pre><code>class SampleClass(object):
  
      def __init__(self):
          self.PublicAttribute1 = "attribute"
  
      def __setattr__(self, key, value):
          raise Exception("Attribute is Read-Only")
  </code></pre>
  
  <p>I had originally thought that only external attempts to set the attribute would throw an error, but even the statement inside the __init__ caused the exception to be thrown.</p>
  
  <p>Later I ended up finding another way to do this, while attempting to solve a different problem. What I ended up with was:</p>
  
  <pre><code>class SampleClass(object):
      PublicAttribute1 = "attribute"
  
      def __setattr__(self, key, value):
          raise Exception("Attribute is Read-Only")
  </code></pre>
  
  <p>I expected to get the same result, but to my surpirse I was able to set the class attribute while preventing changes from being made after the initial declaration. </p>
  
  <p>I don't understand why this works though. I know it has to do with class vs. instance variables. My theory is that using __setattr__ on a class variable will create an instance variable of the same name, since I believe I think I have seen this behavior before, but I am not sure.</p>
  
  <p>Can anyone explain exactly what is happening here?</p>