Edward Loper wrote:
> For this use case, I don't think that a direct translation of the
> overloaded-constructor design for C++ carries over into Python as a good
> design.  In particular, I think this would be better coded in Python
> using either keyword arguments, or factory methods.  I.e., I'd rather
> see the interface be either:

i agree that c++ paradigms don't necessarily fit the "python spirit", at least
directly. i'm pro different functions for different things (i.e.,
from_size_and_pos et al), and the current mechanisms fit it well enough.

but i just wanted to note one case where i wish i has overloading:constructors.
for example, the socket class:

class _socketobject(object):
   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 dup(self):
       return _socketobject(_sock=self._sock)

for once, you want
s = socket.socket(AF_INET, SOCK_STREAM)
i.e., creating a NEW socket.

but you also want to be able to wrap existing objects or to initialize them
externally, i.e., just create an instance of the class and the actual
initialization would be done by *your* code, not __init__'s. the latter
case can be achieved with cls.__new__(cls), but it's kind of ugly...

what i'd like is

class _socketobject(object):
   @overload
   def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0):
       ... create a NEW socket

   @overload
   def __init__(self, existing_sock):
        ... wrap an existing sockets

this is one point that keyword arguments by themselves can't solve the
problem.

but apart from constructors, i can't think of any case where
from_size_and_point isn't the best solution.



-tomer

> From: Talin <talin <at> acm.org>
> Subject: Use case for generics
> Newsgroups: gmane.comp.python.python-3000.devel
> Date: 2006-05-13 21:08:22 GMT (20 hours and 2 minutes ago)
>
> One way of thinking about generic functions is that they are the dynamic
> languages' equivalent to C++ function overloading. Now, there are lots
> of valid (and some not-so-valid) use cases for function overloading; I'm
> just going to pick one of the most common ones.
>
> Many GUI libraries have the concept of a "Rectangle" class which
> represents the area of a widget. Typically, a rectangle can be
> constructed in several ways:
>
> 1) From 4 scalars:
>
>      r = Rectangle( x, y, w, h )
>
> 2) From two points, representing the top left and lower right corners:
>
>      r = Rectangle( minpos, maxpos )
>
> 3) From a position and a size:
>
>      r = Rectangle( position, size )
>
> In order to support this last use case, a special "Size" class is
> defined which is distinct from the "Point" class, and which has "width,
> height" members instead of "x, y" members. (Essentiallly points and
> sizes are both 2D vectors, where points represent absolute locations and
> sizes represent relative locations.)
>
> The following is an implementation, in Python, of a hypothetical
> Rectangle class using generic functions, followed by the same class
> without generics. I've tried my best to make the non-generic version as
> non-obfuscated as possible, so that the comparison would be fair.
>
> (The non-generic version doesn't support keyword args, because I
> couldn't figure out how to do it cleanly; but I'm not sure whether the
> generic version would support keywords or not.)
>
> (And I apologize that my whitespace conventions don't match the
> standard; I work hard to fix that in the PEPs, but its too much effort
> to fix that for this example.)
>
> # Indicates a location in 2D space
> class Point( object ):
>      __slots__ = ( 'x', 'y' )
>
>      def __init__( self, x, y ):
>          self.x = x
>          self.y = y
>
> # The size of an item in 2D space
> class Size( object ):
>      __slots__ = ( 'w', 'h' )
>
>      def __init__( self, w, h ):
>          self.w = w
>          self.h = h
>
> # A rectanglar area in 2D space
> class Rectangle( object ):
>      __slots__ = ( 'x', 'y', 'w', 'h' )
>
>      def __init__( self, x=0, y=0, w=0, h=0 ):
>          self.x = x
>          self.y = y
>          self.w = w
>          self.h = h
>
>      def __init__( self, position:Point, size:Size ):
>          self.x, self.y = position.x, position.y
>          self.w, self.h = size.w, size.h
>
>      def __init__( self, ulpos:Point, lrpos:Point ):
>          self.x, self.y = ulpos.x, lrpos.y
>          self.w = lrpos.x - ulpos.x
>          self.h = lrpos.y - ulpos.y
>
> # Same implementation but without generics
> class Rectangle( object ):
>      __slots__ = ( 'x', 'y', 'w', 'h' )
>
>      def __init__( self, *args ):
>          if len( args ) == 2 and isinstance( args[ 0 ], Point ):
>              if isinstance( args[ 1 ], Point ):
>                  self.from_ul_lr( *args )
>              elif isinstance( args[ 1 ], Size ):
>                  self.from_pos_size( *args )
>              else:
>                  raise TypeError
>          else:
>              self.from_scalars( *args )
>
>      def from_scalars( self, x=0, y=0, w=0, h=0 ):
>          self.x = x
>          self.y = y
>          self.w = w
>          self.h = h
>
>      def from_pos_size( self, position:Point, size:Size ):
>          self.x, self.y = position.x, position.y
>          self.w, self.h = size.w, size.h
>
>      def from_ul_lr( self, ulpos:Point, lrpos:Point ):
>          self.x, self.y = ulpos.x, lrpos.y
>          self.w = lrpos.x - ulpos.x
>          self.h = lrpos.y - ulpos.y
>
> -- Talin
>
_______________________________________________
Python-3000 mailing list
Python-3000@python.org
http://mail.python.org/mailman/listinfo/python-3000
Unsubscribe: 
http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com

Reply via email to