📄 sect09.htm
字号:
<!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:13
Translation Platform:Win32
Number of Output files:18
This File:Sect09.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>6: Function objects</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 ©2002 MindView, Inc.</FONT></H3>
<FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
[ <a href="Sect08.htm">Previous Chapter</a> ]
[ <a href="javascript:window.location.href = 'Index.htm';">Table of Contents</a> ]
[ <a href="DocIdx.htm">Index</a> ]
[ <a href="Sect10.htm">Next Chapter</a> ]
</FONT>
</CENTER>
</P></DIV><A NAME="_Toc462393592"></A><A NAME="_Toc462393593"></A><A NAME="_Toc476705905"></A><A NAME="_Toc534420112"></A><A NAME="Heading63"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H1 ALIGN="LEFT">
6: Function objects</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <I>Advanced C++:Programming Styles And
Idioms (Addison-Wesley, 1992)</I>, Jim Coplien coins the term <I>functor</I>
which is an object whose sole purpose is to encapsulate a function (since
“functor” has a meaning in mathematics, in this book I shall use the
more explicit term <I>function object</I>). The point is to decouple the choice
of function to be called from the site where that function is called.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_269">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This term is mentioned but not used in
<I>Design Patterns</I>. However, the theme of the function object is repeated in
a number of patterns in that book.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_270">Add Comment</A></FONT><A NAME="_Toc476705906"></A><A NAME="_Toc534420113"></A><BR></P></DIV>
<A NAME="Heading64"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Command: choosing the operation at run-time</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is the function object in its purest
sense: a method that’s an
object</FONT><A NAME="fnB14" HREF="#fn14">[14]</A><FONT FACE="Georgia">. By
wrapping a method in an object, you can pass it to other methods or objects as a
parameter, to tell them to perform this particular operation in the process of
fulfilling your request.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_271">Add Comment</A></FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: c06:CommandPattern.py
<font color=#0000ff>class</font> Command:
<font color=#0000ff>def</font> execute(self): <font color=#0000ff>pass</font>
<font color=#0000ff>class</font> Loony(Command):
<font color=#0000ff>def</font> execute(self):
<font color=#0000ff>print</font> <font color=#004488>"You're a loony."</font>
<font color=#0000ff>class</font> NewBrain(Command):
<font color=#0000ff>def</font> execute(self):
<font color=#0000ff>print</font> <font color=#004488>"You might even need a new brain."</font>
<font color=#0000ff>class</font> Afford(Command):
<font color=#0000ff>def</font> execute(self):
<font color=#0000ff>print</font> <font color=#004488>"I couldn't afford a whole new brain."</font>
# An object that holds commands:
<font color=#0000ff>class</font> Macro:
<font color=#0000ff>def</font> __init__(self):
self.commands = []
<font color=#0000ff>def</font> add(self, command):
self.commands.append(command)
<font color=#0000ff>def</font> run(self):
<font color=#0000ff>for</font> c <font color=#0000ff>in</font> self.commands:
c.execute()
macro = Macro()
macro.add(Loony())
macro.add(NewBrain())
macro.add(Afford())
macro.run()
#:~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The primary point of
<I>Command</I> is to allow you to hand a desired action to a method or object.
In the above example, this provides a way to queue a set of actions to be
performed collectively. In this case, it allows you to dynamically create new
behavior, something you can normally only do by writing new code but in the
above example could be done by interpreting a script (see the <I>Interpreter</I>
pattern if what you need to do gets very complex).
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_272">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><I>Design Patterns</I> says that
“Commands are an object-oriented replacement for
callbacks</FONT><A NAME="fnB15" HREF="#fn15">[15]</A><FONT FACE="Georgia">.”
However, I think that the word “back” is an essential part of the
concept of callbacks. That is, I think a callback actually reaches back to the
creator of the callback. On the other hand, with a <I>Command</I> object you
typically just create it and hand it to some method or object, and are not
otherwise connected over time to the <I>Command</I> object. That’s my take
on it, anyway. Later in this book, I combine a group of design patterns under
the heading of “callbacks.”
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_273">Add Comment</A></FONT><A NAME="_Toc462393594"></A><A NAME="_Toc476705907"></A><A NAME="_Toc534420114"></A><BR></P></DIV>
<A NAME="Heading65"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Strategy: choosing the algorithm at run-time</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><I>Strategy</I> appears to be a family of
<I>Command</I> classes, all inherited from the same base. But if you look at
<I>Command</I>, you’ll see that it has the same structure: a hierarchy of
function objects. The difference is in the way this hierarchy is used. As seen
in <B>c12:DirList.py</B>, you use <I>Command</I> to solve a particular
problem—in that case, selecting files from a list. The “thing that
stays the same” is the body of the method that’s being called, and
the part that varies is isolated in the function object. I would hazard to say
that <I>Command</I> provides flexibility while you’re writing the program,
whereas <I>Strategy</I>’s flexibility is at run time.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_274">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><I>Strategy</I> also adds a
“Context” which can be a surrogate class that controls the selection
and use of the particular strategy object—just like <I>State</I>!
Here’s what it looks like:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_275">Add Comment</A></FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: c06:StrategyPattern.py
# The strategy interface:
<font color=#0000ff>class</font> FindMinima:
# Line <font color=#0000ff>is</font> a sequence of points:
<font color=#0000ff>def</font> algorithm(self, line) : <font color=#0000ff>pass</font>
# The various strategies:
<font color=#0000ff>class</font> LeastSquares(FindMinima):
<font color=#0000ff>def</font> algorithm(self, line):
<font color=#0000ff>return</font> [ 1.1, 2.2 ] # Dummy
<font color=#0000ff>class</font> NewtonsMethod(FindMinima):
<font color=#0000ff>def</font> algorithm(self, line):
<font color=#0000ff>return</font> [ 3.3, 4.4 ] # Dummy
<font color=#0000ff>class</font> Bisection(FindMinima):
<font color=#0000ff>def</font> algorithm(self, line):
<font color=#0000ff>return</font> [ 5.5, 6.6 ] # Dummy
<font color=#0000ff>class</font> ConjugateGradient(FindMinima):
<font color=#0000ff>def</font> algorithm(self, line):
<font color=#0000ff>return</font> [ 3.3, 4.4 ] # Dummy
# The <font color=#004488>"Context"</font> controls the strategy:
<font color=#0000ff>class</font> MinimaSolver:
<font color=#0000ff>def</font> __init__(self, strategy):
self.strategy = strategy
<font color=#0000ff>def</font> minima(self, line):
<font color=#0000ff>return</font> self.strategy.algorithm(line)
<font color=#0000ff>def</font> changeAlgorithm(self, newAlgorithm):
self.strategy = newAlgorithm
solver = MinimaSolver(LeastSquares())
line = [
1.0, 2.0, 1.0, 2.0, -1.0, 3.0, 4.0, 5.0, 4.0
]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -