⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sect13.htm

📁 this is the most basic to learn python
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:TIPython.rtf
Application Directory:c:\tools\rtf2html\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:12/31/2001
Translation Time:08:24:14
Translation Platform:Win32
Number of Output files:18
This File:Sect13.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>11: Multiple dispatching</TITLE>

<script language="JavaScript">
</script>
</head>


<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
    <!-- [ <a href="README.txt">Viewing Hints</a> ]
    [ <a href="RevisionHistory.htm">Revision History</a> ] -->
    [ <a href="http://www.mindview.net/Books/TIPython/">Book Home Page</a> ]
    [ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
    [ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/Services">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  Thinking in Python<br>
  <small>Revision 0.1.2 (12/31/01) -- Incomplete and Unfinished</small></FONT></H2>
  <H3><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  by Bruce Eckel &copy;2002 MindView, Inc.</FONT></H3>
  
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
     [ <a href="Sect12.htm">Previous Chapter</a> ] 
    
    [ <a href="javascript:window.location.href = 'Index.htm';">Table of Contents</a> ] 
  
        [ <a href="DocIdx.htm">Index</a> ]
        
     [ <a href="Sect14.htm">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="_Toc476705916"></A><A NAME="_Toc534420128"></A><A NAME="Heading79"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H1 ALIGN="LEFT">
11: Multiple dispatching</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When dealing with multiple types which
are interacting, a program can get particularly messy. For example, consider a
system that parses and executes mathematical expressions. You want to be able to
say <B>Number + Number</B>, <B>Number * Number</B>, etc., where <B>Number</B> is
the base class for a family of numerical objects. But when you say <B>a + b</B>,
and you don&#146;t know the exact type of either <B>a</B> or <B>b</B>, so how
can you get them to interact properly?
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_323">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The answer starts with something you
probably don&#146;t think about: Python performs only single dispatching. That
is, if you are performing an operation on more than one object whose type is
unknown, Python can invoke the dynamic binding mechanism on only one of those
types. This doesn&#146;t solve the problem, so you end up detecting some types
manually and effectively producing your own dynamic binding behavior.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_324">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The solution is called
<A NAME="Index27"></A><A NAME="Index28"></A><I>multiple dispatching</I>.
Remember that polymorphism can occur only via member function calls, so if you
want double dispatching to occur, there must be two member function calls: the
first to determine the first unknown type, and the second to determine the
second unknown type. With multiple dispatching, you must have a polymorphic
method call to determine each of the types. Generally, you&#146;ll set up a
configuration such that a single member function call produces more than one
dynamic member function call and thus determines more than one type in the
process. To get this effect, you need to work with more than one polymorphic
method call: you&#146;ll need one call for each dispatch. The methods in the
following example are called <B>compete(&#160;) </B>and <B>eval(&#160;)</B>, and
are both members of the same type. (In this case there will be only two
dispatches, which is referred to as
<A NAME="Index29"></A><A NAME="Index30"></A><I>double dispatching</I>). If you
are working with two different type hierarchies that are interacting, then
you&#146;ll have to have a polymorphic method call in each hierarchy.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_325">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here&#146;s an example of multiple
dispatching:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: c11:PaperScissorsRock.py
# Demonstration of multiple dispatching.
<font color=#0000ff>from</font> __future__ <font color=#0000ff>import</font> generators
<font color=#0000ff>import</font> random

# An enumeration type:
<font color=#0000ff>class</font> Outcome:
  <font color=#0000ff>def</font> __init__(self, value, name): 
    self.value = value
    self.name = name
  <font color=#0000ff>def</font> __str__(self): <font color=#0000ff>return</font> self.name 
  <font color=#0000ff>def</font> __eq__(self, other):
      <font color=#0000ff>return</font> self.value == other.value

Outcome.WIN = Outcome(0, <font color=#004488>"win"</font>)
Outcome.LOSE = Outcome(1, <font color=#004488>"lose"</font>)
Outcome.DRAW = Outcome(2, <font color=#004488>"draw"</font>)

<font color=#0000ff>class</font> Item(object):
  <font color=#0000ff>def</font> __str__(self): 
    <font color=#0000ff>return</font> self.__class__.__name__ 

<font color=#0000ff>class</font> Paper(Item):
  <font color=#0000ff>def</font> compete(self, item):
    # First dispatch: self was Paper
    <font color=#0000ff>return</font> item.evalPaper(self)
  <font color=#0000ff>def</font> evalPaper(self, item):
    # Item was Paper, we're <font color=#0000ff>in</font> Paper
    <font color=#0000ff>return</font> Outcome.DRAW
  <font color=#0000ff>def</font> evalScissors(self, item):
    # Item was Scissors, we're <font color=#0000ff>in</font> Paper
    <font color=#0000ff>return</font> Outcome.WIN
  <font color=#0000ff>def</font> evalRock(self, item):
    # Item was Rock, we're <font color=#0000ff>in</font> Paper
    <font color=#0000ff>return</font> Outcome.LOSE

<font color=#0000ff>class</font> Scissors(Item):
  <font color=#0000ff>def</font> compete(self, item): 
    # First dispatch: self was Scissors
    <font color=#0000ff>return</font> item.evalScissors(self)
  <font color=#0000ff>def</font> evalPaper(self, item):
    # Item was Paper, we're <font color=#0000ff>in</font> Scissors
    <font color=#0000ff>return</font> Outcome.LOSE
  <font color=#0000ff>def</font> evalScissors(self, item):
    # Item was Scissors, we're <font color=#0000ff>in</font> Scissors
    <font color=#0000ff>return</font> Outcome.DRAW
  <font color=#0000ff>def</font> evalRock(self, item):
    # Item was Rock, we're <font color=#0000ff>in</font> Scissors
    <font color=#0000ff>return</font> Outcome.WIN

<font color=#0000ff>class</font> Rock(Item):
  <font color=#0000ff>def</font> compete(self, item):
    # First dispatch: self was Rock
    <font color=#0000ff>return</font> item.evalRock(self)
  <font color=#0000ff>def</font> evalPaper(self, item):
    # Item was Paper, we're <font color=#0000ff>in</font> Rock
    <font color=#0000ff>return</font> Outcome.WIN
  <font color=#0000ff>def</font> evalScissors(self, item):
    # Item was Scissors, we're <font color=#0000ff>in</font> Rock
    <font color=#0000ff>return</font> Outcome.LOSE
  <font color=#0000ff>def</font> evalRock(self, item):
    # Item was Rock, we're <font color=#0000ff>in</font> Rock
    <font color=#0000ff>return</font> Outcome.DRAW

<font color=#0000ff>def</font> match(item1, item2):
  <font color=#0000ff>print</font> <font color=#004488>"%s &lt;--&gt; %s : %s"</font> % (
    item1, item2, item1.compete(item2))

# Generate the items:
<font color=#0000ff>def</font> itemPairGen(n):
  # Create a list of instances of all Items:
  Items = Item.__subclasses__()
  <font color=#0000ff>for</font> i <font color=#0000ff>in</font> range(n):
    <font color=#0000ff>yield</font> (random.choice(Items)(), 
           random.choice(Items)())

<font color=#0000ff>for</font> item1, item2 <font color=#0000ff>in</font> itemPairGen(20):
  match(item1, item2)
#:~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This was a fairly literal
translation from the Java version, and one of the things you might notice is
that the information about the various combinations is encoded into each type of
<B>Item</B>. It actually ends up being a kind of table, except that it is spread
out through all the classes. This is not very easy to maintain if you ever
expect to modify the behavior or to add a new <B>Item</B> class. Instead, it can
be more sensible to make the table explicit, like this:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_326">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: c11:PaperScissorsRock2.py

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -