The _socketobject class has no need for a __del__ method: all it did was
to delete the reference to self._sock, and the regular destructor will
do that just fine.  This made some hacks in close() unnecessary.

The _fileobject class still has a __del__ method, because it must flush.
diff --git a/Lib/socket.py b/Lib/socket.py
index 0daeadc..3611c43 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -136,30 +136,26 @@
     'recv', 'recvfrom', 'send', 'sendall', 'sendto', 'setblocking',
     'settimeout', 'gettimeout', 'shutdown')
 
+class _closedsocket(object):
+    __slots__ = []
+    def __getattr__(self, name):
+        raise error(9, 'Bad file descriptor')
+
 class _socketobject(object):
 
     __doc__ = _realsocket.__doc__
 
     __slots__ = ["_sock"]
 
-    class _closedsocket(object):
-        __slots__ = []
-        def __getattr__(self, name):
-            raise error(9, 'Bad file descriptor')
-
     def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
         if _sock is None:
             _sock = _realsocket(family, type, proto)
         self._sock = _sock
 
     def close(self):
-        # Avoid referencing globals here
-        self._sock = self.__class__._closedsocket()
+        self._sock = _closedsocket()
     close.__doc__ = _realsocket.close.__doc__
 
-    def __del__(self):
-        self.close()
-
     def accept(self):
         sock, addr = self._sock.accept()
         return _socketobject(_sock=sock), addr