python常用工具手册(纯函数与修改器)

As one example of a programmer-defined type, we’ll define a class called Time that records the time of day. The class definition looks like this:

class Time: """Represents the time of day. attributes: hour, minute, second """

We can create a new Time object and assign attributes for hours, minutes, and seconds:

time = Time() time.hour = 11 time.minute = 59 time.second = 30

As an exercise, write a function called print_time that takes a Time object and prints it in the form hour:minute:second. Hint: the format sequence '%.2d' prints an integer using at least two digits, including a leading zero if necessary.

Write a boolean function called is_after that takes two Time objects, t1 and t2, and returns True if t1 follows t2 chronologically and False otherwise.

1 纯函数Pure functions

We’ll write two functions that add time values. They demonstrate two kinds of functions: pure functions and modifiers(修改器). They also demonstrate a development plan I’ll call prototype and patch(原型和补丁), which is a way of tackling a complex problem by starting with a simple prototype and incrementally dealing with the complications.

Here is a simple prototype of add_time:

def add_time(t1, t2): sum = Time() sum.hour = t1.hour t2.hour sum.minute = t1.minute t2.minute sum.second = t1.second t2.second return sum

The function creates a new Time object, initializes its attributes, and returns a reference to the new object. This is called a pure function because it does not modify any of the objects passed to it as arguments and it has no effect, like displaying a value or getting user input, other than returning a value.

To test this function, I’ll create two Time objects: start contains the start time of a movie, like Monty Python and the Holy Grail, and duration contains the run time of the movie, which is one hour 35 minutes.

add_time figures out when the movie will be done.

>>> start = Time() >>> start.hour = 9 >>> start.minute = 45 >>> start.second = 0 >>> duration = Time() >>> duration.hour = 1 >>> duration.minute = 35 >>> duration.second = 0 >>> done = add_time(start, duration) >>> print_time(done) 10:80:00

The result, 10:80:00 might not be what you were hoping for. The problem is that this function does not deal with cases where the number of seconds or minutes adds up to more than sixty. When that happens, we have to “carry” the extra seconds into the minute column or the extra minutes into the hour column.

Here’s an improved version:

def add_time(t1, t2): sum = Time() sum.hour = t1.hour t2.hour sum.minute = t1.minute t2.minute sum.second = t1.second t2.second if sum.second >= 60: sum.second -= 60 sum.minute = 1 if sum.minute >= 60: sum.minute -= 60 sum.hour = 1 return sum

Although this function is correct, it is starting to get big. We will see a shorter alternative later.

2 修改器Modifiers

Sometimes it is useful for a function to modify the objects it gets as parameters. In that case, the changes are visible to the caller. Functions that work this way are called modifiers.

It is legal to add attributes to objects at any point in the execution of a program。

在程序运行的任何时刻,往对象上添加属性是合法的。

increment, which adds a given number of seconds to a Time object, can be written naturally as a modifier. Here is a rough draft:

def increment(time, seconds): time.second = seconds if time.second >= 60: time.second -= 60 time.minute = 1 if time.minute >= 60: time.minute -= 60 time.hour = 1

The first line performs the basic operation; the remainder deals with the special cases we saw before.

Is this function correct? What happens if seconds is much greater than sixty?

In that case, it is not enough to carry once; we have to keep doing it until time.second is less than sixty. One solution is to replace the if statements with while statements. That would make the function correct, but not very efficient. As an exercise, write a correct version of increment that doesn’t contain any loops.

Anything that can be done with modifiers can also be done with pure functions. In fact, some programming languages only allow pure functions. There is some evidence that programs that use pure functions are faster to develop and less error-prone than programs that use modifiers. But modifiers are convenient at times, and functional programs tend to be less efficient.

In general, I recommend that you write pure functions whenever it is reasonable and resort to modifiers only if there is a compelling advantage. This approach might be called a functional programming style.(函数式编程风格)

As an exercise, write a “pure” version of increment that creates and returns a new Time object rather than modifying the parameter.

3 原型和计划 Prototyping versus planning

The development plan I am demonstrating is called “prototype and patch”. For each function, I wrote a prototype that performed the basic calculation and then tested it, patching errors along the way.

python常用工具手册(纯函数与修改器)(1)

python常用工具手册(纯函数与修改器)(2)

4 Glossary

prototype and patch:

A development plan that involves writing a rough draft of a program, testing, and correcting errors as they are found.

designed development:

A development plan that involves high-level insight into the problem and more planning than incremental development or prototype development.

pure function:

A function that does not modify any of the objects it receives as arguments. Most pure functions are fruitful.

modifier:

A function that changes one or more of the objects it receives as arguments. Most modifiers are void; that is, they return None.

functional programming style:

A style of program design in which the majority of functions are pure.

reference:

http://greenteapress.com/thinkpython2/html/thinkpython2017.html

附代码:

from __future__ import print_function, division

class Time:

...."""Represents the time of day.....

.... attributes: hour, minute, second

...."""

def print_time(t):

...."""Prints a string representation of the time.

.... t: Time object

...."""

....print('%.2d:%.2d:%.2d' % (t.hour, t.minute, t.second))

def int_to_time(seconds):

...."""Makes a new Time object.

.... seconds: int seconds since midnight.

...."""

....time = Time()

....minutes, time.second = divmod(seconds, 60)

....time.hour, time.minute = divmod(minutes, 60)

....return time

def time_to_int(time):

...."""Computes the number of seconds since midnight.

.... time: Time object.

...."""

....minutes = time.hour * 60 time.minute

....seconds = minutes * 60 time.second

....return seconds

def add_times(t1, t2):

...."""Adds two time objects.

....t1, t2: Time

....returns: Time

...."""

....assert valid_time(t1) and valid_time(t2)

....seconds = time_to_int(t1) time_to_int(t2)

....return int_to_time(seconds)

def valid_time(time):

...."""Checks whether a Time object satisfies the invariants.

....time: Time

....returns: boolean

...."""

....if time.hour < 0 or time.minute < 0 or time.second < 0:

........return False

....if time.minute >= 60 or time.second >= 60:

........return False

....return True

def main():

....# if a movie starts at noon...

....noon_time = Time()

....noon_time.hour = 12

....noon_time.minute = 0

....noon_time.second = 0

....print('Starts at', end=' ')

....print_time(noon_time)

....# and the run time of the movie is 109 minutes...

....movie_minutes = 109

....run_time = int_to_time(movie_minutes * 60)

....print('Run time', end=' ')

....print_time(run_time)

....# what time does the movie end?

....end_time = add_times(noon_time, run_time)

....print('Ends at', end=' ')

....print_time(end_time)

if __name__ == '__main__':

....main()

-End-

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页