Question: I am studying python, and although I think I get the whole concept and notion of Python, today I stumbled upon a piece of code that I did not fully understand:

Say I have a class that is supposed to define Circles but lacks a body:

```
class Circle():
    pass

```

Since I have not defined any attributes, how can I do this:

```
my_circle = Circle()
my_circle.radius = 12

```

The weird part is that Python accepts the above statement. I don't understand why Python doesn't raise an `undefined name error`. I do understand that via *dynamic typing* I just bind variables to objects whenever I want, but shouldn't an attribute `radius` exist in the `Circle` class to allow me to do this?

**EDIT**: Lots of wonderful information in your answers! **Thank you everyone for all those fantastic answers!** It's a pity I only get to mark one as an answer.

Answer: 
It creates a `radius` data member of `my_circle`.

If you had asked it for `my_circle.radius` it would have thrown an exception:

```
>>> print my_circle.radius # AttributeError

```

Interestingly, this does not change the class; just that one instance. So:

```
>>> my_circle = Circle()
>>> my_circle.radius = 5
>>> my_other_circle = Circle()
>>> print my_other_circle.radius # AttributeError

```
There are two types of attributes in Python - `Class Data Attributes` and `Instance Data Attributes`.

Python gives you flexibility of creating `Data Attributes` on the fly. 

Since an instance data attribute is related to an instance, you can also do that in `__init__` method or you can do it after you have created your instance..

```
class Demo(object):
    classAttr = 30
    def __init__(self):
         self.inInit = 10

demo = Demo()
demo.outInit = 20
Demo.new_class_attr = 45; # You can also create class attribute here.

print demo.classAttr  # Can access it 

del demo.classAttr         # Cannot do this.. Should delete only through class

demo.classAttr = 67  # creates an instance attribute for this instance.
del demo.classAttr   # Now OK.
print Demo.classAttr  

```

So, you see that we have created two instance attributes, one inside `__init__` and one outside, after instance is created..

But a difference is that, the instance attribute created inside `__init__` will be set for all the instances, while if created outside, you can have different instance attributes for different isntances..

This is unlike Java, where each Instance of a Class have same set of Instance Variables..

* NOTE: - While you can access a class attribute through an instance, you cannot delete it..
Also, if you try to modify a class attribute through an instance, you actually create an instance attribute which shadows the class attribute..