html tool

显示标签为“翻译,Dive Into Python”的博文。显示所有博文
显示标签为“翻译,Dive Into Python”的博文。显示所有博文

2015年4月8日星期三

Dive into Python 的我的翻译------Chapter 15. Refactoring VIII [15.3.Refactoring II]

Example 15.10. Compiling regular expressions

  •        >>> import re
    >>> pattern = '^M?M?M?$'
    >>> re.search(pattern, 'M') ------------------------------------------------1

    >>> compiledPattern = re.compile(pattern)-----------------------------------2
    >>> compiledPattern

    >>> dir(compiledPattern)----------------------------------------------------3
    ['findall', 'match', 'scanner', 'search', 'split', 'sub', 'subn']
    >>> compiledPattern.search('M') --------------------------------------------4

    • 1.
      This is the syntax you've seen before: re.search takes a regular expression as a string (pattern) and a string to match against it ('M'). If the pattern matches, the function returns a match object which can be queried to find out exactly what matched and how
      [pope译]这个语法之前你见过: re.search传入字符串格式(pattern)的正则表达式和要被匹配的字符串('M').如果格式符匹配,这个函数返回一个匹配对象它可以被查找到什么匹配和如何匹配。
      2.This is the new syntax: re.compile takes a regular expression as a string and returns a pattern object. Note there is no string to match here. Compiling a regular expression has nothing to do with matching it against any specific strings (like 'M'); it only involves the regular expression itself.
      [pope译]
      这是一个新的语法:re.compile 输入一个正则表达式最为字符串 并返回一个样式对象{pattern object}.记住这里没有字符串匹配过程.编译{compiling}一个正则表达式而在匹配特殊字符串(像'M')上什么也不做.它仅包含正则表达式本身。
      3.
      The compiled pattern object returned from re.compile has several useful-looking functions, including several (like search and sub) that are available directly in the re module.
      [pope译]
      这个compiledpattern 对象返回来自于re.complie 的几个 看来有用的方法, 比如  在re模块中 几个(像 search 和 sub)直接的有用的方法。
      4.
      Calling the compiled pattern object's search function with the string 'M' accomplishes the same thing as calling re.search with both the regular expression and the string 'M'. Only much, much faster. (In fact, the re.search function simply compiles the regular expression and calls the resulting pattern object's search method for you.)
      [pope译]
      调用这个compiledPattern 对象的search 方法查找字符'M'  达到{accomplishe} 和调用re.search 同样的效果 ,都是正则表达查找'M'.仅仅是更快了。(实际上,这个re.search 方法简单地编译了正则表达式并且 为你调用了匹配样本对象的search方法的结果)
    Whenever you are going to use a regular expression more than once, you should compile it to get a pattern object, then call the methods on the pattern object directly.
    [pope译]
    无论何时你打算使用正则表达式多余一次,你应该编译它获得一个待匹配{pattern}对象,在需要匹配的位置直接调用它。    

2015年3月18日星期三

Dive into Python 的我的翻译------Chapter 15. Refactoring VII [15.3.Refactoring I]

The best thing about comprehensive unit testing is not the feeling you get when all your test cases finally pass, or even the feeling you get when someone else blames you for breaking their code and you can actually prove that you didn't. The best thing about unit testing is that it gives you the freedom to refactor mercilessly.
[pope译]

       完整的单元测试的最大好处,不是当你测试用例全部通过测试的感觉;甚至也不是有人指责{blames}你引起他的代码问题{breaking their code}时 ,你可以证明你没有;单元测试带给你最好的事情是你可以自由的狠狠的{mercilessly}重构你的代码。    

Refactoring is the process of taking working code and making it work better. Usually, "better" means "faster", although it can also mean "using less memory", or "using less disk space", or simply "more elegantly". Whatever it means to you, to your project, in your environment, refactoring is important to the long-term health of any program.
[pope译]

       重构在使用中代码的过程是使其工作得更好,一般来说,"更好"意味着"更快",尽管{although}它可能也意味这着"使用更少的内存",或者“使用更少的磁盘空间”,或者更简单“更加优雅{elegantly}”.无论在你的环境中它对你和你的项目意味着什么,重构对任何程序的长期健康{long-term health}都很重要。

 Here, "better" means "faster". Specifically, the fromRoman function is slower than it needs to be, because of that big nasty regular expression that you use to validate Roman numerals. It's probably not worth trying to do away with the regular expression altogether (it would be difficult, and it might not end up any faster), but you can speed up the function by precompiling the regular expression.
[pope译]
这里,"更好"意味着"更快"。特别是{specifically},这个fromRoman函数比需要的慢,由于这个大而不好的是用来确定{validate}罗马字符的正则表达式.它可能并不值得尝试去除在一起的正则表达(这个可能有点儿难,并且它可能还没更快点儿),但你可以通过预编译{precompiling}这个正则表达式来达到提速这个函数。     

2015年3月17日星期二

Dive into Python 的我的翻译------Chapter 15. Refactoring VI [15.2. Handling changing requirements IV]

Example 15.8. Coding the new requirements

  •        1.toRoman only needs one small change, in the range check. Where you used to check 0 < n < 4000, you now check 0 < n < 5000. And you change the error message that you raise to reflect the new acceptable range (1..4999 instead of 1..3999). You don't need to make any changes to the rest of the function; it handles the new cases already. (It merrily adds 'M' for each thousand that it finds; given 4000, it will spit out 'MMMM'. The only reason it didn't do this before is that you explicitly stopped it with the range check.)
    [pope译]toRoman 仅需要在范围检查中做一个小的改变。在你使用0 2.You don't need to make any changes to fromRoman at all. The only change is to romanNumeralPattern; if you look closely, you'll notice that you added another optional M in the first section of the regular expression. This will allow up to 4 M characters instead of 3, meaning you will allow the Roman numeral equivalents of 4999 instead of 3999. The actual fromRoman function is completely general; it just looks for repeated Roman numeral characters and adds them up, without caring how many times they repeat. The only reason it didn't handle 'MMMM' before is that you explicitly stopped it with the regular expression pattern match
    [pope译]
    你不需要为fromRoman做任何改变。唯一要变的是romanNumeralPattern;如果你仔细看{look closely}你会主要到在正则表达式的第一块{section}加入一个M.这样允许4个M代替3个M,这意味着你将允许罗马字符4999来替代3999.这个实际上{actual}fromRoman函数是完全可以的{completely general};它仅寻找替代的罗马字符并将其拼装起来,不关心{caring}替换了多少次.之前唯一没有打出'MMMM'的原因是你在正则表达执行匹配式停止了它.
    You may be skeptical that these two small changes are all that you need. Hey, don't take my word for it; see for yourself:
    [pope译]
    你可能怀疑{skeptical} 你只要做两个小的改变。嗨,别看这个,注意你自己的
    [popexizhi]这个 don't take your word for it,see for yourself.可以这样翻译吗?
  •  Example 15.9. Output of romantest72.py against roman72.py
    • All the test cases pass. Stop coding.
      Comprehensive unit testing means never having to rely on a programmer who says "Trust me."
      [pope译]
      所有的测试用例通过了,停止编码。
      完整的单元测试意味着从没有依赖{rely on}编程者说"相信{trust}我"    
        

2015年3月10日星期二

Dive into Python 的我的翻译------Chapter 15. Refactoring V [15.2. Handling changing requirements III]

Example 15.7. Output of romantest71.py against roman71.py

  • code
    • fromRoman should only accept uppercase input ... ERROR ----------------1
      toRoman should always return uppercase ... ERROR
      fromRoman should fail with blank string ... ok
      fromRoman should fail with malformed antecedents ... ok
      fromRoman should fail with repeated pairs of numerals ... ok
      fromRoman should fail with too many repeated numerals ... ok
      fromRoman should give known result with known input ... ERROR-----------2
      toRoman should give known result with known input ... ERROR-------------3
      fromRoman(toRoman(n))==n for all n ... ERROR----------------------------4
      toRoman should fail with non?integer input ... ok
      toRoman should fail with negative input ... ok
      toRoman should fail with large input ... ok
      toRoman should fail with 0 input ... ok
    1.Our case checks now fail because they loop from 1 to 4999, but toRoman only accepts numbers from 1 to 3999, so it will fail as soon the test case hits 4000.
    [pope译]
    我们的用例检查失败了因为他们是从1到4999的循环,但是toRoman仅仅支持从1到3999的循环,所以在它遇到4000的测试用例时失败了。
    2.The fromRoman known values test will fail as soon as it hits 'MMMM', because fromRoman still thinks this is an invalid Roman numeral
    [pope译]fromRoman在遇到'MMMM'时测试失败了,因为fromRoman仍然认为这是一个有问题的罗马数字
    3.The toRoman known values test will fail as soon as it hits 4000, because toRoman still thinks this is out of range
    [pope译] toRoman知道它遇到4000的值时测试失败,因为toRoman仍然认为这个超出范围了。
    4.The sanity check will also fail as soon as it hits 4000, because toRoman still thinks this is out of range.
    [pope译]
    这个完整性{sanity}测试在撞到4000时仍然失败,以为toRoman认为这个超出范围
    Now that you have test cases that fail due to the new requirements, you can think about fixing the code to bring it in line with the test cases. (One thing that takes some getting used to when you first start coding unit tests is that the code being tested is never "ahead" of the test cases. While it's behind, you still have some work to do, and as soon as it catches up to the test cases, you stop coding.)

    [pope译]现在测试用例由于新的需求而失败,你可以想想如何修改这些代码向这些测试用例看齐{to bring it in line}(有件事要花些时间适应{one thing that takes some getting used to},当你首次开始单元测试,那些被测代码从未"领先"{ahead}于测试用例。当它们在后面时{behind},你仍有些工作要做,在它们赶上测试用例后,你才可以停止编码)
    [popexizhi]这个就是TDD的要求吧,自己一直在转变自己的coding方式,这个应该多思考和实践,我现在遇到的新问题是,测试代码如何测试?:)我说的至少包括testcase和自动化的测试代码部分两种。    

2015年3月5日星期四

Dive into Python 的我的翻译------Chapter 15. Refactoring IV [15.2. Handling changing requirements II]


Example 15.6. Modifying test cases for new requirements (romantest71.py)

  • + - code
    • import roman71
      import unittest
      class KnownValues(unittest.TestCase):
      knownValues = ( (1, 'I'),
      (2, 'II'),
      (3, 'III'),
      (4, 'IV'),
      (5, 'V'),
      (6, 'VI'),
      (7, 'VII'),
      (8, 'VIII'),
      (9, 'IX'),
      (10, 'X'),
      (50, 'L'),
      (100, 'C'),
      (500, 'D'),
      (1000, 'M'),
      (31, 'XXXI'),
      (148, 'CXLVIII'),
      (294, 'CCXCIV'),
      (312, 'CCCXII'),
      (421, 'CDXXI'),
      (528, 'DXXVIII'),
      (621, 'DCXXI'),
      (782, 'DCCLXXXII'),
      (870, 'DCCCLXX'),
      (941, 'CMXLI'),
      (1043, 'MXLIII'),
      (1110, 'MCX'),
      (1226, 'MCCXXVI'),
      (1301, 'MCCCI'),
      (1485, 'MCDLXXXV'),
      (1509, 'MDIX'),
      (1607, 'MDCVII'),
      (1754, 'MDCCLIV'),
      (1832, 'MDCCCXXXII'),
      (1993, 'MCMXCIII'),
      (2074, 'MMLXXIV'),
      (2152, 'MMCLII'),
      (2212, 'MMCCXII'),
      (2343, 'MMCCCXLIII'),
      (2499, 'MMCDXCIX'),
      (2574, 'MMDLXXIV'),
      (2646, 'MMDCXLVI'),
      (2723, 'MMDCCXXIII'),
      (2892, 'MMDCCCXCII'),
      (2975, 'MMCMLXXV'),
      (3051, 'MMMLI'),
      (3185, 'MMMCLXXXV'),
      (3250, 'MMMCCL'),
      (3313, 'MMMCCCXIII'),
      (3408, 'MMMCDVIII'),
      (3501, 'MMMDI'),
      (3610, 'MMMDCX'),
      (3743, 'MMMDCCXLIII'),
      (3844, 'MMMDCCCXLIV'),
      (3888, 'MMMDCCCLXXXVIII'),
      (3940, 'MMMCMXL'),
      (3999, 'MMMCMXCIX'),
      (4000, 'MMMM'),            ----------------------------------------------1
      (4500, 'MMMMD'),
      (4888, 'MMMMDCCCLXXXVIII'),
      (4999, 'MMMMCMXCIX'))
      def testToRomanKnownValues(self):
      """toRoman should give known result with known input"""
      for integer, numeral in self.knownValues:
      result = roman71.toRoman(integer)
      self.assertEqual(numeral, result)
      def testFromRomanKnownValues(self):
      """fromRoman should give known result with known input"""
      for integer, numeral in self.knownValues:
      result = roman71.fromRoman(numeral)
      self.assertEqual(integer, result)
      class ToRomanBadInput(unittest.TestCase):
      def testTooLarge(self):
      """toRoman should fail with large input"""
      self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, 5000)-----------2
      def testZero(self):
      """toRoman should fail with 0 input"""
      self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, 0)
      def testNegative(self):
      """toRoman should fail with negative input"""
      self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, ?1)
      def testNonInteger(self):
      """toRoman should fail with non?integer input"""
      self.assertRaises(roman71.NotIntegerError, roman71.toRoman, 0.5)
      class FromRomanBadInput(unittest.TestCase):
      def testTooManyRepeatedNumerals(self):
      """fromRoman should fail with too many repeated numerals"""
      for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):  --------------3
      self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s)
      def testRepeatedPairs(self):
      """fromRoman should fail with repeated pairs of numerals"""
      for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
      self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s)
      def testMalformedAntecedent(self):
      """fromRoman should fail with malformed antecedents"""
      for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
      'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
      self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s)
      def testBlank(self):
      """fromRoman should fail with blank string"""
      self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, "")
      class SanityCheck(unittest.TestCase):
      def testSanity(self):
      """fromRoman(toRoman(n))==n for all n"""
      for integer in range(1, 5000):    --------------------------------------------4
      numeral = roman71.toRoman(integer)
      result = roman71.fromRoman(numeral)
      self.assertEqual(integer, result)
      class CaseCheck(unittest.TestCase):
      def testToRomanCase(self):
      """toRoman should always return uppercase"""
      for integer in range(1, 5000):
      numeral = roman71.toRoman(integer)
      self.assertEqual(numeral, numeral.upper())
      def testFromRomanCase(self):
      """fromRoman should only accept uppercase input"""
      for integer in range(1, 5000):
      numeral = roman71.toRoman(integer)
      roman71.fromRoman(numeral.upper())
      self.assertRaises(roman71.InvalidRomanNumeralError,
      roman71.fromRoman, numeral.lower())
      if __name__ == "__main__":
      unittest.main()
    1.The existing known values don't change (they're all still reasonable values to test), but you need to add a few more in the 4000 range. Here I've included 4000 (the shortest), 4500 (the second shortest), 4888 (the longest), and 4999 (the largest).
    [pope译]
    当前知道值并没有改变(它们仍然是合理的测试值),但你需要在4000的行后添加更多的测试数据。这里我加入了4000(最小值),4500(第二小的值),4888(较大值),4999(最大值)
    2.The definition of "large input" has changed. This test used to call toRoman with 4000 and expect an error; now that 4000-4999 are good values, you need to bump this up to 5000
    [pope译]
    定义"最大输入"的改变.这个测试使用的4000调用toRoman并且预期一个错误抛出,现在4000~4999都是正常值,你需要修改为5000
    3.The definition of "too many repeated numerals" has also changed. This test used to call fromRoman with 'MMMM' and expect an error; now that MMMM is considered a valid Roman numeral, you need to bump this up to 'MMMMM'.
    [pope译] "过多重复字符"的定义也需要改变。这个测试使用"MMMM"调用fromRoman 并且 预期一个错误抛出,现在MMMM被认为是一个有效个罗马字符,你需要跟新它为'MMMMM'.
    4.The sanity check and case checks loop through every number in the range, from 1 to 3999. Since the range has now expanded, these for loops need to be updated as well to go up to 4999.
    [pope译]
    完整性测试{santiy check}用例通过检查范围中的1~3999的每个数字。由于这个范围限制扩展了,循环上限要跟新到4999.
    Now your test cases are up to date with the new requirements, but your code is not, so you expect several of the test cases to fail.
    [pope译]
    现在你的测试用例跟新需求的新数据,但你的代码没有更新,所以执行测试测试用例有失败的。    

Dive into Python 的我的翻译------Chapter 15. Refactoring III [15.2. Handling changing requirements]

       15.2. Handling changing requirements
       Despite your best efforts to pin your customers to the ground and extract exact requirements from them on pain of horrible nasty things involving scissors and hot wax, requirements will change.
Most customers don't know what they want until they see it, and even if they do, they aren't that good at articulating what they want precisely enough to be useful. And even if they do, they'll want more in the next release anyway. So be prepared to update your test cases as requirements change.

[pope译] 尽管{despite}你尽力{efforts}站在{pin}客户的角度,提取出{extract}准确的{exact}需求,来自于他们可怕{horribe}污秽{nasty}之物的痛苦{pain} 包括 剪刀{scissors}和很烫的蜡油{hot wax},需求还是会变动。
多数客户并不知道他们到底要什么直到他们看到所要的;并且即使他们知道自己想要什么,他们也不能清晰的{articulating}描述出什么对他们有用;并且即使他们可以清晰描述他们想要的,他们也将在下个版本要求的更多。所以准备{prepared}更新你的测试用例在需求改变时。
[popexizhi]"from them on pain of horrible nasty things involving scissors and hot wax"这个的准确翻译是什么比较好呢?从水深火热中抢救出?! :)好吧反正是琐碎痛苦的事。

  Suppose, for instance, that you wanted to expand the range of the Roman numeral conversion functions. Remember the rule that said that no character could be repeated more than three times? Well, the Romans were willing to make an exception to that rule by having 4 M characters in a row to represent 4000. If you make this change, you'll be able to expand the range of convertible numbers from 1..3999 to 1..4999. But first, you need to make some changes to the test cases.

[pope译]
假设,这个例子中,你想要扩展罗马字符转换函数的行列内容。记得那个规则说的是不能有字符多于三次出现吗?很好,罗马字母将扩展这个规则为可以有4个M来描述4000.如果你实现这个改变,你将扩展这个字符串从1~3999为1~4999.但首先你需要在测试用例中做一些改变。     

2015年1月27日星期二

Dive into Python 的我的翻译------Chapter 15. Refactoring II

Coding this way does not make fixing bugs any easier. Simple bugs (like this one) require simple test cases; complex bugs will require complex test cases.
In a testing−centric environment, it may seem like it takes longer to fix a bug, since you need to articulate in code exactly what the bug is (to write the test case), then fix the bug itself.
Then if the test case doesn't pass right away, you need to figure out whether the fix was wrong, or whether the test case itself has a bug in it.

[pope译]
这种编码方式并不能更简单的修复bug。简单的bug(想这个)需要简单的测试用例;复杂的bug会需要复杂的测试用例。
在测试中,看起来更像用较长时间修复bug,你需要明确{articulate}代码中这个bug的什么(并写到测试用例中),然后修复这个bug。

那么如果测试用例并没有使用正确的方式测试通过,你需要想想{}这个修复是否是错误的,或者这个测试用例本身有bug  

However, in the long run, this back−and−forth between test code and code tested pays for itself, because it makes it more likely that bugs are fixed correctly the first time. Also, since you can easily re−run all the test cases along with your new one, you are much less likely to break old code when fixing new code. Today's unit test is tomorrow's regression test
[pope译]
无论如何,在长时间过去后,重拾之前的测试代码和被测试的代码,这个过程使得它看起来更像是bug们在第一时间被准确的修复了。并且,在你的添加新内容后,你就可以简单的运行全部测试用例了,这样你可以在添加新代码时更少的打乱旧代码了。今天的单元测试就是明天的防止退化的测试{regression test}  

2014年7月8日星期二

Dive into Python 的我的翻译------Chapter 15. Refactoring I

15.1. Handling bugs

  •        Despite your best efforts to write comprehensive unit tests, bugs happen. What do I mean by "bug"? A bug is a test case you haven't written yet.
    [pope 译]
    尽管你做了最完成的单元测试,但bugs还是出现了。那bug又意味着什么呢?一个bug就是一个你还没有写的测试用例
    + - Example 15.1. The bug
    • >>> import roman5
      >>> roman5.fromRoman("") ------------------------------1
      0
      • 1.
        Remember in the previous section when you kept seeing that an empty string would match the regular expression you were using to check for valid Roman numerals? Well, it turns out that this is still true for the final version of the regular expression. And that's a bug; you want an empty string to raise an  InvalidRomanNumeralError exception just like any other sequence of characters that don't represent a valid Roman numeral.
        [pope译]
        可记的前章曾见空串符合罗马数字的检查?是,此版本正则检查出的问题显示为真。是个bug,你本意空串为假 抛出  InvalidRomanNumeralError异常 ,就像其他非罗马数字列表。
      After reproducing the bug, and before fixing it, you should write a test case that fails, thus illustrating the bug
      [pope 译]
      重现此bug后,修复前,你当写此失效的测试用例,来记述{illustrating}此bug
    Example 15.2. Testing for the bug (romantest61.py)
    • class FromRomanBadInput(unittest.TestCase):                                     
          # previous test cases omitted for clarity (they haven't changed)
          def testBlank(self):
              """fromRoman should fail with blank string"""
              self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, "")   --------------------1
      • 1
        Pretty simple stuff here. Call fromRoman with an empty string and make sure it raises an InvalidRomanNumeralError exception. The hard part was finding the bug; now that you know about it, testing for it is the easy part.
        [pope译]
        此处颇{pretty}简单.用空串调fromRoman,且确定此当抛InvalidRomanNumeralError异常。难出是发现此bug;现在君当知testing才是简单的部分而已。
    + - Since your code has a bug, and you now have a test case that tests this bug, the test case will fail
    [pope译]
    因code有bug,且现在有此bug的测试用例,此用例执行失败如下:
    • Example 15.3. Output of romantest61.py against roman61.py
      fromRoman should only accept uppercase input ... ok
      toRoman should always return uppercase ... ok
      fromRoman should fail with blank string ... FAIL
      fromRoman should fail with malformed antecedents ... ok
      fromRoman should fail with repeated pairs of numerals ... ok
      fromRoman should fail with too many repeated numerals ... ok
      fromRoman should give known result with known input ... ok
      toRoman should give known result with known input ... ok
      fromRoman(toRoman(n))==n for all n ... ok
      toRoman should fail with non−integer input ... ok
      toRoman should fail with negative input ... ok
      toRoman should fail with large input ... ok
      toRoman should fail with 0 input ... ok
      ======================================================================
      FAIL: fromRoman should fail with blank string
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage6\romantest61.py", line 137, in testBlank
          self.assertRaises(roman61.InvalidRomanNumeralError, roman61.fromRoman, "")
        File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
          raise self.failureException, excName
      AssertionError: InvalidRomanNumeralError
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Ran 13 tests in 2.864s
      FAILED (failures=1)
    Now you can fix the bug.
    [pope 译]
    现在来修复此bug
    + - Example 15.4. Fixing the bug (roman62.py)
    • This file is available in py/roman/stage6/ in the examples directory
      [pope 译]
      此文py/roman/stage6/ 实例文件中
      def fromRoman(s):
          """convert Roman numeral to integer"""
          if not s:  ------------------------------------------------------------------------------1
              raise InvalidRomanNumeralError, 'Input can not be blank'
          if not re.search(romanNumeralPattern, s):
              raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s
          result = 0
          index = 0
          for numeral, integer in romanNumeralMap:
              while s[index:index+len(numeral)] == numeral:
                  result += integer
                  index += len(numeral)
          return result
      • 1
        Only two lines of code are required: an explicit check for an empty string, and a raise statement.
        [pope译]
        只需两行代码:明确查空串,抛异常声明
    + - Example 15.5. Output of romantest62.py against roman62.py
    • fromRoman should only accept uppercase input ... ok
      toRoman should always return uppercase ... ok
      fromRoman should fail with blank string ... ok  --------------------------------------------------------1
      fromRoman should fail with malformed antecedents ... ok
      fromRoman should fail with repeated pairs of numerals ... ok
      fromRoman should fail with too many repeated numerals ... ok
      fromRoman should give known result with known input ... ok
      toRoman should give known result with known input ... ok
      fromRoman(toRoman(n))==n for all n ... ok
      toRoman should fail with non−integer input ... ok
      toRoman should fail with negative input ... ok
      toRoman should fail with large input ... ok
      toRoman should fail with 0 input ... ok
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Ran 13 tests in 2.834s
      OK  --------------------------------------------------------2
      • 1
        The blank string test case now passes, so the bug is fixed
        [pope译]
        空串测试用例通过,此bug修复
        2.
        All the other test cases still pass, which means that this bug fix didn't break anything else. Stop coding
        [pope译]
        全部测试用例通过,这意味修复bug未引入其他。停止编程了
       

2013年7月24日星期三

Dive into Python 的我的翻译 XLII------14.1 II

Example 14.1. roman1.py

  •  This file is available in py/roman/stage1/ in the examples directory.
    If you have not already done so, you can download this and other examples (http://diveintopython.org/download/diveintopython−examples−5.4.zip) used in this book.
    [pope译]
    这个可用的文件在py/roman/stage1/ 例子的文件夹中。
    如果你还没有,可以在http://diveintopython.org/download/diveintopython−examples−5.4.zip 中下载使用本书的其他例子
    [net 译 来源:http://woodpecker.org.cn/diveintopython/unit_testing/stage_1.html ]
    这个程序可以在例子目录下的 py/roman/stage1/ 目录中找到。
    如果您还没有下载本书附带的样例程序, 可以 下载本程序和其他样例程序


    """Convert to and from Roman numerals"""
    #Define exceptions
    class RomanError(Exception): pass--------------------------------------------------------------1               
    class OutOfRangeError(RomanError): pass--------------------------------------------------------------2         
    class NotIntegerError(RomanError): pass
    class InvalidRomanNumeralError(RomanError): pass -------------------------------------------------3
    def toRoman(n):
        """convert integer to Roman numeral"""--------------------------------------------------------------4
        pass                                        
    def fromRoman(s):
        """convert Roman numeral to integer"""
        pass
    • 1[原文]P198
      This is how you define your own custom exceptions in Python. Exceptions are classes, and you create your own by subclassing existing exceptions. It is strongly recommended (but not required) that you subclass Exception, which is the base class that all built−in exceptions inherit from. Here I am defining RomanError (inherited from Exception) to act as the base class for all my other custom exceptions to follow. This is a matter of style; I could just as easily have inherited each individual exception from the Exception class directly
      [pope译]
      这是你在python中如何定义自己的异常。异常是类,你通过继承存在的异常类创建你自己的异常类。创建Exception 的子集被强烈推荐,但不强制,这个是全部嵌入的异常通过继承得到的。这里我定义的RomanError(继承Exception)作为我当前异常的基类使用。这是个风格问题,我也可以每个异常类只直接简单的继承Exception。
      [popexizhi:这个继承的风格,自己第一次看时还真没有好好注意:)]
      [net 译]
      这就是如何定义你自己的 Python 异常。异常 (Exception) 也是类,通过继承已有的异常,你可以创建自定义的异常。强烈建议 (但不是必须) 你继承 Exception 来定义自己的异常,因为它是所有内建异常的基类。这里我定义了 RomanError (从 Exception 继承而来) 作为我所有自定义异常的基类。这是一个风格问题,我也可以直接从 Exception继承建立每一个自定义异常。
      [popexizhi]
      which is the base class that all built−in exceptions inherit from
      [pope译]这个是全部嵌入的异常通过继承得到的
      [net 译]因为它是所有内建异常的基类
      [popexizhi] 内建异常的基类


      2[原文]P198
      The OutOfRangeError and NotIntegerError exceptions will eventually be used by toRoman to flag various forms of invalid input, as specified in ToRomanBadInput.
      [pope译]
      OutOfRangeError 和 NotIntegerError 异常是toRoman用来标志不同形式的错误输入使用的,在ToRomanBadInput中特别指出的
      [net 译]
      OutOfRangeError  NotIntegerError 异常将会最终被用于 toRoman 以标示不同类型的无效输入,更具体而言就是 ToRomanBadInput 测试的那些。

      3[原文]P198
      The InvalidRomanNumeralError exception will eventually be used by fromRoman to flag invalid input, as specified in FromRomanBadInput.
      [pope译]
      InvalidRomanNumeralError异常是fromRoman用来标记错误输入使用的,在FromRomanBadInput中特别测试对应内容
      [net 译]
      InvalidRomanNumeralError 将被最终用于 fromRoman 以标示无效输入,具体而言就是 FromRomanBadInput测试的那些。
      4[原文]P198
      At this stage, you want to define the API of each of your functions, but you don't want to code them yet, so you stub them out using the Python reserved word pass.
      [pope译]
      在这个过程中,你想要定义实现功能的API,但你现在不打算使用代码实现,所以你使用python保留的关键字pass 充填这个过程。
      [net 译]
      在这一步中你只是想定义每个函数的 API ,而不想具体实现它们,因此你以 Python 关键字 pass 姑且带过。
    [原文]P198
    Now for the big moment (drum roll please): you're finally going to run the unit test against this stubby little module. At this point, every test case should fail. In fact, if any test case passes in stage 1, you should go back to romantest.py and re−evaluate why you coded a test so useless that it passes with do−nothing functions.
    [pope译]
    现在有一个重要信息(打起精神来注意了):你之后要针对这个简短的模块运行单元测试。在当前点,每个单元测试都应该失败。如果有什么单元测试在stage1中成功,你到应该返回到romantest.py 中重新评估一下{re-evaluate}为什么你的单元测试代码这么没有,竟然让什么都没做的功能通过测试了。
    [net 译]
    重要的时刻到了 (请打起鼓来):你终于要对这个简陋的小模块开始运行单元测试了。目前而言,每一个测试用例都应该失败。事实上,任何测试用例在此时通过,你都应该回头看看 romantest.py ,仔细想想为什么你写的测试代码如此没用,以至于连什么都不作的函数都能通过测试。
    [popexizhi]
    at this point
    [pope译]在当前点
    [net 译]目前而言
    [popexizhi] at this point 目前而言,学习了
    [原文]P198
    Run romantest1.py with the −v command−line option, which will give more verbose output so you can see exactly what's going on as each test case runs. With any luck, your output should look like this:

    [pope译]
    使用-v命令行参数运行romantest1.py,它将给出更多的详细{verbose}输出这样你就可以看到每个测试用例运行的精确的过程。如果一切幸运的话{with any luck},你看到的输出类似如下:
    [net 译]
    用命令行选项 -v 运行 romantest1.py 可以得到更详细的输出信息,这样你就可以看到每一个测试用例的具体运行情况。如果幸运,你的结果应该是这样的
    + - Example 14.2. Output of romantest1.py against roman1.py
    • fromRoman should only accept uppercase input ... ERROR
      toRoman should always return uppercase ... ERROR
      fromRoman should fail with malformed antecedents ... FAIL
      fromRoman should fail with repeated pairs of numerals ... FAIL
      fromRoman should fail with too many repeated numerals ... FAIL
      fromRoman should give known result with known input ... FAIL
      toRoman should give known result with known input ... FAIL
      fromRoman(toRoman(n))==n for all n ... FAIL
      toRoman should fail with non−integer input ... FAIL
      toRoman should fail with negative input ... FAIL
      toRoman should fail with large input ... FAIL
      toRoman should fail with 0 input ... FAIL
      ======================================================================
      ERROR: fromRoman should only accept uppercase input
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 154, in testFromRomanCase
          roman1.fromRoman(numeral.upper())
      AttributeError: 'None' object has no attribute 'upper'
      ======================================================================
      ERROR: toRoman should always return uppercase
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 148, in testToRomanCase
          self.assertEqual(numeral, numeral.upper())
      AttributeError: 'None' object has no attribute 'upper'
      ======================================================================
      FAIL: fromRoman should fail with malformed antecedents
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 133, in testMalformedAntecedent
          self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s)
        File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
          raise self.failureException, excName
      AssertionError: InvalidRomanNumeralError
      ======================================================================
      FAIL: fromRoman should fail with repeated pairs of numerals
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 127, in testRepeatedPairs
          self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s)
        File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
          raise self.failureException, excName
      AssertionError: InvalidRomanNumeralError
      ======================================================================
      FAIL: fromRoman should fail with too many repeated numerals
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 122, in testTooManyRepeatedNumerals
          self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s)
        File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
          raise self.failureException, excName
      AssertionError: InvalidRomanNumeralError
      ======================================================================
      FAIL: fromRoman should give known result with known input
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 99, in testFromRomanKnownValues
          self.assertEqual(integer, result)
        File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
          raise self.failureException, (msg or '%s != %s' % (first, second))
      AssertionError: 1 != None
      ======================================================================
      FAIL: toRoman should give known result with known input
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 93, in testToRomanKnownValues
          self.assertEqual(numeral, result)
        File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
          raise self.failureException, (msg or '%s != %s' % (first, second))
      AssertionError: I != None
      ======================================================================
      FAIL: fromRoman(toRoman(n))==n for all n
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 141, in testSanity
          self.assertEqual(integer, result)
        File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
          raise self.failureException, (msg or '%s != %s' % (first, second))
      AssertionError: 1 != None
      ======================================================================
      FAIL: toRoman should fail with non−integer input
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 116, in testNonInteger
          self.assertRaises(roman1.NotIntegerError, roman1.toRoman, 0.5)
        File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
          raise self.failureException, excName
      AssertionError: NotIntegerError
      ======================================================================
      FAIL: toRoman should fail with negative input
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 112, in testNegative
          self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, −1)
        File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
          raise self.failureException, excName
      AssertionError: OutOfRangeError
      ======================================================================
      FAIL: toRoman should fail with large input
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 104, in testTooLarge
          self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, 4000)
        File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
          raise self.failureException, excName
      AssertionError: OutOfRangeError
      ======================================================================
      FAIL: toRoman should fail with 0 input                           ----------------------------------------------------------------------------------------------------------------------------1     
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Traceback (most recent call last):
        File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 108, in testZero
          self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, 0)
        File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
          raise self.failureException, excName
      AssertionError: OutOfRangeError                                       ----------------------------------------------------------------------------------------------------------------------------2
      −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
      Ran 12 tests in 0.040s                                                      ----------------------------------------------------------------------------------------------------------------------------3
      FAILED (failures=10, errors=2)                                         ----------------------------------------------------------------------------------------------------------------------------4
      • 1[原文]P200
        Running the script runs unittest.main(), which runs each test case, which is to say each method defined in each class within romantest.py. For each test case, it prints out the doc string of the method and whether that test passed or failed. As expected, none of the test cases passed.
        [pope ]
        运行脚本时运行unittest.main()将运行每一个测试用例,也就是说romantest.py中的每个类的定义的每个方法。每个测试用例都将打印出此方法的doc string,与是否测试通过无关。就像预期一样,没有通过测试的测试用例。

        [pope译]
        运行脚本时unittest.main(),运行每一个测试用例,也就是说在romantest.py中的每个类中定义的每个方法都被运行。每个测试用例打印出来方法的文档字符串和是否测试通过。和预期的一样{as expected},没有测试用例通过测试。
        [net 译 来源:http://woodpecker.org.cn/diveintopython/unit_testing/stage_1.html]
        运行脚本将会执行 unittest.main(),由它来执行每个测试用例,也就是每个在 romantest.py 中定义的方法。对于每个测试用例,无论测试通过与否,都会输出这个方法的 doc string。意料之中,没有通过一个测试用例。
        [popexizhi:]
        each method defined in each class within romantest.py
        [pope译]在romantest.py中的每个类中定义的每个方法
        [net 译]每个在 romantest.py 中定义的方法
        [popexizhi]net翻译中的each class 被net省略了,也对吧,反正都在.py中吧
        it prints out the doc string of the method and whether that test passed or failed.
        [pope译]每个测试用例打印出来方法的文档字符串和是否测试通过。
        [net 译]对于每个测试用例,无论测试通过与否,都会输出这个方法的 doc string
        [popexizhi] 这里的and是表示条件的,这里pope翻译中没有理解打印出的doc string 是方法默认的文字说明。


        2[原文]P201
        For each failed test case, unittest displays the trace information showing exactly what happened. In this case, the call to assertRaises (also called failUnlessRaises) raised an AssertionError because it was expecting toRoman to raise an OutOfRangeError and it didn't

        [pope译]
        对每个测试失败的用例,单元测试展示跟踪{trace}信息精确的{exactly}显示发生了什么.在这个例子中,调用assertRaises(也叫做failUniessRaises)抛出{raised}AssertionError 因为它预期 toRoman 应该抛出OutOfRangeError 异常但它没有抛出。
        [net 译]
        对于每个失败的测试用例,unittest 显示的跟踪信息告诉我们都发生了什么。就此处而言,调用 assertRaises (也称作 failUnlessRaises) 引发了一个 AssertionError 异常,因为期待 toRoman 所引发的 OutOfRangeError 异常没有出现
        3[原文]P201
        After the detail, unittest displays a summary of how many tests were performed and how long it took.
        [pope译]
        在这些细节之后,单元测试展示有多少测试执行{performed}和它运行多久的总结。
        [net译]
        在这些细节后面,unittest 给出了一个关于被执行测试的个数和花费时间的总结。
        4[原文]P201
        Overall, the unit test failed because at least one test case did not pass. When a test case doesn't pass, unittest distinguishes between failures and errors. A failure is a call to an assertXYZ method, like assertEqual or assertRaises, that fails because the asserted condition is not true or the expected exception was not raised. An error is any other sort of exception raised in the code you're testing or the unit test case itself. For instance, the testFromRomanCase method ("fromRoman should only accept uppercase input") was an error, because the call to numeral.upper() raised an AttributeError exception, because toRoman was supposed to return a string but didn't. But testZero ("toRoman should fail with 0 input") was a failure, because the call to fromRoman did not raise the InvalidRomanNumeral exception that assertRaises was looking for.
        [pope译]
        总计一下,单元测试失败是因为至少有一个测试用例没有通过测试。当测试用例不能通过时,单元测试区分了{distinguishes} 失败和错误。失败是调用assertXYZ 方法,像assertEqual或者assertRaises,失败是因为声明的条件{asserted condition}不为真或者预期的异常{the expected exception }没有抛出。错误是在你的测试代码或者单元测试用例自身中各种种类的异常抛出。例如:testFromRomanCase 方法的("fromRoman should only accept uppercase input") 就是一个错误,因为调用 numeral.upper() 抛出一个 AttributeError 异常,因为 toRoman 应该(was supposed to)返回字符串却没有. 但testZero ("toRoman should fail with 0 input")是一个失败,因为调用fromRoman 没有抛出assertRaises查找的 InvalidRomanNumeral 异常。
        [net译 来源:http://woodpecker.org.cn/diveintopython/unit_testing/stage_1.html ]
        总而言之,由于至少一个测试用例没有通过,单元测试失败了。当某个测试用例没能通过时,unittest 会区分是失败 (failures) 还是错误 (errors)。失败是指调用 assertXYZ方法,比如 assertEqual 或者 assertRaises 时,断言的情况没有发生或预期的异常没有被引发。而错误是指你测试的代码或单元测试本身发生了某种异常。例如:testFromRomanCase 方法 (“fromRoman 只接受大写输入”) 就是一个错误,因为调用 numeral.upper() 引发了一个 AttributeError 异常,因为 toRoman 的返回值不是期望的字符串类型。但是,testZero (“toRoman 应该在输入 0 时失败”) 是一个失败,因为调用 fromRoman 没有引发一个 assertRaises 期待的异常:InvalidRomanNumeral
        [popexizhi]
        because the call to numeral.upper() raised an AttributeError exception,because toRoman was supposed to return a string but didn't.
        [pope译]因为 toRoman 应该(was supposed to)返回字符串却没有.
        [net 译]因为 toRoman 的返回值不是期望的字符串类型
        [popexizhi]这个位置翻译的没有太多问题,查了一下源码,是因为这里的unittest原文如下:

        def testFromRomanCase(self):
                """fromRoman should only accept uppercase input"""
                for integer in range(1, 4000):
                    numeral = roman1.toRoman(integer)
                    roman1.fromRoman(numeral.upper())
                    self.assertRaises(roman1.InvalidRomanNumeralError,
                                      roman1.fromRoman, numeral.lower())

        这里的错误是numeral.upper() 但原因是numeral = roman1.toRoman(integer)返回pass引起的,这样就很明白了,看了翻译时,还是上下文很重要啊:)


        [popexizhi]失败是断言期望的失败,而错误是代码本身的错误(但有可能是被测试代码引起的啊:)),所以例子中才会提到testZero没有得到预期的异常    

2013年5月12日星期日

Dive into Python 的我的翻译 XXXX------8.5 XI


       Example 8.12. locals is read−only, globals is not
  • def foo(arg):
        x = 1
        print locals()   -------------------------------------------------------------------1
        locals()["x"] = 2-------------------------------------------------------------------2
        print "x=",x     -------------------------------------------------------------------3
    z = 7
    print "z=",z
    foo(3)
    globals()["z"] = 8    -------------------------------------------------------------------4
    print "z=",z             -------------------------------------------------------------------5

    打印结果:
    >>> ================================ RESTART ================================
    >>>
    z= 7
    {'x': 1, 'arg': 3}
    x= 1
    z =  8
    • 1
      [原文]P111
      Since foo is called with 3, this will print {'arg': 3, 'x': 1}. This should not be a surprise
      [pope译]
      由于foo调用时使用3,所以这里打印 {'arg': 3, 'x': 1}。这个没什么要吃惊的

      [net 译 来源:http://woodpecker.org.cn/diveintopython/html_processing/locals_and_globals.html]

      因为使用 3 来调用 foo,会打印出 {'arg': 3, 'x': 1}。这个应该没什么奇怪的。
      2.[原文]P111
      locals()["x"] = 2
      locals is a function that returns a dictionary, and here you are setting a value in that dictionary. You might think that this would change the value of the local variable x to 2, but it doesn't. locals does not actually return the local namespace, it returns a copy. So changing it does nothing to the value of the variables in the local namespace.

      [popexizhi] 这种使用locals()使用的是一个copy ,只可以read-only
      [pope译]
      locals 是一个返回字典的函数,这里你给字典中设置了一个值。你可能认为这样可以改变local的参数x为2,但是不是这样的。locals并不是真的返回local命名空间,它返回一个拷贝。所以改变它,对local 命名空间没什么变量值的改变。
      [net 译 来源:http://woodpecker.org.cn/diveintopython/html_processing/locals_and_globals.html]
      locals 是一个返回 dictionary 的函数,这里您在 dictionary 中设置了一个值。您可能认为这样会改变局部变量 x 的值为 2,但并不会。locals 实际上没有返回局部名字空间,它返回的是一个拷贝。所以对它进行改变对局部名字空间中的变量值并无影响。
      [popexizhi]
      nothing to the value of the variables in the local namespace
      [pope译]对local 命名空间没什么变量值的改变
      [net 译] 对局部名字空间中的变量值并无影响
      [popexizhi] nothing 在这里还是翻译为无影响比较顺畅一点儿:)
      3[原文]P112
      This prints x= 1, not x= 2
      [pope译]
      这里打印 x=1,而不是x=2
      [net 译]
      这样会打印出 x= 1,而不是 x= 2
      4[原文] P112
      globals()["z"] = 8
      After being burned by locals, you might think that this wouldn't change the value of z, but it does. Due to internal differences in how Python is implemented (which I'd rather not go into, since I don't fully understand them myself), globals returns the actual global namespace, not a copy: the exact opposite behavior of locals. So any changes to the dictionary returned by globals directly affect your global variables.

      [?] globals()倒是可以修改,问题是why?看来作者也不是很明白(作者是谁啊?搜了一下也没发现,推荐去豆瓣看看)。why?如此设计,有什么用意呢?
      [pope译]
      在处理了locals后,你可能认为z也不会有什么变化,但它改变了。由于Python应用本身的不同(我最好还是不要深入谈这个问题,因为我自己也不是很了解其中的原因),globals 返回global 真实的命名空间,而不是一个拷贝,这个与locals的行为完成相反。所以对你的globals 返回字典的修改回直接影响你的全局变量的值
      [net 译 来源:http://woodpecker.org.cn/diveintopython/html_processing/locals_and_globals.html ]
      在有了对 locals 的经验之后,您可能认为这样不会 改变 z 的值,但是可以。由于 Python 在实现过程中内部有所区别 (关于这些区别我宁可不去研究,因为我自已还没有完全理解) ,globals 返回实际的全局名字空间,而不是一个拷贝:与 locals 的行为完全相反。所以对 globals 所返回的 dictionary 的任何的改动都会直接影响到全局变量。


      5[原文]P112
      This prints z= 8, not z= 7.
      [pope译]
      打印为z=8,而不是 z=7
      [net 译]
      这样会打印出 z= 8,而不是 z= 7

2013年5月5日星期日

Dive into Python 的我的翻译 IXXXX------8.5 X


[原文]P111
Using the locals and globals functions, you can get the value of arbitrary variables dynamically, providing the variable name as a string. This mirrors the functionality of the getattr function, which allows you to access arbitrary functions dynamically by providing the function name as a string.
[?] 使用 locals 和 globals 函数你可以增加任何变量为动态加载变量。这个getattr 函数如何使用才能加载呢?有例子吗?这句话是这个意思吗?晕

[pope译]
使用这个 locals 和globals函数,你可以获得任何{arbitrary}变量的动态值,其提供{providing}的变量名称为字符串格式.使用getattr函数映射{mirrors}到对应的功能函数,它允许你对任何{arbitrary}函数,通过使用函数名称的字符串来完成动态访问。
[net 译 来源:http://woodpecker.org.cn/diveintopython/html_processing/locals_and_globals.html]
使用 locals  globals 函数,通过提供变量的字符串名字您可以动态地得到任何变量的值。这种方法提供了这样的功能:getattr 函数允许您通过提供函数的字符串名来动态地访问任意的函数。


[原文]P111
There is one other important difference between the locals and globals functions, which you should learn now before it bites you. It will bite you anyway, but at least then you'll remember learning it.
[popexizhi] bite you嘻嘻这个说法好形象啊:)
[pope译]
在这个locals和globals函数之间有一个重要的区别,你最好在它开始咬你{bites you :)}之前就搞懂它。它可能在任何地方咬你,直到你最后记着这个区别。
[net 译 来源:http://woodpecker.org.cn/diveintopython/html_processing/locals_and_globals.html]
在 locals 与 globals 之间有另外一个重要的区别,您应该在它困扰您之前就了解它。它无论如何都会困扰您的,但至少您还会记得曾经学习过它。
[popexizhi]
bites you
[pope译]咬你
[net 译]困扰您
[popexizhi]go了一下韦氏字典(http://www.merriam-webster.com/dictionary/bite)应该主要就是尖锐物体引起不适应的引起的。net翻译的不错,困扰,嘻嘻:),pope还是直译为咬吧!很形象:)

2013年3月26日星期二

Dive into Python 的我的翻译 XXXVIII------8.5 IX


[原文]P110
Remember the difference between from module import and import module?
With import module, the module itself is imported, but it retains its own namespace, which is why you need to use the module name to access any of its functions or attributes: module.function.

[popexizhi] import module ,导入模块全部的命名空间使用 module.function方式访问


But with from module import, you're actually importing specific functions and attributes from another module into your own namespace, which is why you access them directly without referencing the original module they came from. With the globals function, you can actually see this happen.
[popexizhi] from module import 导入的functions 和attributes访问时就不需要使用the original module they came from了。


[pope译]还记得 from module import 和 import module 有什么区别吗?
使用import module,模块自身被导入,但它保留了自己的命名空间,这就是你为什么要使用模块名称 来访问它的函数和属性:module.function.
但使用from module import,你实际上只导入了指定的函数和属性到你自己的命名空间中,这也是你为什么可以直接访问而不用指定它们的来源模块。使用globals函数,你就会看到这个了。
[?]想起一个问题,如果from module Import 导入的内容中与当前命名空间有重名的定义内容,会发生什么呢?报错?提示修改?直接导入,引用时提示选择引用哪个?experment 一下,我使用文件自身的复制版导入文件自身。没看到报错,正常运行,why?

[net 译 来源:http://woodpecker.org.cn/diveintopython/html_processing/locals_and_globals.html]
回想一下 from module import  import module 之间的不同。使用 import module,模块自身被导入,但是它保持着自已的名字空间,这就是为什么您需要使用模块名来访问它的函数或属性:module.function 的原因。但是使用 from module import,实际上是从另一个模块中将指定的函数和属性导入到您自己的名字空间,这就是为什么您可以直接访问它们却不需要引用它们所来源的模块。使用 globals 函数,您会真切地看到这一切的发生。