[Interface-dev] Re: interface.py

Thomas Lotze tl at gocept.com
Mon Jul 11 05:01:10 EDT 2005


Steve Alexander wrote:

> I think it is an evil trick because it is unclear code.  Whenever someone
> write unclear code but has a reason for not using a clear alternative, it
> needs a comment to explain why.

OK, no arguing against that. Maybe I played around too much with closures
lately, so I didn't realize how unclear it was. However, I think the
explanation needn't necessarily rant on evility where it actually just
takes knowing why thing are done the way they are done.

> That's a really bad thing to do.  With your change, the dict will be
> instantiated once only, at the time the class is first read by the
> interpreter.

Damn, that's one of the things I keep forgetting :o/ Usually I trip on
something like this when I set the default for a class member that is then
changed by instances...

I've appended a corrected patch. BTW, I start wondering whether it is OK
to send patches this size in a message; would you feel more annoyed if I
uploaded them somewhere on the web? (I'd certainly be as I read mail and
news offline.)

Thomas


36,41c36,37
<     tags = f_locals.get(TAGGED_DATA)
<     if tags is None:
<         tags = f_locals[TAGGED_DATA] = {}
<     invariants = tags.get('invariants')
<     if invariants is None:
<         invariants = tags['invariants'] = []
---
>     tags = f_locals.setdefault(TAGGED_DATA, {})
>     invariants = tags.setdefault('invariants', [])
359,363c355
<         if callback is None:
<             return weakref.ref(self)
<         else:
<             return weakref.ref(self, callback)
< 
---
>         return weakref.ref(self, callback)
395a388,390
>         if attrs is None:
>             attrs = {}
> 
397,401c392,393
<             if (attrs is not None and
<                 ('__module__' in attrs) and
<                 isinstance(attrs['__module__'], str)
<                 ):
<                 __module__ = attrs['__module__']
---
>             __module__ = attrs.get('__module__')
>             if isinstance(__module__, str):
404d395
< 
415,417d405
<         if attrs is None:
<             attrs = {}
< 
430,434c418
<         if attrs.has_key(TAGGED_DATA):
<             tagged_data = attrs[TAGGED_DATA]
<             del attrs[TAGGED_DATA]
<         else:
<             tagged_data = None
---
>         tagged_data = attrs.pop(TAGGED_DATA, None)
480,481d463
< 
< 
487,489c469
<         if self == other:
<             return True
<         return other.extends(self)
---
>         return self == other or other.extends(self)
496,498c476,477
<         r = {}
<         for name in self.__attrs.keys():
<             r[name] = 1
---
>         r = self.__attrs.copy()
> 
500,501c479,480
<             for name in base.names(all):
<                 r[name] = 1
---
>             r.update(dict.fromkeys(base.names(all)))
> 
513,514c492,493
<         for name, d in self.__attrs.items():
<             r[name] = d
---
>         for base in self.__bases__[::-1]:
>             r.update(dict(base.namesAndDescriptions(all)))
516,519c495
<         for base in self.__bases__:
<             for name, d in base.namesAndDescriptions(all):
<                 if name not in r:
<                     r[name] = d
---
>         r.update(self.__attrs)
572d547
<                 pass
586c561,562
<         for b in self.__bases__: b.__d(dict)
---
>         for b in self.__bases__:
>             b.__d(dict)
589,590c565,567
<         r = getattr(self, '_v_repr', self)
<         if r is self:
---
>         try:
>             return self._v_repr
>         except AttributeError:
597c574
<         return r
---
>             return r
600,603c577,579
<         # TRICK! Create the call method
<         #
<         # An embedded function is used to allow an optional argument to
<         # __call__ without resorting to a global marker.
---
>         # Mind the closure. It serves to keep a unique marker around to
>         # allow for an optional argument to __call__ without resorting
>         # to a global marker.
605,610c581
<         # The evility of this trick is a reflection of the underlying
<         # evility of "optional" arguments, arguments whose presense or
<         # absense changes the behavior of the methods.
<         # 
<         # I think the evil is necessary, and perhaps desireable to
<         # provide some consistencey with the PEP 246 adapt method.
---
>         # This provides some consistency with the PEP 246 adapt method.
699,702c670,674
<             if adapter is None:
<                 if alternate is not marker:
<                     return alternate
<                 
---
>             if adapter is not None:
>                 return adapter
>             elif alternate is not marker:
>                 return alternate
>             else:
705,706d676
<             return adapter
< 
709c679
<     __call__ = __call__() # TRICK! Make the *real* __call__ method
---
>     __call__ = __call__() # Make the closure the *real* __call__ method.
802d771
< 
861c830
<         sig = "("
---
>         sig = []
863c832
<             sig = sig + v
---
>             sig.append(v)
865,866c834
<                 sig = sig + "=%s" % `self.optional[v]`
<             sig = sig + ", "
---
>                 sig[-1] += "=%s" % `self.optional[v]`
868c836
<             sig = sig + ("*%s, " % self.varargs)
---
>             sig.append("*%s" % self.varargs)
870,874c838
<             sig = sig + ("**%s, " % self.kwargs)
< 
<         # slice off the last comma and space
<         if self.positional or self.varargs or self.kwargs:
<             sig = sig[:-2]
---
>             sig.append("**%s" % self.kwargs)
876,877c840
<         sig = sig + ")"
<         return sig
---
>         return "(%s)" % ", ".join(sig)
896,897c859
<     for i in range(len(defaults)):
<         opt[names[i+nr]] = defaults[i]
---
>     opt.update(dict(zip(names[nr:], defaults)))




More information about the Interface-dev mailing list