Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Help Analyzing some code ...

iwilld0itiwilld0it Posts: 1,134Member
Ive been analyzing the pythonwin libraries (since no documentation exists) ... i was wondering if anyone can help me decipher the code below so that I have a better understanding ...

[code]

class Object:
def __init__(self, initObj = None):
self.__dict__['_obj_'] = initObj
# self._obj_ = initObj
if initObj is not None: initObj.AttachObject(self)
def __del__(self):
self.close()
def __getattr__(self, attr): # Make this object look like the underlying win32ui one.
# During cleanup __dict__ is not available, causing recursive death.
if attr != '__dict__':
try:
o = self.__dict__['_obj_']
if o is not None:
return getattr(o, attr)
# Only raise this error for non "internal" names -
# Python may be calling __len__, __nonzero__, etc, so
# we dont want this exception
if attr[0]!= '_' and attr[-1] != '_':
raise win32ui.error, "The MFC object has died."
except KeyError:
# No _obj_ at all - dont report MFC object died when there isnt one!
pass
raise AttributeError, attr

def OnAttachedObjectDeath(self):
# print "object", self.__class__.__name__, "dieing"
self._obj_ = None
def close(self):
if self.__dict__.has_key('_obj_'):
if self._obj_ is not None:
self._obj_.AttachObject(None)
self._obj_ = None

[/code]

I know how __init__ and __del__ works.

I im not really sure how __getattr__ and __dict__ work and what the programmer is trying to do in the __getattr__ method. Thank you.


Comments

  • infidelinfidel Posts: 2,900Member
    : Ive been analyzing the pythonwin libraries (since no documentation exists) ... i was wondering if anyone can help me decipher the code below so that I have a better understanding ...
    :
    : [code]
    :
    : class Object:
    : def __init__(self, initObj = None):
    : self.__dict__['_obj_'] = initObj
    : # self._obj_ = initObj
    : if initObj is not None: initObj.AttachObject(self)
    : def __del__(self):
    : self.close()
    : def __getattr__(self, attr): # Make this object look like the underlying win32ui one.
    : # During cleanup __dict__ is not available, causing recursive death.
    : if attr != '__dict__':
    : try:
    : o = self.__dict__['_obj_']
    : if o is not None:
    : return getattr(o, attr)
    : # Only raise this error for non "internal" names -
    : # Python may be calling __len__, __nonzero__, etc, so
    : # we dont want this exception
    : if attr[0]!= '_' and attr[-1] != '_':
    : raise win32ui.error, "The MFC object has died."
    : except KeyError:
    : # No _obj_ at all - dont report MFC object died when there isnt one!
    : pass
    : raise AttributeError, attr
    :
    : def OnAttachedObjectDeath(self):
    : # print "object", self.__class__.__name__, "dieing"
    : self._obj_ = None
    : def close(self):
    : if self.__dict__.has_key('_obj_'):
    : if self._obj_ is not None:
    : self._obj_.AttachObject(None)
    : self._obj_ = None
    :
    : [/code]
    :
    : I know how __init__ and __del__ works.
    :
    : I im not really sure how __getattr__ and __dict__ work and what the programmer is trying to do in the __getattr__ method. Thank you.

    __dict__ is where an object stores it's instance variables. When you use dot notation to refer to an attribute of an object, Python looks in object.__dict__

    For example:

    [code]
    >>> class A:
    ... def __init__(self):
    ... self.foo = 'foo'
    ...
    >>> a = A()
    >>> a.__dict__
    {'foo': 'foo'}
    >>> a.bar = 'bar'
    >>> a.__dict__
    {'foo': 'foo', 'bar': 'bar'}
    >>>
    [/code]

    So when this class is instantiated, you pass it some other object, initObj. The instance then adds it to it's own __dict__, making it an instance variable. self.__dict__['name'] = value is basically the same as self.name = value. I'm not sure why the chose the former over the latter.

    __getattr__ is called when someone tries to access an instance attribute that the object doesn't have. Since this class is wrapping another object, if someone refers to obj.foo, __getattr__ is called and passed "foo" as the name. Then the class checks it's own __dict__ for an item named _obj_. If it has one, it calls getattr() which is a builtin function that returns an object attribute by name. That's basically what it's doing. Wrapping an object in another object and redirecting attribute references to the wrapped object.

    One of my books has a great example that shows how useful the getattr() function is. It's a simple chatroom server where the users issue commands in their clients like "say foobar" or "login username". The server picks off the first word of the client input and then calls getattr(self, 'handle_' + command) to try to find a function within itself that can handle the client command (i.e. handle_say, handle_login, etc). If there is one, getattr returns a function object, which I think we covered in the past. It's really pretty cool, especially compared to how difficult the equivalent functionality is in other languages.


    [size=5][italic][blue][RED]i[/RED]nfidel[/blue][/italic][/size]

Sign In or Register to comment.