mirror of
https://github.com/kennethreitz/dive-into-python3.git
synced 2026-06-05 23:10:17 +00:00
'the answer' is not the answer
This commit is contained in:
+14
-1
@@ -33,8 +33,21 @@ open(..., 'r', encoding='...')
|
||||
|
||||
<h3 id=encoding>Character Encoding Rears Its Ugly Head</h3>
|
||||
|
||||
<p>Bytes are bytes; <a href=strings.html#byte-arrays>characters are an abstraction</a>. A string is a sequence of Unicode characters. But a file on disk is not a sequence of Unicode characters; a file on disk is a sequence of bytes. So if you read a “text file” from disk, how does Python convert that sequence of bytes into a sequence of characters? It decodes the bytes according to a specific character encoding algorithm, and returns a sequence of Unicode characters, otherwise known as a string.
|
||||
|
||||
<pre>
|
||||
# on Windows...
|
||||
>>> file = open('examples/chinese.txt')
|
||||
>>> a_string = file.read()
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
File "C:\Python31\lib\encodings\cp1252.py", line 23, in decode
|
||||
return codecs.charmap_decode(input,self.errors,decoding_table)[0]
|
||||
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f in position 28: character maps to <undefined>
|
||||
>>>
|
||||
</pre>
|
||||
|
||||
<!--
|
||||
OK, so a string is a sequence of Unicode characters. But a file on disk is not a sequence of Unicode characters; a file on disk is a sequence of bytes. So if you read a “text file” from disk, how does Python convert that sequence of bytes into a sequence of characters? The answer is that it decodes the bytes according to a specific character encoding algorithm, and returns a sequence of Unicode characters, otherwise known as a string.
|
||||
|
||||
"The default encoding is platform dependent (whatever locale.getpreferredencoding() returns)." -- http://docs.python.org/3.1/library/io.html
|
||||
-->
|
||||
|
||||
@@ -51,7 +51,7 @@ Type "help", "copyright", "credits" or "license" for more information.
|
||||
<samp class=p>mark@manganese:~$ </samp><kbd>python3</kbd>
|
||||
<samp>bash: python3: command not found</samp></pre>
|
||||
|
||||
<p>So back to the question that started this section, “Which Python is right for you?” The answer is whichever one runs on the computer you already have.
|
||||
<p>So back to the question that started this section, “Which Python is right for you?” Whichever one runs on the computer you already have.
|
||||
|
||||
<p>[Read on for Windows instructions, or skip to <a href=#macosx>Installing on Mac OS X</a>, <a href=#ubuntu>Installing on Ubuntu Linux</a>, or <a href=#other>Installing on Other Platforms</a>.]
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@ class FieldStorage:
|
||||
|
||||
<p>This is <em>not</em> a case of taking a <code>Fraction</code> and dividing it by an integer (as in the previous example). That case was straightforward: <code>x / 3</code> calls <code>x.__truediv__(3)</code>, and the <code>__truediv__()</code> method of the <code>Fraction</code> class handles all the math. But integers don’t “know” how to do arithmetic operations with fractions. So why does this example work?
|
||||
|
||||
<p>The answer lies in a second set of arithmetic special methods with <i>reflected operands</i>. Given an arithmetic operation that takes two operands (<i>e.g.</i> <code>x / y</code>), there are two ways to go about it:
|
||||
<p>There is a second set of arithmetic special methods with <i>reflected operands</i>. Given an arithmetic operation that takes two operands (<i>e.g.</i> <code>x / y</code>), there are two ways to go about it:
|
||||
|
||||
<ol>
|
||||
<li>Tell <var>x</var> to divide itself by <var>y</var>, or
|
||||
|
||||
+1
-1
@@ -276,7 +276,7 @@ Ran 2 tests in 0.000s
|
||||
FAILED (errors=1)</samp></pre>
|
||||
<ol>
|
||||
<li>You should have expected this to fail (since you haven’t written any code to pass it yet), but... it didn’t actually “fail,” it had an “error” instead. This is a subtle but important distinction. A unit test actually has <em>three</em> return values: pass, fail, and error. Pass, of course, means that the test passed — the code did what you expected. “Fail” is what the previous test case did (until you wrote code to make it pass) — it executed the code but the result was not what you expected. “Error” means that the code didn’t even execute properly.
|
||||
<li>Why didn’t the code execute properly? The traceback gives the answer: the module you’re testing doesn’t have an exception called <code>OutOfRangeError</code>. Remember, you passed this exception to the <code>assertRaises()</code> method, because it’s the exception you want the function to raise given an out-of-range input. But the exception doesn’t exist, so the call to the <code>assertRaises()</code> method failed. It never got a chance to test the <code>to_roman()</code> function; it didn’t get that far.
|
||||
<li>Why didn’t the code execute properly? The traceback tells all. The module you’re testing doesn’t have an exception called <code>OutOfRangeError</code>. Remember, you passed this exception to the <code>assertRaises()</code> method, because it’s the exception you want the function to raise given an out-of-range input. But the exception doesn’t exist, so the call to the <code>assertRaises()</code> method failed. It never got a chance to test the <code>to_roman()</code> function; it didn’t get that far.
|
||||
</ol>
|
||||
<p>To solve this problem, you need to define the <code>OutOfRangeError</code> exception in <code>roman2.py</code>.
|
||||
<pre><code class=pp><a>class OutOfRangeError(ValueError): <span class=u>①</span></a>
|
||||
|
||||
Reference in New Issue
Block a user