Python官方文档学习一

Python文件的编码方式

  • 默认情况下,Python源码文件是以UTF-8编码方式处理的
  • 如果不使用默认编码,要声明文件所使用的编码,文件的第一行要写成特殊的注释 # -*- coding: encoding -*-,其中encoding可以是Python支持的任意一种codecs,比如要声明使用Windows-1252编码,文件的第一行为 # -*- coding:cp1252 -*-。关于第一行的另一种情况是源码以UNIX shebang行开头时,编码声明应该写在第二行:
  # !/usr/bin/env python3
  # -*- coding:cp1252

Python作为计算器使用

  • 运算符 +、-、*、/ 的用法和其他大部分语言一样(比如 Pascal 或者 C 语言);括号 (()) 用来分组

  • 除法运算(/)永远返回浮点数类型。如果要做floor division得到一个整数结果可以使用//运算符;如果要计算余数,可以使用%:

        >>> 17 / 3 # classic division returns a float
        5.666666666666667
        >>> 17 // 3 # floor division discards the fractional part
        5
        >>> 17 % 3 # the % operator returns the remainder of the division
        2
        >>> 5 * 3 + 2 # result * divisor + remainder
        17
    

Python字符串

  • Python字符串支持索引和切片,切片的开始被包含在结果里而结束不被包含,所以s[:i]+s[i:]总是等于s

  • 试图使用过大索引会产生一个错误

      >>> word[42] # the word only has 6 characters
        Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        IndexError: string index out of range
    
  • 切片中的越界索引会被自动处理

      >>> word[4:42]
       'on'
    
  • Python中的字符串不能被修改,像字符串的某个索引位置赋值会产生错误

       >>> word[0] = 'J'
      TypeError: 'str' object does not support item assignment
      >>> word[2:] = 'py'
      TypeError: 'str' object does not support item assignment
    
  • 关键词end可以用来取消输出后面的换行,或使用另外一个字符串来结尾

      print(1,2,3, end=',')
      print(9,8,7)
      output:1,2,3,9,8,7
    

Python列表

  • 列表可以包含不同类型的数据
  • 列表可以被索引和切片,且所有的切片操作都返回一个新列表

Python中for循环语句

如果在循环内需要修改序列中的值(比如重复某些选中的元素,推荐先拷贝一个副本

  words = ['cat', 'window', 'defenestrate']
  for w in words[:]:
    if len(w) > 6:
      words.insert(0, w)
  words = ['defenestrate', 'cat', 'window', 'defenestrate']

Python range()函数

如果你需要遍历一个数字序列,可以使用内置函数range()

  for i in range(5):
    print(i)
  output:0,1,2,3,4

range也可以以另一个数字开头,或者以指定的增幅增加

range(5,10)
  5,6,7,8,9
range(0,10,3)
  1,3,6,9
range(-10,-100,-30)
  -10,-40,-70

如果你只打印range,会出现奇怪的结果

  print(range(10))
  output:range(0,10)

range()多返回的对象在许多方面表现得像一个列表,但实际却不是,此对象会在你迭代它时基于序列返回连续的项,但它没有真正生成列表,这样可以节省空间。我们说这样的对象是 可迭代的,也就是说,适合作为函数和结构体的参数,这些函数和结构体期望在迭代结束之前可以从中获取连续的元素。我们已经看到 for 语句就是这样一个迭代器。函数 list() 是另外一个,它从可迭代对象中创建列表。

Python中break和continue语句

  • break语句用于跳出最近的for或while循环
      for n in range(2, 21):
      for x in range(2, n):
      	if n % x == 0:
      		print(n, 'equals', x, '*', n // x)
      		break
      else:
      	print(n, 'is a prime number.')
    
      output:
      2 is a prime number.
      3 is a prime number.
      4 equals 2 * 2
      5 is a prime number.
      6 equals 2 * 3
      7 is a prime number.
      8 equals 2 * 4
      9 equals 3 * 3
      10 equals 2 * 5
      11 is a prime number.
      12 equals 2 * 6
      13 is a prime number.
      14 equals 2 * 7
      15 equals 3 * 5
      16 equals 2 * 8
      17 is a prime number.
      18 equals 2 * 9
      19 is a prime number.
      20 equals 2 * 10
    
  • continue语句表示继续循环中的下一次迭代
    for num in range(2, 10):
      if num % 2 == 0:
      	print('Found an even number', num)
      	continue
      print('Found a number', num)
    
      output:
      Found an even number 2
      Found a number 3
      Found an even number 4
      Found a number 5
      Found an even number 6
      Found a number 7
      Found an even number 8
      Found a number 9
    

定义函数

  • 函数被调用时,实参会被引用到被调用函数的local symbol table中。实参是通过按值调用传递的(其中的值始终是对象引用而不是对象的值)。
  • 函数定义会把函数名引入当前的symbol table中。函数名称的值通过解释器将其识别为用户定义函数的类型。这个值可以分配给另外一个名称,该名称也可以作为一个函数使用
      def add(n, m):
          print(n + m)
    
      a = add
      a(2, 3)
    
  • 函数参数说明
    • 参数默认值

      def ask_ok(prompt, retries=4,reminder='please try again.'):
          while True:
          	ok = input(prompt)
          	if ok in ('y', 'ye', 'yes'):
          		return True
          	if ok in ('n', 'no', 'nop', 'nope'):
          		return False
          	retries-=1
          	if retries<0:
          		raise ValueError('invalid user response')
          	print(reminder)
      ask_ok('Do you really want to quit?')
      ask_ok('OK to overwrite the file?', 2)
      ask_ok('OK to overwrite the file?', 2, 'Come on, only yes
      or no!')
      
      • 参数中的默认值是在函数定义出定义的,默认值只会执行一次。这条规则在默认值为可变对象(列表、字典等)时很重要。
        i = 5
        def f(arg=i):
          print(arg)
        i = 6
        f() output:5
      
        def f(a, L=[]):
          L.append(a)
          return L
        
        print(f(1))
        print(f(2))
        print(f(3))
        output:
        [1]
        [1,2]
        [1,2,3]
      

      如果不想在后续调用之间共享默认值,可以这样写函数

         def f(a, L=None): #指定默认参数为不可变数据类型,最佳实践
           if L is None:
             L = []
           L.append(a)
           return L
      
    • 位置参数:When a final formal parameter of the form **name is present, it receives a dictionary (see typesmapping) containing all keyword arguments except for those corresponding to a formal parameter. This may be combined with a formal parameter of the form name (described in the next subsection) which receives a tuple containing the positional arguments beyond the formal parameter list. (***name must occur before *name.**)

        def cheeseshop(kind, *arguments, **keywords):
          print("-- Do you have any", kind, "?")
          print("-- I'm sorry, we're all out of", kind)
          for arg in arguments:
            print(arg)
            print("-" * 40)
          for kw in keywords:
            print(kw, ":", keywords[kw])
      
        cheeseshop("Limburger", "It's very runny, sir.",
                    "It's really very, VERY runny, sir.",
                    shopkeeper="Michael Palin",
                    client="John Cleese",
                    sketch="Cheese Shop Sketch")
      
    • 任意数量的参数列表,这些参数会被包含在一个元组里。在可变数量的参数之前,可能会出现零个或多个普通参数。一般来说这些可变参数将在形参列表的末尾,因为它们接受传递给函数所有剩余输入参数,出现在*args参数之后的任何形式参数都是关键字参数

        def concat(*args, sep='/'):
          return sep.join(args)
      
        concat('earth','mars','venus')
        output:'earth/mars/venus'
      
    • 解包参数列表,当参数在列表或者字典里需要解包成参数给函数调用时,列表参数使用*args,字典参数使用**kargs。

        def f(a, b):
            print(a + b)
      
        l1 = [2, 3]
        f(*l1)
        l2 = {'a': 2, 'b': 3}
        f(**l2)
      
    • Lambda表达式,可以用lambda关键字来创建一个小的匿名函数。它在语法上仅限于单个表达式,从语义上来讲,它只是正常函数定义的语法糖

        def make_incrementor(n):
          return lambda x: x+n
        f = make_incrementor(42)
        f(0) 42
        f(1) 43
      

数据结构

  • 列表的更多特性
  • 1.列表的方法
  • list.append(x)
  • list.extend(iterable),使用可迭代对象中的所有元素来扩展列表,相当于a[len(a):]=iterable
  • list.insert(i,x)
  • list.remove(x),Remove the first item from the list whose value is x
  • list.pop([i]),删除列表中给定位置的元素并返回它。如果没有给定位置,则删除并返回列表最后一个元素
  • list.clear(),移除列表中所有的元素。等价于del a[:]
  • list.index(x[,start[,end]]),返回第一个值为x的元素的索引值,可选参数start和end是切片符号,用于>搜>索限制为列 表的特> * 定子序列,返回的索引是相对于整个序列开始计算的,而不是start参数
  • list.count(x),返回元素x在列表中出现的次数
  • list.sort(key=None, reverse=Flase),对列表中的元素进行排序
  • list.reverse(),翻转列表中的元素
  • list.copy(),返回列表的一个浅拷贝,等价于a[:]
  • 2.列表作为队列使用,“先进先出”对于列表来说很低效,因为在列表的开头插入或弹出元素很慢(所有的其他元素都必须移动一位)。若想实现一个队列,可使用collections.deque,它被设计成可以快速从两端添加或弹出元素
  from collections import deque
  queue = deque(['Eric','John','Michael'])
  queue.append('Terry')
  queue.append('Graham')
  queue.popleft()
  queue.popleft()
  print(queue)
  • 列表推导式
  • 把某种操作应用于序列或可迭代对象的每个元素上,然后使用其结果来创建列表,或者通过满足某些特定条件元素来创建子序列
```python
  squares = []
  for x in range(10):
    squares.append(x**2)
  squares = list(map(lambda x: x**2, range(10)))
  squares = [x**2 for x in range(10)]
```
  • 元组和序列
    一个元组由几个被逗号隔开的值组成,元组在输出时总是被圆括号包围,输入时圆括号可有可无。给元组中的一个单独的元素赋值是不允许的,但是可以创建包含可变对象的元组,例如列表。

  • 集合
    集合是由不重复元素组成的无序的集,它的基本用法包括成员检测和消除重复元素。集合对象也支持像联合,交集,差集,对称等分等数学运算。
    花括号或set()函数可以用来创建集合。注:创建一个空集合只能用set()而不能用{},因为后者是创建一个空字典。

  • 字典
    字典是以关键字为索引的,关键字可以是任意不可变类型,通常是字符串或数字。字典主要的操作是使用关键字存储和解析值,也可以用del来删除一个键值对。

     >>> tel = {'jack': 4098, 'sape': 4139}
     >>> tel['guido'] = 4127
     >>> tel
     {'sape': 4139, 'guido': 4127, 'jack': 4098}
     >>> tel['jack']
     4098
     >>> del tel['sape']
     >>> tel['irv'] = 4127
     >>> tel
     {'guido': 4127, 'irv': 4127, 'jack': 4098}
     >>> list(tel.keys())
     ['irv', 'guido', 'jack']
     >>> sorted(tel.keys())
     ['guido', 'irv', 'jack']
     >>> 'guido' in tel
     True
     >>> 'jack' not in tel
     False
    

    dict()构造函数的使用

    >>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]  )
    {'sape': 4139, 'jack': 4098, 'guido': 4127}
    >>> dict(sape=4139, guido=4127, jack=4098)
    {'sape': 4139, 'jack': 4098, 'guido': 4127}
    
  • 序列循环

  • 在字典里使用items()方法可将关键字和对应的值同时取出
    python knights = {'gallahad': 'the pure', 'robin': 'the brave'} for k, v in knights.items(): print(k, v) gallahad the pure robin the brave
  • 当在序列中循环时,用enumerate()函数可以将索引位置和对应的值同时取出
    python for i, v in enumerate(['tic', 'tac', 'toe']): print(i, v) 0 tic 1 tac 2 toe
  • 当同时在两个或更多序列中循环时,可以用zip()函数将其内元素一一匹配
    python questions = ['name', 'quest', 'favorite color'] answers = ['lancelot', 'the holy grail', 'blue', 'red'] for q, a in zip(questions, answers): print('what is your {0}? It is {1}'.format(q, a)) what is your name? It is lancelot what is your quest? It is the holy grail what is your favorite color? It is blue
  • 如果要按某个指定顺序循环一个序列,可以用sorted()函数,它可以在不改动原序列的基础上返回一个新的排好序的序列,有时可能会想在循环时修改列表内容,一般来说改为创建一个新列表是比较简单且安全的
    python basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] for f in sorted(set(basket)): print(f) apple banana orange pear import math raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8] filtered_data = [] for value in raw_data: if not math.isnan(value): filtered_data.append(value) print(raw_data) print(filtered_data) [56.2, nan, 51.7, 55.3, 52.5, nan, 47.8] [56.2, 51.7, 55.3, 52.5, 47.8]
  • 序列比较
    序列对象可以与相同类型的其他对象比较。它们使用字典顺序进行比较:首先比较两个序列的第一个元素,如果不同,那么这就决定了比较操作的结果。如果它们相同,就再比较序列的第二个元素,以此类推,直到有一个序列被耗尽。
  • 读写文件,open(filename, mode)mode可以是'r',表示文件只能读取,'w'表示只能写入(已存在的同名文件会被删除),'a'表示打开文件以追加内容,任何写入的数据会自动添加到文件的末尾,'r+'表示打开文件进行读写。mode参数是可选的,默认为'r'。通常文件以text mode打开,在mode中追加'b'则以binary mode打开文件,现在数据是以字节对象的形式进行读写的。
  • 文件对象的方法
  • f.read(size),size为可选参数,当未提供size时,全部内容会被读取返回。如果已经读取到文件的最末端,再一次调用f.read()将返回空值。

      f.read()
     'This is the entire file.\n'
      f.read()
     ''
    
  • f.readline()从文件中读取一行;换行符留在字符串的末尾。如果f.readline()返回一个空的字符串,则表示已经到达文件末尾,而空行使用'\n'表示,该字符串质保函一个换行符

    >>> f.readline()
    'This is the first line of the file.\n'
    >>> f.readline()
    'Second line of the file\n'
    >>> f.readline()
    ''
    

    要从文件中读取行,可以循环遍历文件对象。

    >>> for line in f:
    ... 	print(line, end='')
    ...
    This is the first line of the file.
    Second line of the file
    

    如果想以列表的形式读取文件中的所有行,可以使用list(f)或f.readlines()。

  • f.write(string)会把string的内容写入到文件中,并返回写入的字符数。在写入其他类型的对象之前,需要先把它们转化为字符串或者字节对象

    >>> value = ('the answer', 42)
    >>> s = str(value) # convert the tuple to string
    >>> f.write(s)
    18
    
  • f.tell()返回一个整数,给出文件对象在文件中的当前位置,二进制模式下时从文件开始的字节数。改变文件对象的位置,使用f.seek(offset, from_what),from_what为0表示从文件开始处,为1表示从文件当前位置,为2便是从文件最末端,默认from_what为0。

    >>> f = open('workfile', 'rb+')
    >>> f.write(b'0123456789abcdef')
    16
    >>> f.seek(5) # Go to the 6th byte in the file
    5
    >>> f.read(1)
    b'5'
    >>> f.seek(-3, 2) # Go to the 3rd byte before the end
    13
    >>> f.read(1)
    b'd'
    

    在文本文件(那些在模式字符串中没有 b 的打开的文件)中,只允许相对于文件开头搜索(使用 seek(0,2) 搜索到文件末尾是个例外)并且唯一有效的 offset 值是那些能从 f.tell() 中返回的或者是零。其他 offset
    值都会产生未定义的行为。

  • 使用json保存结构化数据

    字符串可以写入文件并从文件中读取出来,数字可能会麻烦一点,因为read()方法只能返回字符串,这些字符串必须传递给类似int()的函数。当想保存如嵌套列表和字典这样更复杂的数据类型时,手动解析和序列化会变得复杂。

    json格式 ===> 字符串:serializing

    字符串 ===> json格式:deserializing

错误与异常

  • 异常处理

    >>> while True:
    ... 	try:
    ... 		x = int(input("Please enter a number: "))
    ... 		break
    ... 	except ValueError:
    ... 		print("Oops! That was no valid number. Try again...")
    

    try语句的工作原理:

    1. 首先执行try子句(try和except关键字之间的语句)
    2. 如果没有异常发生,则跳过except子句并完成try语句
    3. 如果在执行try子句时发生了异常,则跳过该子句中剩下的部分。如果异常类型和except关键字后面的异常匹配,则执行except子句,然后继续执行try语句之后的代码
    4. 如果不匹配,则将其传递到外部的try语句中。如果没有找到处理程序,则它是一个未处理异常,执行将停止并显示消息。

    try...except语句有一个可选的else子句,在使用时必须放在所有的except子句后面。对于在try子句不引发异常时必须执行的代码来说很有用。

  • 异常参数

    except子句可以在异常名称后面指定一个变量。这个变量和一个异常实例绑定,它的参数存储在instance.args中。为了方便起见,异常实例定义了__str__(),因此可以直接打印参数而无无需引入.args。也可以在抛出之前首先实例化异常,并根据需要向其中添加属性:

    >>> try:
    ... 	raise Exception('spam', 'eggs')
    ... except Exception as inst:
    ... 	print(type(inst)) # the exception instance
    ... 	print(inst.args) # arguments stored in .args
    ... 	print(inst) # __str__ allows args to be printed directly,
    ... 	# but may be overridden in exception subclasses
    ... 	x, y = inst.args # unpack args
    ... 	print('x =', x)
    ... 	print('y =', y)
    ...
    <class 'Exception'>
    ('spam', 'eggs')
    ('spam', 'eggs')
    x = spam
    y = eggs
    
  • 抛出异常

    raise语句允许强制发生指定异常

    >>> raise NameError('HiThere')
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: HiThere
    

    raise唯一的参数就是要抛出的异常。这个参数必须是一个异常实例或者是一个异常类(派生自Exception的类)。如果传递的是一个异常类,它将通过调用没有参数的构造函数来隐式实例化。

    raise ValueError ==> raise ValueError()

  • 用户自定义异常

    异常通常应该直接或间接地从 Exception 类派生。可以定义异常类,它可以执行任何其他类可以执行的任何操作,但通常保持简单,通常只提供许多属性,这些属性允许处理程序为异常提取有关错误的信息。在创建可能引发多个不同错误的模块时,通常的做法是为该模块定义的异常创建基类,并为不同错误条件创建特定异常类的子类:

    class Error(Exception):
    	"""Base class for exceptions in this module."""
    	pass
    
    class InputError(Error):
    	"""Exception raised for errors in the input.
    	Attributes:
    	expression -- input expression in which the error occurred
    	message -- explanation of the error
    	"""
    	def __init__(self, expression, message):
    		self.expression = expression
    		self.message = message
            
    class TransitionError(Error):
    	"""Raised when an operation attempts a state transition that's not
    	allowed.
    	Attributes:
    	previous -- state at beginning of transition
    	next -- attempted new state
    	message -- explanation of why the specific transition is not allowed
    	"""
    	def __init__(self, previous, next, message):
    		self.previous = previous
    		self.next = next
    		self.message = message
    
  • 定义清理操作

    try语句有另外一个子句,用于定义所有情况下执行的清理操作。A finally clause is always executed before leaving try statement,whether an exception has occurred or not.The finally clause is also executed when any other clause of the try statement is left via break,continue or return statement.

    >>> def divide(x, y):
    ... 	try:
    ...			result = x / y
    ... 		except ZeroDivisionError:
    ...		 	print("division by zero!")
    ... 	else:
    ... 		print("result is", result)
    ... 	finally:
    ... 		print("executing finally clause")
    ...
    >>> divide(2, 1)
    result is 2.0
    executing finally clause
    >>> divide(2, 0)
    division by zero!
    executing finally clause
    >>> divide("2", "1")
    # The TypeError raised by dividing two strings is not handled by the except clause and therefore re-raised after the finally clause has been executed.
    executing finally clause
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 3, in divide
    TypeError: unsupported operand type(s) for /: 'str' and 'str'
    

    在实际应用程序中,finally子句对于释放外部资源(例如文件或者网络连接)非常有用,无论是否成功使用资源。

posted @ 2021-02-12 17:26  jackpod  阅读(91)  评论(0编辑  收藏  举报