zoukankan      html  css  js  c++  java
  • python基础学习

    简介

    龟叔 Guido van rossum

    胶水语言

    提供了非常完善的代码库

    运行速度慢,大小写敏感

    是解释型语言,也就是说,发布项目时相当于发布源代码

    编译型语言,如C语言,运行以后生成exe文件,不能从exe文件反推出C语言代码

    Python语言解释器:

    ​ CPython 使用广泛 >>>

    ​ IPython 基于CPython,在交互方式上有增强 In[序号]

    ​ PyPy 注重于执行速度,动态编译Python

    ​ JPython 编译为java字节码

    ​ IronPython 编译为.NET字节码

    Python代码运行助手

    ​ 让浏览器运行Python代码

    ​ 源码:c:codespythonlearning.py

    ​ 方法:

    ​ 先将python保存为临时文件,然后调用解释器

    语法

    1. 以 : 结尾的语句被视为一个代码块

      条件判断

      ​ if 条件:

      ​ 操作语句

      ​ elif 条件:

      ​ 操作语句

      ​ else:

      ​ 操作语句

      循环

      ​ for l in list:

      ​ 操作语句

      ​ while 条件:

      ​ 操作语句

      range(x,y,z)生成一个整数序列,可以通过list()转换成list数据类型;x代表开始数字,y代表结束数字,z代表隔z个数字取

    2. print("your name is %s" % name)

      占位符

      ​ %s 字符串

      ​ %d 整数

      ​ %f 浮点数

      ​ %x 十六进制整数

      ​ %%=%

      整数、浮点数没有大小限制,浮点数超出一定范围直接表示为inf(无限大)、

    list与tuple数组

    tuple和list的主要区别在于,一旦建立,tuple的各个元素不可再变更,而list的各个元素可以再变更

    tuple 元组/定值表

    >>>s1 = (2, 1.3, 'love', 5.6, 9, 12, False)         # s1是一个tuple     
    >>>s2 = [True, 5, 'smile']                          # s2是一个list
    

    list可变数组 list=[]

    ​ list.append(str) 追加元素

    ​ list.insert(index,str) 将字符串插入到指定索引位置

    ​ list.pop() 删除list末尾元素

    ​ list.pop(index) 删除指定索引位置的元素

    ​ list里最后一个字符,索引位置的使用 -1,len(list)-1

    tuple数组定长 tuple=()

    ​ 当tuple数组里只有一个元素时,t=(1,)

    范围引用: 基本样式[下限:上限:步长]
    
    >>>print(s1[:5])             # 从开始到下标4 (下标5的元素 不包括在内)
    
    >>>print(s1[2:])             # 从下标2到最后
    
    >>>print(s1[0:5:2])          # 从下标0到下标4 (下标5不包括在内),每隔2取一个元素 (下标为0,2,4的元素)
    
    >>>print(s1[2:0:-1])         # 从下标2到下标1
    
    从上面可以看到,在范围引用的时候,如果写明上限,那么这个上限本身不包括在内。
    
    尾部元素引用
    
    >>>print(s1[-1])             # 序列最后一个元素
    
    >>>print(s1[-3])             # 序列倒数第三个元素
    
    同样,如果s1[0:-1], 那么最后一个元素不会被引用 (再一次,不包括上限元素本身)
    

    词典

    词典和表类似的地方,是包含有多个元素,每个元素以逗号分隔。但词典的元素包含有两部分,键和值,常见的是以字符串来表示键,也可以使用数字或者真值来表示键(不可变的对象可以作为键)。值可以是任意对象。键和值两者一一对应。

    与表不同的是,词典的元素没有顺序。你不能通过下标引用元素。词典是通过键来引用。

    dic = {'tom':11, 'sam':57,'lily':100}
    #在词典中增添一个新元素的方法:
    >>>dic['lilei'] = 99
    >>>print dic
    #词典的循环调用
    dic = {'lilei': 90, 'lily': 100, 'sam': 57, 'tom': 90}
    for key in dic:
        print dic[key]
    #常用方法
    >>>print dic.keys()           # 返回dic所有的键
    >>>print dic.values()         # 返回dic所有的值
    >>>print dic.items()          # 返回dic所有的元素(键值对)
    >>>dic.clear()                # 清空dic,dict变为{}
    #另外有一个很常用的用法:
    >>>del dic['tom']             # 删除 dic 的‘tom’元素
    #del是Python中保留的关键字,用于删除对象。
    #与表类似,你可以用len()查询词典中的元素总数。
    >>>print(len(dic))
    
    1. sorted函数按key值对字典排序

    ​ 先来基本介绍一下sorted函数,sorted(iterable,key,reverse),sorted一共有iterable,key,reverse这三个参数。

    ​ 其中iterable表示可以迭代的对象,例如可以是 dict.items()、dict.keys()等,key是一个函数,用来选取参与比较的元素,reverse则是用来指定排序是倒序还是顺 序,reverse=true则是倒序,reverse=false时则是顺序,默认时reverse=false。

    ​ 要按key值对字典排序,则可以使用如下语句:

    d={"a":1,"f":3,"e":1,"b":7}
    sorted(d.keys())     #["a","b","e","f"]
    

    ​ 直接使用sorted(d.keys())就能按key值对字典排序,这里是按照顺序对key值排序的,如果想按照倒序排序的话,则只要将reverse置为true即可。

    1. sorted函数按value值对字典排序

    ​ 要对字典的value排序则需要用到key参数,在这里主要提供一种使用lambda表达式的方法,如下:

    d={"a":1,"f":3,"e":1,"b":7}
    sorted(d.items(),key=lambda item:item[1])     #[("a",1),("b",7),("e",1),("f",3)]
    

    这里的d.items()实际上是将d转换为可迭代对象,迭代对象的元素为 ("a",1),("b",7),("e",1),("f",3),items()方法将字典的元素 转化为了元组,而这里key参数对应的lambda表达式的意思则是选取元组中的第二个元素作为比较参数(如果写作key=lambda item:item[0]的话则是选取第一个元素作为比较对象,也就是key值作为比较对象。lambda x:y中x表示输出参数,y表示lambda 函数的返回值),所以采用这种方法可以对字典的value进行排序。注意排序后的返回值是一个list,而原字典中的名值对被转换为了list中的元组。

    列表、阵列

    color=['red','green','blue']  
    print(color[0])  
    color.append('orange') # red,green,blue,orange  
    c=color.pop(1); # 索引为1的元素弹出,并将其赋值给c  
    print(c) # green  
    print(color)  
    color.append(['white','black']) # 添加一项类型为列表的元素['white','black']  
    print(color)  # ['red', 'blue', 'orange', ['white', 'black']]  
    del color[3] # 将其删除  
    print(color) #['red', 'blue', 'orange']  
    color=color+['white','black'] # color列表与['white','black'] 合并并重新赋值给color  
    print(color) #['red', 'blue', 'orange', 'white', 'black']    
    

    请注意上面的color.append(['white','black'])和color=color+['white','black']的区别

    1. 动态生成列表:

      a=[x for x in range(1,11,1)]  
      print(a) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]      
      
    2. 列表的复制 :

      newcopy=data[:]

      列表中套列表即可形成阵列(听起来是不是很牛X?),比如下面, r就是阵列:

      r1=[1,2,3,4,5]  
      r2=[10,20,30,40,50]  
      r3=[100,200,300,400,500]  
      arr=[r1,r2,r3]  
      for row in arr:   
          print(row)   
      
    3. 阵列的操作,比如列提取,行统计

      m=[[1,2,3],[2,3,50],[33,20,30]]  
      n=[row[1]for row in m if row[2]>10]  
      print(n)  
      
      r1=[  1,  2,  3,  4,  5]  
      r2=[ 10, 20, 30, 40, 50]  
      r3=[100,200,300,400,500]  
      arr=[r1,r2,r3]  
      for row in arr:   
          print(row)  
        
      #阵列操作  
      c1=[row[0] for row in arr] #将arr阵列的每行的第1个单元取出,并组成列表后赋值给c1 ,c1是列表类型  
      print(c1) #[1, 10, 100]  
      c11=[row[0]+50 for row in arr] #将arr阵列的每行的第1个单元取出后分别加50后的值组成列表后赋给c11 ,c11是列表类型  
      print(c11)  
      
        
      c2=[row[1] for row in arr if row[1]>=20] #添加条件的取值: 每行第2个元素>=20才考虑  
      print (c2) # [20, 200]  
      #统计阵列中每行的总数  
      s=(sum(row) for row in arr) #创建一个逐行统计的生成器  
      i=0  
      while (i<len(arr)):  
          print ("Line %d, sum=%d" %(i , next(s)))   
          i=i+1      
      
    4. 统计阵列的总数:

      #统计这个阵列的总数  
      line_sum=list(map(sum,arr)) #将arr阵列每行统计数转换成一个列表赋值给line_sum  
      print(line_sum)# [15, 150, 1500]  
      print(sum(line_sum)) #再将每行的统计数再汇总输出:1665 
      

    内置函数

    秉承着一切皆对象的理念,我们再次回头来看函数(function)。函数也是一个对象,具有属性(可以使用dir()查询)。作为对象,它还可以赋值给其它对象名,或者作为参数传递。

    lambda函数

    在展开之前,我们先提一下lambda函数。可以利用lambda函数的语法,定义函数。lambda例子如下:

    func = lambda x,y: x + y
    print func(3,4)
    

    lambda生成一个函数对象。该函数参数为x,y,返回值为x+y。函数对象赋给func。func的调用与正常函数无异。

    以上定义可以写成以下形式:

    def func(x, y):
        return x + y
    

    函数作为参数传递

    函数可以作为一个对象,进行参数传递。函数名(比如func)即该对象。比如说:

    def test(f, a, b):
        print 'test'
        print f(a, b)
    
    test(func, 3, 5)
    

    test函数的第一个参数f就是一个函数对象。将func传递给f,test中的f()就拥有了func()的功能。

    我们因此可以提高程序的灵活性。可以使用上面的test函数,带入不同的函数参数。比如:

    test((lambda x,y: x**2 + y), 6, 9)
    

    map()函数

    map()是Python的内置函数。它的第一个参数是一个函数对象。

    re = map((lambda x: x+3),[1,3,5,6])
    

    这里,map()有两个参数,一个是lambda所定义的函数对象,一个是包含有多个元素的表。map()的功能是将函数对象依次作用于表的每一个元素,每次作用的结果储存于返回的表re中。map通过读入的函数(这里是lambda函数)来操作数据(这里“数据”是表中的每一个元素,“操作”是对每个数据加3)。

    在Python 3.X中,map()的返回值是一个循环对象。可以利用list()函数,将该循环对象转换成表。

    如果作为参数的函数对象有多个参数,可使用下面的方式,向map()传递函数参数的多个参数:

    re = map((lambda x,y: x+y),[1,2,3],[6,7,9])
    

    map()将每次从两个表中分别取出一个元素,带入lambda所定义的函数。

    filter()函数

    filter函数的第一个参数也是一个函数对象。它也是将作为参数的函数对象作用于多个元素。如果函数对象返回的是True,则该次的元素被储存于返回的表中。filter通过读入的函数来筛选数据。同样,在Python 3.X中,filter返回的不是表,而是循环对象。

    filter函数的使用如下例:

    def func(a):
        if a > 100:
            return True
        else:
            return False
    
    print filter(func,[10,56,101,500])
    

    reduce()函数

    reduce函数的第一个参数也是函数,但有一个要求,就是这个函数自身能接收两个参数。reduce可以累进地将函数作用于各个参数。如下例:

    print reduce((lambda x,y: x+y),[1,2,5,7,9])
    

    reduce的第一个参数是lambda函数,它接收两个参数x,y, 返回x+y。

    reduce将表中的前两个元素(1和2)传递给lambda函数,得到3。该返回值(3)将作为lambda函数的第一个参数,而表中的下一个元素(5)作为lambda函数的第二个参数,进行下一次的对lambda函数的调用,得到8。依次调用lambda函数,每次lambda函数的第一个参数是上一次运算结果,而第二个参数为表中的下一个元素,直到表中没有剩余元素。

    上面例子,相当于(((1+2)+5)+7)+9

    reduce()函数在3.0里面不能直接用的,它被定义在了functools包里面,需要引入包。

    range()

    在Python中,for循环后的in跟随一个序列的话,循环每次使用的序列元素,而不是序列的下标。

    之前我们已经使用过range()来控制for循环。现在,我们继续开发range的功能,以实现下标对循环的控制:

    S = 'abcdefghijk'
    for i in range(0,len(S),2):
        print S[i]
    

    在该例子中,我们利用len()函数和range()函数,用i作为S序列的下标来控制循环。在range函数中,分别定义上限,下限和每次循环的步长。这就和C语言中的for循环相类似了。

    enumerate()

    利用enumerate()函数,可以在每次循环中同时得到下标和元素:

    S = 'abcdefghijk'
    for (index,char) in enumerate(S):
        print index
        print char
    

    实际上,enumerate()在每次循环中,返回的是一个包含两个元素的定值表(tuple),两个元素分别赋予index和char

    zip()

    如果你多个等长的序列,然后想要每次循环时从各个序列分别取出一个元素,可以利用zip()方便地实现:

    ta = [1,2,3]
    tb = [9,8,7]
    tc = ['a','b','c']
    for (a,b,c) in zip(ta,tb,tc):
        print(a,b,c)
    

    每次循环时,从各个序列分别从左到右取出一个元素,合并成一个tuple,然后tuple的元素赋予给a,b,c

    zip()函数的功能,就是从多个列表中,依次各取出一个元素。每次取出的(来自不同列表的)元素合成一个元组,合并成的元组放入zip()返回的列表中。zip()函数起到了聚合列表的功能。

    我们可以分解聚合后的列表,如下:

    ta = [1,2,3]
    tb = [9,8,7]
    # cluster
    zipped = zip(ta,tb)
    print(zipped)# decomposena, nb = zip(*zipped)print(na, nb)
    

    abs()&hex()

    abs()返回绝对值

    hex()返回十六进制数

    转换数据类型:int() float() str() bool()

    在解释器中,导入一个python文件里的函数

    from abstest import my_abs
    rag_abs(-5)  
    

    较小的精度

    基础

    浮点数是用机器上浮点数的本机双精度(64 bit)表示的。提供大约17位的精度范围从-308到308的指数。和C语言里面的double类型相同。Python不支持32bit的单精度浮点数。如果程序需要精确控制区间和数字精度,可以考虑使用numpy扩展库。

    Python 3.X对于浮点数默认的是提供17位数字的精度。

    关于单精度和双精度的通俗解释:

    • 单精度型和双精度型,其类型说明符为float 单精度说明符

    • double 双精度说明符。在Turbo C中单精度型占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供七位有效数字。

    • 双精度型占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。

    要求较小的精度

    将精度高的浮点数转换成精度低的浮点数。

    round()内置方法

    这个是使用最多的,刚看了round()的使用解释,也不是很容易懂。round()不是简单的四舍五入的处理方式。

    For the built-in types supporting round(), values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2).

    >>> round(2.5)
    2
    >>> round(1.5)
    2
    >>> round(2.675)
    3
    >>> round(2.675, 2)
    2.67
    

    round()如果只有一个数作为参数,不指定位数的时候,返回的是一个整数,而且是最靠近的整数(这点上类似四舍五入)。但是当出现.5的时候,两边的距离都一样,round()取靠近的偶数,这就是为什么round(2.5) = 2。当指定取舍的小数点位数的时候,一般情况也是使用四舍五入的规则,但是碰到.5的这样情况,如果要取舍的位数前的小树是奇数,则直接舍弃,如果偶数这向上取舍。看下面的示例:

    >>> round(2.635, 2)
    2.63
    >>> round(2.645, 2)
    2.65
    >>> round(2.655, 2)
    2.65
    >>> round(2.665, 2)
    2.67
    >>> round(2.675, 2)
    2.67
    
    使用格式化

    效果和round()是一样的。

    >>> a = ("%.2f" % 2.635)
    >>> a
    '2.63'
    >>> a = ("%.2f" % 2.645)
    >>> a
    '2.65'
    >>> a = int(2.5)
    >>> a
    2
    
    要求超过17位的精度分析

    python默认的是17位小数的精度,但是这里有一个问题,就是当我们的计算需要使用更高的精度(超过17位小数)的时候该怎么做呢?

    使用格式化(不推荐)
    >>> a = "%.30f" % (1/3)
    >>> a
    '0.333333333333333314829616256247'
    

    可以显示,但是不准确,后面的数字往往没有意义。

    decimal+getcontext

    高精度使用decimal模块,配合getcontext

    >>> from decimal import *
    >>> print(getcontext())
    Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
    >>> getcontext().prec = 50
    >>> b = Decimal(1)/Decimal(3)
    >>> b
    Decimal('0.33333333333333333333333333333333333333333333333333')
    >>> c = Decimal(1)/Decimal(17)
    >>> c
    Decimal('0.058823529411764705882352941176470588235294117647059')
    >>> float(c)
    0.058823529411764705
    

    默认的context的精度是28位,可以设置为50位甚至更高,都可以。这样在分析复杂的浮点数的时候,可以有更高的自己可以控制的精度。其实可以留意下context里面的这rounding=ROUND_HALF_EVEN 参数。ROUND_HALF_EVEN, 当half的时候,靠近even.

    小数和取整

    既然说到小数,就必然要说到整数。一般取整会用到这些函数:

    round()

    这个不说了,前面已经讲过了。一定要注意它不是简单的四舍五入,而是ROUND_HALF_EVEN的策略。

    math模块的ceil(x)

    取大于或者等于x的最小整数。

    math模块的floor(x)

    去小于或者等于x的最大整数.

    >>> from math import ceil, floor
    >>> round(2.5)
    2
    >>> ceil(2.5)
    3
    >>> floor(2.5)
    2
    >>> round(2.3)
    2
    >>> ceil(2.3)
    3
    >>> floor(2.3)
    2
    >>>
    

    生成器

    生成器(generator)的主要目的是构成一个用户自定义的循环对象。

    生成器的编写方法和函数定义类似,只是在return的地方改为yield。生成器中可以有多个yield。当生成器遇到一个yield时,会暂停运行生成器,返回yield后面的值。当再次调用生成器的时候,会从刚才暂停的地方继续运行,直到下一个yield。生成器自身又构成一个循环器,每次循环使用一个yield返回的值。

    下面是一个生成器:

    def gen():
        a = 100
        yield a
        a = a*8
        yield a
        yield 1000
    

    该生成器共有三个yield, 如果用作循环器时,会进行三次循环。

    for i in gen():
        print i
    

    再考虑如下一个生成器:

    def gen():
        for i in range(4):
            yield i
    

    它又可以写成生成器表达式(Generator Expression):

    G = (x for x in range(4))
    

    生成器表达式是生成器的一种简便的编写方式。

    测试代码:

    def gen():
        for i in range(4):
            yield i
            
    for i in gen():
        print i
    
    G = (x for x in range(4))
    for i in G:
        print(i)
    

    表推导

    表推导(list comprehension)是快速生成表的方法。它的语法简单,很有实用价值。

    假设我们生成表L:

    L = []
    for x in range(10):
        L.append(x**2)
    

    以上产生了表L,但实际上有快捷的写法,也就是表推导的方式:

    L = [x**2 for x in range(10)]
    

    这与生成器表达式类似,只不过用的是中括号。

    自定义函数

    对于基本数据类型的变量,变量传递给函数后,函数会在内存中复制一个新的变量,从而不影响原来的变量。(我们称此为值传递)

    但是对于表来说,表传递给函数的是一个指针,指针指向序列在内存中的位置,在函数中对表的操作将在原有内存中进行,从而影响原有变量。 (我们称此为指针传递)

    自定义函数

    ​ def 函数名(参数列表):

    ​ 函数内容

    ​ return = return none

    空函数:

    def pop():
        pass   #占位符,让程序先运行起来
    

    函数可以返回多个值,这多个值作为一个tuple返回,这个tuple也可以按照位置赋值给多个变量

    数据类型检查

    def my_abs(x):
    	if not isinstance(x,(int,float)):           #isinstance(x,数据类型)判断x是否为该数据类型
    		raise TypeError('bad operand type')
    	if x>0:
    		return x
    	if x<0:
    		return -x
    

    函数的参数列表:

    • 正常定义的必选参数
    • 默认参数
    • 可变参数
    • 关键字参数
    • 命名关键字参数

    默认参数

    设置参数的默认值 如:def power(x,y=2)
    必选参数在前;变化大的在前
    调用默认参数:
    正常传参,顺序调用;
    不按顺序调用,要用参数名 如

    enroll('Adam','M',city='tianjin')
    def enroll(name,sex,age=18,city='beijing')
    多次调用默认参数函数时的异常情况:

        def app_end(L=[]):
             L.append('END')
             return L                     #多次调用后L=['END','END',...]
         def app_end(L=None):
             if L is None:
                 L=[]
             L.append('END')
             return L                     #多次调用后L=['END']
    

    可变参数

    def calc(numbers):
    调用 calc(1,2,3,4) #调用时可任意传参,甚至0个参数
    def calc(numbers):
    调用 calc([1,2,3]) calc((1,2,3)) #只能传入list/tuple
    如果将list/tuple作为参数 calc(
    list/*tuple)

    def func(**dict):
        print type(dict)
        print dict
    
    func(a=1,b=9)
    func(m=2,n=1,c=11)关键字参数
    

    可变参数

    传入0/多个参数,传入时自动组装成tuple

    关键字参数

    传入0/多个含参数名的参数,自动组装成dictionary

    命名关键字参数

    可以有缺省值
    def person(name,age,,city,job)
    def person(name,age,
    city,job)
    如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*
    * 分隔符,*后均为命名关键字参数,限制传入的关键字参数;
    可替换为一个可变参数

    解包裹

    *和**,也可以在调用的时候使用,即解包裹(unpacking), 下面为例:

    def func(a,b,c):
        print a,b,cargs = (1,3,4)func(*args)
    

    在这个例子中,所谓的解包裹,就是在传递tuple时,让tuple的每一个元素对应一个位置参数。在调用func时使用*,是为了提醒Python:我想要把args拆成分散的三个元素,分别传递给a,b,c。(设想一下在调用func时,args前面没有*会是什么后果?)

    相应的,也存在对词典的解包裹,使用相同的func定义,然后:

    dict = {'a':1,'b':2,'c':3}
    func(**dict)
    

    在传递词典dict时,让词典的每个键值对作为一个关键字传递给func。

    参数定义的顺序:必选,默认,可变,命名关键字,关键字

    递归函数

    ​ 函数调用是通过栈(stack)这种数据结构实现的

    ​ 调用一次,栈加一层栈帧

    ​ 函数返回,栈减一层栈帧

    ​ 递归次数过多,有可能栈溢出,可以用尾递归方法(尚未理解尾递归)

    for循环遍历list/tuple 相当于迭代函数

    判断是否为可迭代对象:

    • from collections import Iterable
    • isinstance('abc',Iterable)

    可以用enumerate(list) 将list转换为索引元素

    for i,value in enumerate([1,2,3]):
    	print(i,value)
    

    ​ 输出结果:0 1 1 2 2 3

    特殊方法

    _init_()

    _init_()是一个特殊方法(special method)。Python有一些特殊方法。Python会特殊的对待它们。特殊方法的特点是名字前后有两个下划线。

    如果你在类中定义了_init_()这个方法,创建对象时,Python会自动调用这个方法。这个过程也叫初始化。

    class happyBird(Bird):
        def __init__(self,more_words):
            print 'We are happy birds.',more_words
    
    summer = happyBird('Happy,Happy!')
    

    dir()&help()

    两个内置函数,dir()和help()

    dir()用来查询一个类或者对象所有属性。你可以尝试一下

    >>>print dir(list)

    help()用来查询的说明文档。你可以尝试一下

    >>>print help(list)

    (list是Python内置的一个类,对应于我们之前讲解过的列表)

    类和对象

    Python使用类(class)和对象(object),进行面向对象(object-oriented programming,简称OOP)的编程。

    面向对象的最主要目的是提高程序的重复使用性。

    class Bird(object):
        have_feather = True
        way_of_reproduction = 'egg'
        def move(self, dx, dy):
            position = [0,0]
            position[0] = position[0] + dx
            position[1] = position[1] + dy
            return position
    
    summer = Bird()
    print 'after move:',summer.move(5,8)
    
    class Chicken(Bird):
        way_of_move = 'walk'
        possible_in_KFC = True
    
    class Oriole(Bird):
        way_of_move = 'fly'
        possible_in_KFC = False
    
    summer = Chicken()
    print summer.have_feather
    print summer.move(5,8)
    

    在类定义时,括号里为了Bird。这说明,Chicken是属于鸟类(Bird)的一个子类,即Chicken继承自Bird。自然而然,Bird就是Chicken的父类。Chicken将享有Bird的所有属性

    class Bird(object):
        have_feather = True
        way_of_reproduction  = 'egg'
    

    括号中的object,当括号中为object时,说明这个类没有父类(到头了)

    文件读写

    Python具有基本的文本文件读写功能。Python的标准库提供有更丰富的读写功能。

    文本文件的读写主要通过open()所构建的文件对象来实现。

    f = open(文件名,模式)
    

    最常用的模式有:

    "r" # 只读

    "w" # 写入

    >>>f = open("test.txt","r")  
    

    读取:

    content = f.read(N)          # 读取N bytes的数据
    content = f.readline()       # 读取一行
    content = f.readlines()      # 读取所有行,储存在列表中,每个元素是一行。  
    

    写入:

    f.write('I like apple')      # 将'I like apple'写入文件  
    

    关闭文件:

    f.close()  
    

    模块

    引入模块后,可以通过模块.对象的方式来调用引入模块中的某个对象。

    Python中还有其它的引入方式,

    import a as b             # 引入模块a,并将模块a重命名为b
    from a import function1   # 从模块a中引入function1对象。调用a中对象时,我们不用再说明模块,即直接使用function1,而不是a.function1。
    from a import *           # 从模块a中引入所有对象。调用a中对象时,我们不用再说明模块,即直接使用对象,而不是a.对象。
    

    搜索路径

    Python会在以下路径中搜索它想要寻找的模块:

    1. 程序所在的文件夹
    2. 标准库的安装路径
    3. 操作系统环境变量PYTHONPATH所包含的路径

    如果你有自定义的模块,或者下载的模块,可以根据情况放在相应的路径,以便Python可以找到。

    模块包

    可以将功能相似的模块放在同一个文件夹(比如说this_dir)中,构成一个模块包。通过

    import this_dir.module
    

    引入this_dir文件夹中的module模块。

    该文件夹中必须包含一个__init__.py的文件,提醒Python,该文件夹为一个模块包。_init_.py可以是一个空文件。

    异常处理

    处理异常

    在项目开发中,异常处理是不可或缺的。异常处理帮助人们debug,通过更加丰富的信息,让人们更容易找到bug的所在。异常处理还可以提高程序的容错性。

    我们之前在讲循环对象的时候,曾提到一个StopIteration的异常,该异常是在循环对象穷尽所有元素时的报错。

    我们以它为例,来说明基本的异常处理。

    一个包含异常的程序:

    re = iter(range(5))
    
    for i in range(100):
        print re.next()
    
    print 'HaHaHaHa'
    

    首先,我们定义了一个循环对象re,该循环对象将进行5次循环,每次使用序列的一个元素。

    在随后的for循环中,我们手工调用next()函数。当循环进行到第6次的时候,re.next()不会再返回元素,而是抛出(raise)StopIteration的异常。整个程序将会中断。

    我们可以修改以上异常程序,直到完美的没有bug。但另一方面,如果我们在写程序的时候,知道这里可能犯错以及可能的犯错类型,我们可以针对该异常类型定义好”应急预案“。

    re = iter(range(5))
    
    try:
        for i in range(100):
            print re.next()
    except StopIteration:
        print 'here is end ',i
    
    print 'HaHaHaHa'
    

    在try程序段中,我们放入容易犯错的部分。我们可以跟上except,来说明如果在try部分的语句发生StopIteration时,程序该做的事情。如果没有发生异常,则except部分被跳过。

    随后,程序将继续运行,而不是彻底中断。

    完整的语法结构如下:

    try:
        ...
    except exception1:
        ...
    except exception2:    ...except:
        ...
    else:
        ...
    finally:
        ...
    

    如果try中有异常发生时,将执行异常的归属,执行except。异常层层比较,看是否是exception1, exception2...,直到找到其归属,执行相应的except中的语句。如果except后面没有任何参数,那么表示所有的exception都交给这段程序处理。比如:

    try:
        print(a*2)
    except TypeError:
        print("TypeError")
    except:
        print("Not Type Error & Error noted")
    

    由于a没有定义,所以是NameError。异常最终被except:部分的程序捕捉。

    如果无法将异常交给合适的对象,异常将继续向上层抛出,直到被捕捉或者造成主程序报错。比如下面的程序

    def test_func():
        try:
            m = 1/0
        except NameError:
            print("Catch NameError in the sub-function")
    
    try:
        test_func()
    except ZeroDivisionError:
        print("Catch error in the main program")
    

    子程序的try...except...结构无法处理相应的除以0的错误,所以错误被抛给上层的主程序。

    如果try中没有异常,那么except部分将跳过,执行else中的语句。

    finally是无论是否有异常,最后都要做的一些事情。

    流程如下,

    try->异常->except->finally

    try->无异常->else->finally

    抛出异常

    我们也可以自己写一个抛出异常的例子:

    print 'Lalala'
    raise StopIteration
    print 'Hahaha'
    

    这个例子不具备任何实际意义。只是为了说明raise语句的作用。

    StopIteration是一个类。抛出异常时,会自动有一个中间环节,就是生成StopIteration的一个对象。Python实际上抛出的,是这个对象。当然,也可以自行生成对象:

    raise StopIteration()
    
  • 相关阅读:
    从源代码解释Android事件分发机制
    怎样让oracle实验本在不做实验时性能提升——win7下举例
    could only be replicated to 0 nodes, instead of 1
    虚拟机和主机ping不通解决的方法
    ZOJ3623:Battle Ships(全然背包)
    Android 网络编程之---HttpClient 与 HttpURLConnection 共用cookie
    注冊成为Windows Phone开发人员而且解锁Windows Phone 8.1手机
    sharding-method首页、文档和下载
    rootsongjc/kubernetes-handbook: Kubernetes中文指南/实践手册
    如何基于K8S打造轻量级PaaS平台
  • 原文地址:https://www.cnblogs.com/fengzzi/p/10042824.html
Copyright © 2011-2022 走看看