Why the object still works correctly without a class

I am new to Python. After reading some chapters of the Python Tutorial Release 2.7.5, I got confused about the scope and spaces of Python. This question may be duplicated because I do not know what to look for.

I created a class and an instance. Then I deleted the class using del . But the instance is still working correctly. What for?

 >>>class MyClass: # define a class ... def greet(self): ... print 'hello' ... >>>instan = MyClass() # create an instantiation >>>instan <__main__.MyClass instance at 0x00BBCDC8> >>>instan.greet() hello >>>dir() ['instan', 'MyClass', '__builtins__', '__doc__', '__name__', '__package__'] >>> >>> >>>del MyClass >>>dir() ['instan', '__builtins__', '__doc__', '__name__', '__package__'] >>>instan <__main__.MyClass instance at 0x00BBCDC8> # Myclass doesn't exist! >>>instan.greet() hello 

I know little about OOP, so this question may seem simple. Thanks in advance.

+7
python
source share
3 answers

Python is a garbage collector . When you execute del MyClass , you are not actually deleting the โ€œclass objectโ€ (classes are also objects), but you are only deleting the โ€œnameโ€ MyClass from the current namespace, which is a kind of reference to the class object. Any object stays alive as long as while referring to something. Because instances refer to their own class, the class will remain alive as long as at least one instance exists.

Caution when you override a class (for example, on the command line):

 In [1]: class C(object): ...: def hello(self): ...: print 'I am an instance of the old class' In [2]: c = C() In [3]: c.hello() I am an instance of the old class In [4]: class C(object): # define new class and point C to it ...: def hello(self): ...: print 'I am an instance of the new class' In [5]: c.hello() # the old object does not magically become a new one I am an instance of the old class In [6]: c = C() # point c to new object, old class and object are now garbage In [7]: c.hello() I am an instance of the new class 

Any existing instances of the old class will still have the same behavior, which makes sense considering what I mentioned. The relationship between namespaces and objects is a bit specific to python, but not as complicated as you get it. A good explanation is given here .

+9
source share

When you delete a variable using del , you delete the variable name and your own reference to the object in the variable, and not to the object itself.

The created object still contains its own class reference. In general, as long as someone still contains a reference to any object (including the class definition), it will not be deleted by the garbage collector.

+3
source share

Python does not store values โ€‹โ€‹in variables, assigns names to objects. The locals () function will return all the names in the current namespace (or, more precisely, the current scope). Let's start a new interpreter session and see what locals() gives us.

 >>> locals() {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None} 

The only names currently in the namespace are created in the names that Python puts there at startup. Here's a quick one-liner to show us only the names we assigned:

 >>> {k:v for k,v, in locals().iteritems() if k[0] != '_'} {} 

This is better. Don't worry about how one liner works, let's move on and create a class.

 >>> class C(object): greeting = "I'm the first class" 

When we define a class, it calls it in places in the current area:

 >>> {k:v for k,v, in locals().iteritems() if k[0] != '_'} {'C': <class '__main__.C'>} 

Part is Python's way of saying that there is an object that is too large to print, but it is an object of the class that we defined. Let's look at the memory address in which our class object is stored. We can use the id () function to find out.

 >>> id(C) 18968856 

The number returned by id() is the memory address of the argument. If you run these commands yourself, you will see a different number, but the number will not change in one session.

 >>> id(C) 18968856 

Now create an instance.

 >>> c = C() >>> c.greeting "I'm the first class" 

Now, when we look at locals() , we can see both our class object and our instance of the object.

 >>> {k:v for k,v, in locals().iteritems() if k[0] != '_'} {'C': <class '__main__.C'>, 'c': <__main__.C object at 0x011BDED0>} 

Each instance object has a special member __class__ , which is a reference to an object of the class whose instance is an instance.

 >>> c.__class__ <class '__main__.C'> 

If we call id() this variable, we can see a reference to the C class that we just defined:

 >>> id(c.__class__) 18968856 >>> id(c.__class__) == id(C) True 

Now let's remove the name C from the local namespace:

 >>> del C >>> {k:v for k,v, in locals().iteritems() if k[0] != '_'} {'c': <__main__.C object at 0x011BDED0>} >>> C Traceback (most recent call last): File "<pyshell#16>", line 1, in <module> C NameError: name 'C' is not defined 

That is what we expect. The name C no longer tied to anything. However, our instance still has a reference to the class object.

 >>> c.__class__ <class '__main__.C'> >>> id(c.__class__) 18968856 

As you can see, the class still exists, you simply cannot reference it through the name C in the local namespace.

Create a second class named C

 >>> class C(object): greeting = "I'm the second class" >>> {k:v for k,v, in locals().iteritems() if k[0] != '_'} {'C': <class '__main__.C'>, 'c': <__main__.C object at 0x011BDED0>} 

If we create an instance of the second class, it will behave as you noticed:

 >>> c2 = C() >>> c2.greeting "I'm the second class" >>> c.greeting "I'm the first class" 

To understand why, look at the id this new class. We see that the new class object is stored elsewhere from our first.

 >>> id(C) 19011568 >>> id(C) == id(C.__class__) False 

This is why instances can work fine: both objects of the class still exist separately, and each instance contains a reference to its object.

+1
source share

All Articles