Changeset 391 for python/trunk/Doc/howto/doanddont.rst
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Doc/howto/doanddont.rst
r2 r391 33 33 valid, no more than having a smart lawyer makes a man innocent. Do not use it 34 34 like that ever. Even in versions where it was accepted, it made the function 35 execution slower, because the compiler could not be certain which names are36 local and which are global. In Python 2.1 this construct causes warnings, and35 execution slower, because the compiler could not be certain which names were 36 local and which were global. In Python 2.1 this construct causes warnings, and 37 37 sometimes even errors. 38 38 … … 47 47 some module grows additional functions or classes. 48 48 49 One of the most awful question asked on the newsgroup is why this code::49 One of the most awful questions asked on the newsgroup is why this code:: 50 50 51 51 f = open("www") … … 114 114 This is a "don't" which is much weaker than the previous "don't"s but is still 115 115 something you should not do if you don't have good reasons to do that. The 116 reason it is usually bad idea is because you suddenly have an object which lives116 reason it is usually a bad idea is because you suddenly have an object which lives 117 117 in two separate namespaces. When the binding in one namespace changes, the 118 118 binding in the other will not, so there will be a discrepancy between them. This … … 145 145 146 146 Python has the ``except:`` clause, which catches all exceptions. Since *every* 147 error in Python raises an exception, this makes many programming errors look 148 like runtime problems, and hinders the debugging process. 149 150 The following code shows a great example:: 147 error in Python raises an exception, using ``except:`` can make many 148 programming errors look like runtime problems, which hinders the debugging 149 process. 150 151 The following code shows a great example of why this is bad:: 151 152 152 153 try: … … 155 156 sys.exit("could not open file!") 156 157 157 The second line triggers a :exc:`NameError` which is caught by the except 158 clause. The program will exit, and you will have no idea that this has nothing 159 to do with the readability of ``"file"``. 160 161 The example above is better written :: 158 The second line triggers a :exc:`NameError`, which is caught by the except 159 clause. The program will exit, and the error message the program prints will 160 make you think the problem is the readability of ``"file"`` when in fact 161 the real error has nothing to do with ``"file"``. 162 163 A better way to write the above is :: 162 164 163 165 try: 164 foo = opne("file") # will be changed to "open" as soon as we run it166 foo = opne("file") 165 167 except IOError: 166 168 sys.exit("could not open file") 167 169 168 There are some situations in which the ``except:`` clause is useful: for 169 example, in a framework when running callbacks, it is good not to let any 170 callback disturb the framework. 170 When this is run, Python will produce a traceback showing the :exc:`NameError`, 171 and it will be immediately apparent what needs to be fixed. 172 173 .. index:: bare except, except; bare 174 175 Because ``except:`` catches *all* exceptions, including :exc:`SystemExit`, 176 :exc:`KeyboardInterrupt`, and :exc:`GeneratorExit` (which is not an error and 177 should not normally be caught by user code), using a bare ``except:`` is almost 178 never a good idea. In situations where you need to catch all "normal" errors, 179 such as in a framework that runs callbacks, you can catch the base class for 180 all normal exceptions, :exc:`Exception`. Unfortunately in Python 2.x it is 181 possible for third-party code to raise exceptions that do not inherit from 182 :exc:`Exception`, so in Python 2.x there are some cases where you may have to 183 use a bare ``except:`` and manually re-raise the exceptions you don't want 184 to catch. 171 185 172 186 … … 186 200 return open(file).readline() 187 201 188 Consider the case the file gets deleted between the time the call to 189 :func:`os.path.exists` is made and the time :func:`open` is called. That means 190 the last line will throw an :exc:`IOError`. The same would happen if *file* 191 exists but has no read permission. Since testing this on a normal machine on 192 existing and non-existing files make it seem bugless, that means in testing the 193 results will seem fine, and the code will get shipped. Then an unhandled 194 :exc:`IOError` escapes to the user, who has to watch the ugly traceback. 195 196 Here is a better way to do it. :: 202 Consider the case where the file gets deleted between the time the call to 203 :func:`os.path.exists` is made and the time :func:`open` is called. In that 204 case the last line will raise an :exc:`IOError`. The same thing would happen 205 if *file* exists but has no read permission. Since testing this on a normal 206 machine on existent and non-existent files makes it seem bugless, the test 207 results will seem fine, and the code will get shipped. Later an unhandled 208 :exc:`IOError` (or perhaps some other :exc:`EnvironmentError`) escapes to the 209 user, who gets to watch the ugly traceback. 210 211 Here is a somewhat better way to do it. :: 197 212 198 213 def get_status(file): 199 214 try: 200 215 return open(file).readline() 201 except (IOError, OSError):202 print " file not found"216 except EnvironmentError as err: 217 print "Unable to open file: {}".format(err) 203 218 sys.exit(1) 204 219 205 In this version, \*either\* the file gets opened and the line is read (so it 206 works even on flaky NFS or SMB connections), or the message is printed and the 207 application aborted. 208 209 Still, :func:`get_status` makes too many assumptions --- that it will only be 210 used in a short running script, and not, say, in a long running server. Sure, 211 the caller could do something like :: 220 In this version, *either* the file gets opened and the line is read (so it 221 works even on flaky NFS or SMB connections), or an error message is printed 222 that provides all the available information on why the open failed, and the 223 application is aborted. 224 225 However, even this version of :func:`get_status` makes too many assumptions --- 226 that it will only be used in a short running script, and not, say, in a long 227 running server. Sure, the caller could do something like :: 212 228 213 229 try: … … 216 232 status = None 217 233 218 So, try to make as few ``except`` clauses in your code --- those will usually be 219 a catch-all in the :func:`main`, or inside calls which should always succeed. 220 221 So, the best version is probably :: 234 But there is a better way. You should try to use as few ``except`` clauses in 235 your code as you can --- the ones you do use will usually be inside calls which 236 should always succeed, or a catch-all in a main function. 237 238 So, an even better version of :func:`get_status()` is probably :: 222 239 223 240 def get_status(file): 224 241 return open(file).readline() 225 242 226 The caller can deal with the exception if it wants (for example, if it 243 The caller can deal with the exception if it wants (for example, if it tries 227 244 several files in a loop), or just let the exception filter upwards to *its* 228 245 caller. 229 246 230 The last version is not very good either --- due to implementation details, the 231 file would not be closed when an exception is raised until the handler finishes, 232 and perhaps not at all in non-C implementations (e.g., Jython). :: 247 But the last version still has a serious problem --- due to implementation 248 details in CPython, the file would not be closed when an exception is raised 249 until the exception handler finishes; and, worse, in other implementations 250 (e.g., Jython) it might not be closed at all regardless of whether or not 251 an exception is raised. 252 253 The best version of this function uses the ``open()`` call as a context 254 manager, which will ensure that the file gets closed as soon as the 255 function returns:: 233 256 234 257 def get_status(file): 235 fp = open(file) 236 try: 258 with open(file) as fp: 237 259 return fp.readline() 238 finally:239 fp.close()240 260 241 261 … … 262 282 :func:`splitext`. 263 283 264 There are also many useful built-in functions people seem not to be aware of for 265 some reason: :func:`min` and :func:`max` can find the minimum/maximum of any 266 sequence with comparable semantics, for example, yet many people write their own 267 :func:`max`/:func:`min`. Another highly useful function is :func:`reduce`. A 268 classical use of :func:`reduce` is something like :: 269 270 import sys, operator 271 nums = map(float, sys.argv[1:]) 272 print reduce(operator.add, nums)/len(nums) 273 274 This cute little script prints the average of all numbers given on the command 275 line. The :func:`reduce` adds up all the numbers, and the rest is just some 276 pre- and postprocessing. 277 278 On the same note, note that :func:`float`, :func:`int` and :func:`long` all 279 accept arguments of type string, and so are suited to parsing --- assuming you 280 are ready to deal with the :exc:`ValueError` they raise. 284 There are also many useful built-in functions people seem not to be aware of 285 for some reason: :func:`min` and :func:`max` can find the minimum/maximum of 286 any sequence with comparable semantics, for example, yet many people write 287 their own :func:`max`/:func:`min`. Another highly useful function is 288 :func:`reduce` which can be used to repeatly apply a binary operation to a 289 sequence, reducing it to a single value. For example, compute a factorial 290 with a series of multiply operations:: 291 292 >>> n = 4 293 >>> import operator 294 >>> reduce(operator.mul, range(1, n+1)) 295 24 296 297 When it comes to parsing numbers, note that :func:`float`, :func:`int` and 298 :func:`long` all accept string arguments and will reject ill-formed strings 299 by raising an :exc:`ValueError`. 281 300 282 301
Note:
See TracChangeset
for help on using the changeset viewer.