python学习笔记(一)

python学习笔记(一)


list

Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。

list定义:classmates = [‘Michael’, ‘Bob’, ‘Tracy’]

  • len(classmates ): 取list元素个数
  • []: 索引访问,[0]-第一个;[-1]-倒数第一个
  • classmates .append(): 追加元素到末尾
  • classmates .insert(i,’A’): 在索引i处插入元素A
  • classmates .pop(): 删除list末尾元素;返回被删除元素
  • classmates .pop(i): 删除索引i处的元素;返回被删除元素
  • lsit 中元素数据类型可以不同,L = ['Apple', 123, True]
  • list 中元素可以是另一个list,s = ['python', 'java', ['asp', 'php'], 'scheme']

tuple

另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出同学的名字:classmates = ('Michael', 'Bob', 'Tracy'),现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用classmates[0]classmates[-1],但不能赋值成另外的元素。

因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

  • 要定义一个只有1个元素的tuple, tuple(1)表示数字1,tuple(1,)表示元组。

if-else

if <条件判断1>: 
    <执行1> 
elif <条件判断2>: 
    <执行2> 
elif <条件判断3>:
    <执行3>
else:
    <执行4>

int()

int()函数可以将字符创转换为数字;当发现一个字符串并不是合法的数字时就会报错,程序就退出了。

循环

Python的循环有两种,一种是for…in循环,依次把list或tuple中的每个元素迭代出来;第二种循环是while循环,只要条件满足,就不断循环,条件不满足时退出循环。

  1. for…in
   sum = 0
   for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
       sum = sum + x
   print(sum)
  1. while:
   sum = 0
   n = 99
   while n > 0:
       sum = sum + n
       n = n - 2
   print(sum)  

dict

ython内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。

  • 定义

      >>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
      >>> d['Michael']
      95
    
  • 把数据放入dict的方法,除了初始化时指定外,还可以通过key放入:

      >>> d['Adam'] = 67
      >>> d['Adam']
      67
    
  • 要避免key不存在的错误,有两种办法,
    • 通过in判断key是否存在:
      >>> 'Thomas' in d
      False
      
    • 通过dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value:
      >>> d.get('Thomas')
      >>> d.get('Thomas', -1)
      

      注意:返回None的时候Python的交互式命令行不显示结果

  • pop(key)方法,对应的value也会从dict中删除:

      >>> d.pop('Bob')
      75
      >>> d
      {'Michael': 95, 'Tracy': 85}
    
  • 和list比较,dict有以下几个特点:

    1. 查找和插入的速度极快,不会随着key的增加而增加;
    2. 需要占用大量的内存,内存浪费多。

set

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。

  • 要创建一个set,需要提供一个list作为输入集合:

    >>> s = set([1, 2, 3])
    >>> s
    set([1, 2, 3])      
    
  • 重复元素在set中自动被过滤:

    >>> s = set([1, 1, 2, 2, 3, 3])
    >>> s
    set([1, 2, 3])
    
  • 通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:

    >>> s.add(4)
    >>> s
    set([1, 2, 3, 4])
    >>> s.add(4)
    >>> s
    set([1, 2, 3, 4])
    
  • 通过remove(key)方法可以删除元素:

    >>> s.remove(4)
    >>> s
    set([1, 2, 3])
    
  • 两个set可以做数学意义上的交集、并集等操作:

    >>> s1 = set([1, 2, 3])
    >>> s2 = set([2, 3, 4])
    >>> s1 & s2
    set([2, 3])
    >>> s1 | s2
    set([1, 2, 3, 4])
    

函数

定义函数

定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x  
  • 空函数: 如果想定义一个什么事也不做的空函数,可以用pass语句:

    def nop():
        pass
    
  • 类型检查: 用内置函数isinstance()实现:

    def my_abs(x):
        if not isinstance(x, (int, float)):
            raise TypeError('bad operand type')
        if x >= 0:
            return x
        else:
            return -x
    
    
  • 返回多个值

    • python 可以返回多个值:

      import math
      
      def move(x, y, step, angle=0):
          nx = x + step * math.cos(angle)
          ny = y - step * math.sin(angle)
          return nx, ny
      
      >>> x, y = move(100, 100, 60, math.pi / 6)
      >>> print(x, y)
      151.96152422706632 70.0
      
    • 其实这是一个假象:python的饭后值任然是单一的,是一个tuple。

      >>> r = move(100, 100, 60, math.pi / 6)
      >>> print(r)
      (151.96152422706632, 70.0)
      
  • 函数参数: Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。

    • 默认参数

      def power(x, n=2):
          s = 1
          while n > 0:
              n = n - 1
              s = s * x
          return s
      

      必选参数在前,默认参数在后,否则Python的解释器会报错

    • 默认参数很有用,但使用不当,也会掉坑里。默认参数有个最大的坑,演示如下:

      • 先定义一个函数,传入一个list,添加一个END再返回:

          def add_end(L=[]):
              L.append('END')
              return L
        
      • 当你正常调用时,结果似乎不错:

          >>> add_end([1, 2, 3])
          [1, 2, 3, 'END']
          >>> add_end(['x', 'y', 'z'])
          ['x', 'y', 'z', 'END']
        

      • 当你使用默认参数调用时,一开始结果也是对的:

          >>> add_end()
          ['END']
        
      • 但是,再次调用add_end()时,结果就不对了:

          >>> add_end()
          ['END', 'END']
          >>> add_end()
          ['END', 'END', 'END']
        

      很多初学者很疑惑,默认参数是[],但是函数似乎每次都“记住了”上次添加了'END'后的list。原因解释如下:

      Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

      所以,定义默认参数要牢记一点:默认参数必须指向不变对象!

    • 可变参数

      • 要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,这样,函数可以定义如下:

          def calc(numbers):
              sum = 0
              for n in numbers:
                  sum = sum + n * n
              return sum
        
          >>> calc([1, 2, 3])
          14
        
      • 我们把函数的参数改为可变参数:

          def calc(*numbers):
              sum = 0
              for n in numbers:
                  sum = sum + n * n
              return sum
        

        定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:

          >>> calc(1, 2)
          5
        
    • 关键字参数

      • 关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。

        def person(name, age, **kw):
            print('name:', name, 'age:', age, 'other:', kw)
        

      • 函数person除了必选参数nameage外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数:

        >>> person('Michael', 30)
        name: Michael age: 30 other: {}
        

      • 也可以传入任意个数的关键字参数:

          >>> person('Bob', 35, city='Beijing')
          name: Bob age: 35 other: {'city': 'Beijing'}
          >>> person('Adam', 45, gender='M', job='Engineer')
          name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
        
    • 命名关键字:

      • 和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数。

        def person(name, age, *, city, job):
            print(name, age, city, job)
        
        >>> person('Jack', 24, city='Beijing', job='Engineer')
        Jack 24 Beijing Engineer
        
      • 命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:

        >>> person('Jack', 24, 'Beijing', 'Engineer')
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        TypeError: person() takes 2 positional arguments but 4 were given
        
    • 组合参数

      • 参数定义的顺序必须是:必选参数、默认参数、可变参数/命名关键字参数和关键字参数。

              
        def f1(a, b, c=0, *args, **kw):
            print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
        
        def f2(a, b, c=0, *, d, **kw):
            print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
        
        >>> f1(1, 2)
        a = 1 b = 2 c = 0 args = () kw = {}
        >>> f1(1, 2, c=3)
        a = 1 b = 2 c = 3 args = () kw = {}
        >>> f1(1, 2, 3, 'a', 'b')
        a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
        >>> f1(1, 2, 3, 'a', 'b', x=99)
        a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
        >>> f2(1, 2, d=99, ext=None)
        a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
        
        # 最神奇的是通过一个tuple和dict,你也可以调用上述函数:
        >>> args = (1, 2, 3, 4)
        >>> kw = {'d': 99, 'x': '#'}
        >>> f1(*args, **kw)
        a = 1 b = 2 c = 3 args = () kw = {'d': 99, 'x': '#'}
        >>> args = (1, 2, 3)
        >>> kw = {'d': 88, 'x': '#'}
        >>> f2(*args, **kw)
        a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
        

        *args是可变参数,args接收的是一个tuple;

        **kw是关键字参数,kw接收的是一个dict。

        以及调用函数时如何传入可变参数和关键字参数的语法:

        • 可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过*args传入:func(*(1, 2, 3))
        • 关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过**kw传入:func(**{'a': 1, 'b': 2})
  • 切片

    >>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
    >>> L[0:3]
    ['Michael', 'Sarah', 'Tracy']
    >>> L[:3]
    ['Michael', 'Sarah', 'Tracy']
    
    >>> L = list(range(100))
    >>> L
    [0, 1, 2, 3, ..., 99]
    
    #前10个数,每两个取一个:
    >>> L[:10:2]
    [0, 2, 4, 6, 8]
    
    # 只写[:]就可以原样复制一个list:
    >>> L[:]
    [0, 1, 2, 3, ..., 99]
    
    # 字符串'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:
    >>> 'ABCDEFG'[:3]
    'ABC'
    >>> 'ABCDEFG'[::2]
    'ACEG'
    
    
  • 迭代

    • dict迭代

          
      d = {'a': 1, 'b': 2, 'c': 3}
      
      # 按照key迭代
      >>> for key in d:
      ...     print(key)
      
      # 按照value迭代
      for value in d.values()
      
      # 按照k-v迭代
      for k, v in d.items()
      
    • 判断可迭代:通过collections模块的Iterable类型判断

      >>> from collections import Iterable
      >>> isinstance('abc', Iterable) # str是否可迭代
      True
      >>> isinstance([1,2,3], Iterable) # list是否可迭代
      True
      >>> isinstance(123, Iterable) # 整数是否可迭代
      False
      
    • 下标循环:Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:

      >>> for i, value in enumerate(['A', 'B', 'C']):
      ...     print(i, value)
      ...
      0 A
      1 B
      2 C
      
  • 列表生成式

    >>> list(range(1, 11))
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    >>> [x * x for x in range(1, 11)]
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    
    >>> [x * x for x in range(1, 11) if x % 2 == 0]
    [4, 16, 36, 64, 100]
    
    >>> [m + n for m in 'ABC' for n in 'XYZ']
    ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
    
    >>> import os # 导入os模块,模块的概念后面讲到
    >>> [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
    ['.emacs.d', '.ssh', '.Trash', 'Adlm', 'Applications', 'Desktop', 'Documents', 'Downloads', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'VirtualBox VMs', 'Workspace', 'XCode']
    
    >>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
    >>> [k + '=' + v for k, v in d.items()]
    ['y=B', 'x=A', 'z=C']
    
  • 生成器

    >>> L = [x * x for x in range(10)]
    >>> L
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> g = (x * x for x in range(10))
    >>> g
    <generator object <genexpr> at 0x1022ef630>
    # 创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
    
    #遍历
    >>> g = (x * x for x in range(10))
    >>> for n in g:
    ...     print(n)
    
    #要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a + b
            n = n + 1
        return 'done'
    
    >>> f = fib(6)
    >>> f
    <generator object fib at 0x104feaaa0>
    
    >>> for n in fib(6):
    ...     print(n)