[OPINION] - does language really matter if they all do the samething?
Greg Ewing (using news.cis.dfn.de)
g2h5dqi002 at sneakemail.com
Wed Feb 11 22:14:47 EST 2004
Dietrich Epp wrote:
> In Objective C, I can create an object which doesn't respond to some
> message "foo". However, if I send "foo" to the object, it gets a chance
> to respond. In Python, there is no concept of messages. You would have
> to override the function that gets an object's attribute and create a
> function for it to return. You can capture function calls, but
> capturing method calls is a two-step process in Python which requires a
> little bit of magic to implement.
It's slightly more convoluted, but not all that bad:
class Foo(object):
def __getattr__(self, name):
def f(*args, **kwds):
return self.message_not_understood(name, *args, **kwds)
return f
def message_not_understood(self, name, *args, **kwds):
# Do whatever you want here
print self, "does not understand", name, args, kwds
If you use this a lot, you can put it in a small mixin class for
incorporating in your other classes. (That's something you couldn't
do in Smalltalk, btw -- multiple inheritance!)
> In Objective C:
>
> - (void)forwardInvocation:(NSInvocation *)invocation
> {
> if ([someOtherObject respondsToSelector:[invocation selector]])
> [invocation invokeWithTarget:someOtherObject];
> else
> [self doesNotRecognizeSelector:[invocation selector]];
> }
>
> In Python:
>
> def __getattr__(self, name):
> try:
> return super(this_class, self).__getattr__(name)
> except AttributeError:
> try:
> method = super(this_class,
> self).some_other_object.__getattr(name)
> if iscallable(method):
> return method
> except:
> pass
> raise
Here you're thinking in terms of the Objective-C way of doing things
and trying to translate them too literally into Python. It's actually
much EASIER to do delegation in Python:
def __getattr__(self, name):
return getattr(some_other_object, name)
That's all you need!
> In Python you have to be careful because this won't normally capture
> just method calls, but all attribute accesses.
Well, if that's a concern when delegating, you'll need to do a bit of
filtering in the __getattr__. But in many cases it's a feature -- you
can easily create a proxy that transparently wraps the whole interface
of another object, including both its attributes and methods.
> In a typical Objective-C
> application you'll probably see a lot of places where the program sends
> a message to an object only if the object responds to that message.
> Let's compare.
>
> In Objective C:
>
> - (void)resetToDefaultSettings
> {
> if ([delegate respondsToSelector:@selector(defaultSettingsFor:)])
> [self setSettings:[delegate defaultSettingsFor:self]];
> else
> [self setSettings:someFallbackValue];
> }
>
> In Python, first try:
>
> def reset_settings(self):
> try:
> self.set_settings(self.delegate.default_settings(self))
> except AttributeError:
> self.set_settings(some_fallback_value)
>
> But wait! What if there is an error in self.delegate.default_settings()
> which raises an AttributeError?
I'd actually translate the Objective-C rather more literally in
this case:
if hasattr(self.delegate, 'default_settings'):
self.set_settings(self.delegate.default_settings(self))
else:
self.set_settings(some_fallback_value)
It might be a whisker slower, but doesn't suffer from the "catching the
wrong exception" problem, and (I think) is easier to read as well.
--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg
More information about the Python-list
mailing list