[ Pobierz całość w formacie PDF ]
.print n,0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987You can use a generator like fibonacci in a for loop directly.The for loop will create the generatorobject and successively call the next() method to get values to assign to the for loop index variable (n).Each time through the for loop, n gets a new value from the yield statement in fibonacci, and all you dois print it out.Once fibonacci runs out of numbers (a gets bigger than max, which in this case is 1000),then the for loop exits gracefully.OK, let's go back to the plural function and see how you're using this.Example 17.21.Generators that generate dynamic functionsdef rules(language):for line in file('rules.%s' % language):pattern, search, replace = line.split()yield lambda word: re.search(pattern, word) and re.sub(search, replace, word)def plural(noun, language='en'):for applyRule in rules(language):result = applyRule(noun)if result: return resultfor line in file(.) is a common idiom for reading lines from a file, one line at a time.Itworks becausefile actually returns a generator whose next() method returns the next line of thefile.That is so insanely cool, I wet myself just thinking about it.No magic here.Remember that the lines of the rules file have three values separated by whitespace, soline.split() returns a tuple of 3 values, and you assign those values to 3 local variables.And then you yield.What do you yield? A function, built dynamically with lambda, that is actually aclosure (it uses the local variables pattern, search, and replace as constants).In other words,rules is a generator that spits out rule functions.Since rules is a generator, you can use it directly in a for loop.The first time through the forloop, you will call the rules function, which will open the rules file, read the first line out of it,dynamically build a function that matches and applies the first rule defined in the rules file, and yieldsthe dynamically built function.The second time through the for loop, you will pick up where you leftoff in rules (which was in the middle of the for line in file(.) loop), read the secondline of the rules file, dynamically build another function that matches and applies the second ruledefined in the rules file, and yields it.And so forth.Dive Into Python 245What have you gained over stage 5? In stage 5, you read the entire rules file and built a list of all the possible rulesbefore you even tried the first one.Now with generators, you can do everything lazily: you open the first and read thefirst rule and create a function to try it, but if that works you don't ever read the rest of the file or create any otherfunctions.Further reading" PEP 255 (http://www.python.org/peps/pep-0255.html) defines generators." Python Cookbook (http://www.activestate.com/ASPN/Python/Cookbook/) has many more examples ofgenerators (http://www.google.com/search?q=generators+cookbook+site:aspn.activestate.com).17.8.SummaryYou talked about several different advanced techniques in this chapter.Not all of them are appropriate for everysituation.You should now be comfortable with all of these techniques:" Performing string substitution with regular expressions." Treating functions as objects, storing them in lists, assigning them to variables, and calling them through thosevariables." Building dynamic functions with lambda." Building closures, dynamic functions that contain surrounding variables as constants." Building generators, resumable functions that perform incremental logic and return different values each timeyou call them.Adding abstractions, building functions dynamically, building closures, and using generators can all make your codesimpler, more readable, and more flexible.But they can also end up making it more difficult to debug later.It's up toyou to find the right balance between simplicity and power.Dive Into Python 246Chapter 18.Performance TuningPerformance tuning is a many-splendored thing.Just because Python is an interpreted language doesn't mean youshouldn't worry about code optimization.But don't worry about it too much.18.1.Diving inThere are so many pitfalls involved in optimizing your code, it's hard to know where to start.Let's start here: are you sure you need to do it at all? Is your code really so bad? Is it worth the time to tune it? Overthe lifetime of your application, how much time is going to be spent running that code, compared to the time spentwaiting for a remote database server, or waiting for user input?Second, are you sure you're done coding? Premature optimization is like spreading frosting on a half-baked cake.You spend hours or days (or more) optimizing your code for performance, only to discover it doesn't do what youneed it to do.That's time down the drain.This is not to say that code optimization is worthless, but you need to look at the whole system and decide whether it'sthe best use of your time.Every minute you spend optimizing code is a minute you're not spending adding newfeatures, or writing documentation, or playing with your kids, or writing unit tests.Oh yes, unit tests.It should go without saying that you need a complete set of unit tests before you begin performancetuning.The last thing you need is to introduce new bugs while fiddling with your algorithms.With these caveats in place, let's look at some techniques for optimizing Python code.The code in question is animplementation of the Soundex algorithm.Soundex was a method used in the early 20th century for categorizingsurnames in the United States census.It grouped similar-sounding names together, so even if a name was misspelled,researchers had a chance of finding it.Soundex is still used today for much the same reason, although of course weuse computerized database servers now.Most database servers include a Soundex function.There are several subtle variations of the Soundex algorithm.This is the one used in this chapter:1.Keep the first letter of the name as-is.2.Convert the remaining letters to digits, according to a specific table:f& B, F, P, and V become 1.f& C, G, J, K, Q, S, X, and Z become 2.f& D and T become 3.f& L becomes 4.f& M and N become 5.f& R becomes 6.f& All other letters become 9.3.Remove consecutive duplicates.4.Remove all 9s altogether.5.If the result is shorter than four characters (the first letter plus three digits), pad the result with trailing zeros.6.if the result is longer than four characters, discard everything after the fourth character.For example, my name, Pilgrim, becomes P942695.That has no consecutive duplicates, so nothing to do there.Then you remove the 9s, leaving P4265.That's too long, so you discard the excess character, leaving P426.Another example: Woo becomes W99, which becomes W9, which becomes W, which gets padded with zeros tobecome W000.Dive Into Python 247Here's a first attempt at a Soundex function:Example 18.1.soundex/stage1/soundex1a [ Pobierz całość w formacie PDF ]
zanotowane.pl doc.pisz.pl pdf.pisz.pl matkasanepid.xlx.pl
.print n,0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987You can use a generator like fibonacci in a for loop directly.The for loop will create the generatorobject and successively call the next() method to get values to assign to the for loop index variable (n).Each time through the for loop, n gets a new value from the yield statement in fibonacci, and all you dois print it out.Once fibonacci runs out of numbers (a gets bigger than max, which in this case is 1000),then the for loop exits gracefully.OK, let's go back to the plural function and see how you're using this.Example 17.21.Generators that generate dynamic functionsdef rules(language):for line in file('rules.%s' % language):pattern, search, replace = line.split()yield lambda word: re.search(pattern, word) and re.sub(search, replace, word)def plural(noun, language='en'):for applyRule in rules(language):result = applyRule(noun)if result: return resultfor line in file(.) is a common idiom for reading lines from a file, one line at a time.Itworks becausefile actually returns a generator whose next() method returns the next line of thefile.That is so insanely cool, I wet myself just thinking about it.No magic here.Remember that the lines of the rules file have three values separated by whitespace, soline.split() returns a tuple of 3 values, and you assign those values to 3 local variables.And then you yield.What do you yield? A function, built dynamically with lambda, that is actually aclosure (it uses the local variables pattern, search, and replace as constants).In other words,rules is a generator that spits out rule functions.Since rules is a generator, you can use it directly in a for loop.The first time through the forloop, you will call the rules function, which will open the rules file, read the first line out of it,dynamically build a function that matches and applies the first rule defined in the rules file, and yieldsthe dynamically built function.The second time through the for loop, you will pick up where you leftoff in rules (which was in the middle of the for line in file(.) loop), read the secondline of the rules file, dynamically build another function that matches and applies the second ruledefined in the rules file, and yields it.And so forth.Dive Into Python 245What have you gained over stage 5? In stage 5, you read the entire rules file and built a list of all the possible rulesbefore you even tried the first one.Now with generators, you can do everything lazily: you open the first and read thefirst rule and create a function to try it, but if that works you don't ever read the rest of the file or create any otherfunctions.Further reading" PEP 255 (http://www.python.org/peps/pep-0255.html) defines generators." Python Cookbook (http://www.activestate.com/ASPN/Python/Cookbook/) has many more examples ofgenerators (http://www.google.com/search?q=generators+cookbook+site:aspn.activestate.com).17.8.SummaryYou talked about several different advanced techniques in this chapter.Not all of them are appropriate for everysituation.You should now be comfortable with all of these techniques:" Performing string substitution with regular expressions." Treating functions as objects, storing them in lists, assigning them to variables, and calling them through thosevariables." Building dynamic functions with lambda." Building closures, dynamic functions that contain surrounding variables as constants." Building generators, resumable functions that perform incremental logic and return different values each timeyou call them.Adding abstractions, building functions dynamically, building closures, and using generators can all make your codesimpler, more readable, and more flexible.But they can also end up making it more difficult to debug later.It's up toyou to find the right balance between simplicity and power.Dive Into Python 246Chapter 18.Performance TuningPerformance tuning is a many-splendored thing.Just because Python is an interpreted language doesn't mean youshouldn't worry about code optimization.But don't worry about it too much.18.1.Diving inThere are so many pitfalls involved in optimizing your code, it's hard to know where to start.Let's start here: are you sure you need to do it at all? Is your code really so bad? Is it worth the time to tune it? Overthe lifetime of your application, how much time is going to be spent running that code, compared to the time spentwaiting for a remote database server, or waiting for user input?Second, are you sure you're done coding? Premature optimization is like spreading frosting on a half-baked cake.You spend hours or days (or more) optimizing your code for performance, only to discover it doesn't do what youneed it to do.That's time down the drain.This is not to say that code optimization is worthless, but you need to look at the whole system and decide whether it'sthe best use of your time.Every minute you spend optimizing code is a minute you're not spending adding newfeatures, or writing documentation, or playing with your kids, or writing unit tests.Oh yes, unit tests.It should go without saying that you need a complete set of unit tests before you begin performancetuning.The last thing you need is to introduce new bugs while fiddling with your algorithms.With these caveats in place, let's look at some techniques for optimizing Python code.The code in question is animplementation of the Soundex algorithm.Soundex was a method used in the early 20th century for categorizingsurnames in the United States census.It grouped similar-sounding names together, so even if a name was misspelled,researchers had a chance of finding it.Soundex is still used today for much the same reason, although of course weuse computerized database servers now.Most database servers include a Soundex function.There are several subtle variations of the Soundex algorithm.This is the one used in this chapter:1.Keep the first letter of the name as-is.2.Convert the remaining letters to digits, according to a specific table:f& B, F, P, and V become 1.f& C, G, J, K, Q, S, X, and Z become 2.f& D and T become 3.f& L becomes 4.f& M and N become 5.f& R becomes 6.f& All other letters become 9.3.Remove consecutive duplicates.4.Remove all 9s altogether.5.If the result is shorter than four characters (the first letter plus three digits), pad the result with trailing zeros.6.if the result is longer than four characters, discard everything after the fourth character.For example, my name, Pilgrim, becomes P942695.That has no consecutive duplicates, so nothing to do there.Then you remove the 9s, leaving P4265.That's too long, so you discard the excess character, leaving P426.Another example: Woo becomes W99, which becomes W9, which becomes W, which gets padded with zeros tobecome W000.Dive Into Python 247Here's a first attempt at a Soundex function:Example 18.1.soundex/stage1/soundex1a [ Pobierz całość w formacie PDF ]