美文网首页
Python 中一些容易忽略的知识点(2)

Python 中一些容易忽略的知识点(2)

作者: 捡个七 | 来源:发表于2019-07-17 16:58 被阅读0次

    最近在补 Python 进阶的内容,学习资源来自:Python 进阶,是《Intermediate Python》的中译本。这里面的一些内容,对于我来说是比较容易忽略的知识点。

    对象自省(Inrospection)

    在 Python 中,对象自省也是其强项之一。自省指的是在运行时判断一个对象的类型的能力。下面可以看看 Python 中一些常用的自省能力。

    • dir:返回一个列表。用来查看对象所拥有的属性和方法。

      In [6]: a = 1
      
      In [7]: dir(a)
      Out[7]:
      ['__abs__',
       '__add__',
       '__and__',
       '__bool__',
       '__ceil__',
       '__class__',
       '__delattr__',
       '__dir__',
       '__divmod__',
       '__doc__',
       '__eq__',
       '__float__',
       '__floor__',
       '__floordiv__',
       '__format__',
       '__ge__',
       '__getattribute__',
       '__getnewargs__',
       '__gt__',
       '__hash__',
       '__index__',
       '__init__',
       '__init_subclass__',
       '__int__',
       '__invert__',
       '__le__',
       '__lshift__',
        .....]
      
    • type:返回一个对象的类型。

      In [9]: a = "hello"
      
      In [10]: type(a)
      Out[10]: str
      
    • id:返回任意不同种类对象的唯一 ID

      In [11]: name = "caoqi95"
      
      In [12]: id(name)
      Out[12]: 1875152854352
      
      In [13]: age = 23
      
      In [14]: id(age)
      Out[14]: 1572630272
      

    Python 中还有很多其他方法用于自省。有需要的话,可以看看文档说明。

    解析式(Comprehension)

    解析式是 Python 独有的特性。其是可以从一个数据结构构建另一个新的数据结构序列的结构体。一共有 3 种类型,包括列表,字典和集合解析式。

    • 列表解析式
      列表解析式很常见,如下所示:

      multiples = [i for i in range(30) if i % 3 is 0]
      

      其可以简化 for 循环的代码:

      squared = []
      for i in range(10):
          squared.append(i)
      
      # 简化
      squared = [i**2 for i in range(10)]
      
    • 字典解析式
      字典解析式最常用的就是快速兑换字典的键和值:

      {v:k for k, v in some_dict.item()}
      
    • 集合解析式
      它们跟列表推导式也是类似的。 唯一的区别在于它们使用大括号{}。 如下所示:

      squared = {x**2 for x in [1, 1, 2]}
      

    异常处理

    通常在一些代码中见到的都是单个错误的处理,如下所示:

    try:
        file = open('test.txt', 'rb')
    except IOError as e:
        print('An IOError occurred. {}'.format(e.args[-1]))
    

    其实,还可以同时处理多个错误,下面有 3 种方法可以用来处理多个异常。

    • 把所有可能发生的异常都写在一个元祖里:
      try:
          file = open('test.txt', 'rb')
      except (IOError, EOFError) as e:
          print("An error occurred. {}".format(e.args[-1]))
      
    • 每个异常都起一个 except
      try:
          file = open('test.txt', 'rb')
      except EOFError as e:
          print("An EOF error occurred.")
          raise e
      except IOError as e:
          print("An error occurred.")
          raise e
      
    • 捕捉所有异常:
      try:
          file = open('test.txt', 'rb')
      except Exception:
          raise
      

    对于异常处理,除了 try:.... except:.... 语句外,还有其他语句。

    • finally 从句
      try:
          file = open('test.txt', 'rb')
      except IOError as e:
          print('An IOError occurred. {}'.format(e.args[-1]))
      finally:
          print("This would be printed whether or not an exception occurred!")
      
      finally 从句后面的代码不管异常是否触发,都将会被执行。通常可以用来处理一些善后工作。
    • try/else 语句
      try:
          print('I am sure no exception is going to occur!')
      except Exception:
          print('exception')
      else:
          # 这里的代码只会在 try 语句里没有触发异常时运行,
          # 但是这里的异常将 *不会* 被捕获
          print('This would only run if no exception occurs. And an error here '
              'would NOT be caught.')
      finally:
          print('This would be printed in every case.')
      
      如果想在没有触发异常的时候执行一些代码,可以很轻松地通过一个 else 从句来实现。其中 else 从句只会在没有异常的情况下执行,而且它会在 finally 语句之前执行。

    for - else 结构

    我们一般见到的 for 循环会如下所示,但其实它还会有 else 结构。

    for i in range(10):
         print(i)
    

    下面来看看 for 循环的 else 结构:

    for i in range(2, 10):
        if i > 10: # 此条件在整个循环范围外,因此不会 break
            break
    else:
            print('Hello World')
    
    for i in range(2, 10):
        if i > 5:  # 会 break,未完全执行完整个循环
            break
    else:
            print('Hello World')
    

    可以看出,在 for 循环中,如果没有从任何一个 break中退出,则会执行和 for 对应的 else。即 else 后面的代码只会在循环正常结束的时候执行。

    建议避免在生产环境中使用 for...else 结构,因为其本身的歧义以及和 try....else/finally 完全相反的运作方式,会影响可阅读性。

    open 函数

    我们都是到 open 函数的用法如下:

    with open('file_name', 'r+') as f:
        data = f.read()
    

    其实可以写成下面的形式:

    f = open('file_name', 'r+')
    data = f.read()
    f.close()
    

    为什么都使用第一种形式,而不是第二种形式?这是有原因的。首先,open 函数返回的是一个文件句柄,从操作系统托付给 Python 程序。在处理完成之后,需要归还这个文件句柄,这样才不会超过使用句柄的次数上限。其次,close() 之后在文件 read 成功的条件下,才能被调用。一旦有任何异常,就不能被调用。所以,为了确保不触发任何,就会写成第一种形式。

    相关文章

      网友评论

          本文标题:Python 中一些容易忽略的知识点(2)

          本文链接:https://www.haomeiwen.com/subject/imowsqtx.html