On Mon, Aug 26, 2002 at 08:39:44PM -0500, jepler@unpythonic.net wrote: > On Mon, Aug 26, 2002 at 05:56:52PM -0400, Guido van Rossum wrote: > > > It gets harder if you want to remove a method or marker. The problem is > > > that there is currently no way to mask inherited attributes. This will > > > require either a language extension that will allow you to del them or > > > using some other convention for this purpose. > > > > Can't you use this? > > > > def B: > > def foo(self): pass > > > > def C: > > foo = None # Don't implement foo > > This comes closer: > > def raise_attributeerror(self): > raise AttributeError > > RemoveAttribute = property(raise_attributeerror) > > class A: > def f(self): print "method A.f" > def g(self): print "method A.g" > > class B: > f = RemoveAttribute Yes, that's a good solution. But it should be some special builtin out-of-band value, not a user-defined property. > writing 'b.f' will raise AttributeError, but unfortunately hasattr(B, 'f') > will still return True. This isn't necessarily a problem but hasattr could be taught about this out-of-band value. -- Proposed hierarchy for categories, types and interfaces: +category +type +int +str etc. +interface +Iattribute +Icallsignature +Iunion +Iintersection etc. Both types and interfaces define a set. The set membership test is the 'isinstance' function (implemented by a new slot). For types the set membership is defined by inheritance - the isinstance handler will get the first argument's type and crawl up the __bases__ DAG to see if it finds the itself. Interfaces check the object's form instead of its ancestry. An Iattribute interface checks for the presence of a single attribute and applies another interface check to its value. An Icallsignature interface checks if the argument is a callable object with a specified number of arguments, default arguments, etc. An Iintersection interface checks that the argument matches a set of categories. example: interface readable: def read(bytes: int): str def readline(): str def readlines(): [str] is just a more convenient way to write: readable = Iintersection( Iattribute('read', Icallsignature(str, ('bytes', int) )), Iattribute('readline', Icallsignature(str)), Iattribute('readlines', Icallsignature(Ilistof(str))) ) The name 'readable' is simply bound to the resulting object; interfaces are defined by their value, not their name. The types of arguments and return values will not be checked at first and only serve as documentation. Note that they don't necessarily have to be types - they can be interfaces, too. For example, 'str|int' in an interface declaration will be coverted to Iunion(str, int). >>>isinstance(file('/dev/null'), readable) True >>>isinstance(MyFileLikeClass(), readable) True The MyFileLIkeClass or file classes do not have to be explicitly declared as implementing the readable interface. The benefit of explit inteface declarations is that you will get an error if you write a method that does not match the declaration. If you try to implement two conflicting interfaces this can also be detected immediately - the intersection of the two interfaces will reduce to the empty interface. For now this will only catch the same method name with different number of arguments but in the future it may detect conflicting argument or return value types. doesn't-have-anything-better-to-do-at-6-am-ly yours, Oren
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4