Python 3中的range对象中的__contains__方法

另一个值得一提的是,在Python 3.x中,range有了一个新的__contains__方法。__contains__方法可以有效的加快Python 3.x中整数和布尔型的“查找”速度。

  1. x = 10000000 
  2. def val_in_range(x, val): 
  3.     return val in range(x) 
  4.  
  5. def val_in_xrange(x, val): 
  6.     return val in xrange(x) 
  7.  
  8. print('Python', python_version()) 
  9. assert(val_in_range(x, x/2) == True
  10. assert(val_in_range(x, x//2) == True
  11. %timeit val_in_range(x, x/2
  12. %timeit val_in_range(x, x//2
  1. Python 3.4.1 
  2. 1 loops, best of 3742 ms per loop 
  3. 1000000 loops, best of 31.19 µs per loop 

根据上面的timeit的结果,查找整数比查找浮点数要快大约6万倍。但由于Python 2.x中的range或xrange没有__contains__方法,所以在Python 2中的整数和浮点数的查找速度差别不大。

  1. print 'Python', python_version() 
  2.  
  3. assert(val_in_xrange(x, x/2.0) == True
  4. assert(val_in_xrange(x, x/2) == True
  5. assert(val_in_range(x, x/2) == True
  6. assert(val_in_range(x, x//2) == True
  7. %timeit val_in_xrange(x, x/2.0
  8. %timeit val_in_xrange(x, x/2
  9. %timeit val_in_range(x, x/2.0
  10. %timeit val_in_range(x, x/2
  1. Python 2.7.7 
  2. 1 loops, best of 3285 ms per loop 
  3. 1 loops, best of 3179 ms per loop 
  4. 1 loops, best of 3658 ms per loop 
  5. 1 loops, best of 3556 ms per loop 

下面的代码证明了Python 2.x中没有__contain__方法:

  1. print('Python', python_version()) 
  2. range.__contains__ 
  1. Python 3.4.1 
  2. <slot wrapper '__contains__' of 'range' objects 
  1. print('Python', python_version()) 
  2. range.__contains__ 
  1. Python 2.7.7 
  2. --------------------------------------------------------------------------- 
  3. AttributeError Traceback (most recent call last) 
  4. <ipython-input-7-05327350dafbin <module>() 
  5. 1 print 'Python', python_version() 
  6. ----> 2 range.__contains__ 
  7.  
  8. AttributeError: 'builtin_function_or_method' object has no attribute '__contains__' 
  1. print('Python', python_version()) 
  2. xrange.__contains__ 
  1. Python 2.7.7 
  2.  
  3. --------------------------------------------------------------------------- 
  4. AttributeError Traceback (most recent call last) 
  5. in () 
  6. 1 print 'Python', python_version() 
  7. ----> 2 xrange.__contains__ 
  8.  
  9. AttributeError: type object 'xrange' has no attribute '__contains__' 

关于Python 2中xrange()与Python 3中range()之间的速度差异的一点说明:

有读者指出了Python 3中的range()和Python 2中xrange()执行速度有差异。由于这两者的实现方式相同,因此理论上执行速度应该也是相同的。这里的速度差别仅仅是因为Python 3的总体速度就比Python 2慢。

  1. def test_while(): 
  2.     i = 0 
  3.     while i < 20000
  4.         i += 1 
  5.     return 
  1. print('Python', python_version()) 
  2. %timeit test_while() 
  1. Python 3.4.1 
  2. %timeit test_while() 
  3. 100 loops, best of 32.68 ms per loop 
  1. print 'Python', python_version() 
  2. %timeit test_while() 
  1. Python 2.7.6 
  2. 1000 loops, best of 31.72 ms per loop 

触发异常

Python 2支持新旧两种异常触发语法,而Python 3只接受带括号的的语法不然会触发SyntaxError):

Python 2

print 'Python', python_version()
Python 2.7.6
raise IOError, "file error"
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-8-25f049caebb0> in <module>()
----> 1 raise IOError, "file error"

IOError: file error
raise IOError("file error")
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-9-6f1c43f525b2> in <module>()
----> 1 raise IOError("file error")

IOError: file error

Python 3

print('Python', python_version())
Python 3.4.1
raise IOError, "file error"
File "<ipython-input-10-25f049caebb0>", line 1
raise IOError, "file error"
^
SyntaxError: invalid syntax
The proper way to raise an exception in Python 3:
print('Python', python_version())
raise IOError("file error")
Python 3.4.1

---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-11-c350544d15da> in <module>()
1 print('Python', python_version())
----> 2 raise IOError("file error")

OSError: file error

异常处理

Python 3中的异常处理也发生了一点变化。在Python 3中必须使用“as”关键字。

Python 2

print 'Python', python_version()
try:
    let_us_cause_a_NameError
except NameError, err:
    print err, '--> our error message'
Python 2.7.6
name 'let_us_cause_a_NameError' is not defined --> our error message

Python 3

print('Python', python_version())
try:
    let_us_cause_a_NameError
except NameError as err:
    print(err, '--> our error message')
Python 3.4.1
name 'let_us_cause_a_NameError' is not defined --> our error message




评论关闭