复习资料Python

复习资料Python

在Python交互式模式下,可以直接输入代码,然后执行,并立刻得到结果
在命令行模式下,可以直接运行.py文件

一、输入和输出:
1、输出:print()在括号中加上字符串,用单引号/双引号括起来;
     多个字符串用逗号隔开,逗号打印出来会是有一个空格
     python2.0可省略(),python3.0不能省略()
2、输入:变量名 = input()  
     注:input()函数的返回类型为str
3、区分大小写


二、数据类型和变量
1、整数:没有大小限制
2、浮点数
3、字符串:以单引号或双引号括起来的任意文本
4、转义字符:\
    \n:空格
    \t:制表符
    \\:表示\
5、r'字符串':默认不转义
6、布尔值
7、空值:用None表示
8、变量:变量名必须是大小写英文、数字和_的组合,且不能用数字开头
9、常量:通常用全部大写的变量名表示
除法:
1)'/': 结果为浮点数
2)'//': 结果为整数

10、List:是一种有序的集合,可以随时添加和删除其中的元素,可变!
例:>>> classmates = ['Michael', 'Bob', 'Tracy']
    >>> classmates
    ['Michael', 'Bob', 'Tracy']
1) len()函数获取list元素的个数
2) 索引从0开始
3) 最后一个索引是: len(**)-1 或 -1
4) 往list中追加元素到末尾: **.append('**')
5) 把元素插入指定位置: **.insert('**')
6) 删除list末尾的元素: pop()
7) 删除指定位置的元素: pop(*)(*:指索引位置)
8) 把某个元素替换成别的元素,直接赋值给对应的索引位置: **[*]='**'
9) list里面的元素的数据类型可以不同
10) list元素也可以是另一个list
例:>>> s = ['python', 'java', ['asp', 'php'], 'scheme']
    >>> len(s)
    4

    >>> p = ['asp', 'php']
    >>> s = ['python', 'java', p, 'scheme']
    
11、tuple:初始化后不能修改,不可变!
例:>>> t = (1, 2)
    >>> t
    (1, 2)
注:定义只有一个元素的tuple: 
    >>> t = (1,)
    >>> t
    (1,)

12、dict使用(key-value)存储
例:>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
    >>> d['Michael']
    95
1) 判断key是否存在
a、通过in判断
例:>>> 'Thomas' in d
    False
b、通过dict提供的get()方法: 
如果key不存在,返回None(Python的交互环境不显示结果)或者指定的value
例:>>> d.get('Thomas')
    >>> d.get('Thomas', -1)
    -1
2) 删除key: pop(key)
例:>>> d.pop('Bob')
    75
    >>> d
    {'Michael': 95, 'Tracy': 85}
注:key是不可变对象(字符串、整数是不可变的)---哈希算法

13、set:一组key的集合,不存储value。key不能重复!
(无序和无重复元素的集合,不可变对象)
创建一个set,需要提供一个list作为输入集合:
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}
1) add(key): 添加元素到set中,可以重复添加,但没有效果
2) remove(key): 删除元素
例:>>> a = 'abc'
    >>> b = a.replace('a', 'A')
    >>> b
    'Abc'
    >>> a
    'abc'
a是变量,'abc'是字符串对象
    
    
三、Python的字符串类型str
1、单个字符:
    ord()函数获取字符的整数表示
    chr()函数把编码转换为对应的字符
    '\u**': 十六进制
2、bytes类型的数据:带b前缀的单引号或双引号表示(只占一个字节)
     encode()方法可以编码为指定的bytes
    decode()方法可以把bytes变为str 
    注: errors = 'ignore'忽略错误的字节
    在bytes中,无法显示为ASCII字符的字节,用\x##显示
例:>>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
    '中'
3、计算字符/字节个数:len()
4、格式化字符串:%
    %d  整数
    %f  浮点数
    %s  字符串
    %x  十六进制整数
    %%  %
例:'Age: %d. Gender: %s. 开心就好: %s %%' % (25, True, 7)
    'Age: 25. Gender: True. 开心就好: 7 %'
format()格式化字符串
例:'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
    'Hello, 小明, 成绩提升了 17.1%'
    
    
四、条件判断
1、if条件判断:
if <条件判断1>:
    <执行语句1>
elif <条件判断2>:
    <执行语句2>
elif <条件判断3>:
    <执行语句3>
else:
    <执行语句4>

2、强制转换:
例:s = input('birth: ')      #输入的s为str类型
    birth = int(s)      #int()将s转换为int类型
    if birth < 2000:
        print('00前')
    else:
        print('00后')

        
五、循环
1、for...in循环:依次把list或tuple中的每个元素迭代出来
2、range(n)函数:生成一个整数序列,从0开始小于n的整数
3、while循环:只要条件满足,就不断循环,条件不满足时退出循环
4、break:提前退出循环
5、continue:跳过当前循环,直接开始下次循环


六、函数
可以把函数名赋给一个变量,相当于给这个函数起了一个"别名"
例:>>> a = abs # 变量a指向abs函数
    >>> a(-1) # 所以也可以通过a调用abs函数
    1
1、定义函数:
def 函数名(参数):
    函数体
    return 参数
2、函数的使用
1) 在Python交互环境中定义函数,会出现...提示。函数定义结束后按两次回车重新回到>>>提示符下
例:>>>def my_abs(x):
    ...    if x > 0:
    ...       return x 
    ...    else:
    ...       return -x
    ...
    >>>my_abs(-99)
    99
2) 把my_abs()函数定义保存为abstest.py文件
用from abstest import my_abs导入my_abs()函数,abstest是文件名(不含.py扩展名)
3、定义空函数:用pass语句
例:def nop():
        pass  #pass相当于占位符,可以用在其他语句中
4、函数参数
1) 位置参数(必选参数)
例:def power(x, n):      #定义一个计算x^n的函数
        s = 1
        while n > 0:
            n = n - 1
            s = s * x
        return s 
2) 默认参数: 默认参数必须指向不变对象!
例:def power(x, n=2):      #定义一个计算x^2的函数
        s = 1
        while n > 0:
            n = n - 1
            s = s * x
        return s
注:
设置默认参数时:
一是必选参数在前,默认参数在后,否则Python的解释器会报错
二是如何设置默认参数。
当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
3) 可变参数: 可变参数允许你传入0个或任意个参数
例:def calc(*numbers):
        sum = 0
        for n in numbers:
            sum = sum + n * n
        return sum
注:
a、调用该函数时(可变参数),可以传入任意个参数,包括0个参数
b、Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去
例:>>> nums = [1, 2, 3]
    >>> calc(*nums)
    14
4) 关键字参数: 关键字参数允许你传入0个或任意个含参数名的参数
例:def person(name, age, **kw):
       print('name:', name, 'age:', age, 'other:', kw)
调用函数时,可以只传入必选参数(位置参数),可以传入任意个数的关键字参数: 
>>> 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'}
5) 命名关键字参数: 必须传入参数名!
特殊分隔符"*,",后面的参数被视为命名关键字参数
例:def person(name, age, *, city, job):
        print(name, age, city, job)
注:如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要特殊分隔符。
例:def person(name, age, *args, city, job):
        print(name, age, args, city, job)
注:命名关键字参数可以有缺省值
例:def person(name, age, *, city='Beijing', job):
        print(name, age, city, job)
调用:>>> person('Jack', 24, job='Engineer')
      Jack 24 Beijing Engineer
可变参数和关键字参数的语法:
*args是可变参数,args接收的是一个tuple=(a,b,c)或list
**kw是关键字参数,kw接收的是一个dict={key:value,...}
以及调用函数时如何传入可变参数和关键字参数的语法:
可变参数既可以直接传入:
func(1, 2, 3),又可以先组装list或tuple,再通过*args传入: func(*(1, 2, 3));
关键字参数既可以直接传入:
func(a=1, b=2),又可以先组装dict,再通过**kw传入: 
func(**{'a': 1, 'b': 2})。


七、递归函数
1、尾递归:在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。
2、任何递归函数都存在栈溢出的问题。


八、切片(Slice)操作符
例:>>> L[0:3]   #从索引0开始取,直到索引3为止,但不包括索引3。如果第一个索引是0,还可以省略。
    ['Michael', 'Sarah', 'Tracy']
    前10个数,每两个取一个: 
    >>> L[:10:2]
    [0, 2, 4, 6, 8]
    所有数,每5个取一个:
    >>> L[::5]
    [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
注:可以对List、tuple、字符串进行切片
例:1、 >>> (0, 1, 2, 3, 4, 5)[:3]
        (0, 1, 2)
    2、 >>> 'ABCDEFG'[:3]
        'ABC'
        >>> 'ABCDEFG'[::2]
        'ACEG'
        
        
九、迭代:通过for ... in来完成的
1、dict迭代的默认是key;
如果要迭代value,可以用for value in d.values();
如果要同时迭代key和value,可以用for k, v in d.items()。
2、字符串也是可迭代对象
3、如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:
>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整数是否可迭代
False
4、Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:
>>> for i, value in enumerate(['A', 'B', 'C']):
...     print(i, value)
...
0 A
1 B
2 C
5、同时引用了两个变量:
>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
...     print(x, y)
...
1 1
2 4
3 9


十、列表生成式:用来创建list
例:
1、要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11))
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2、要生成[1x1, 2x2, 3x3, ..., 10x10]
方法一:循环
>>> L = []
>>> for x in range(1, 11):
...    L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
方法二:列表生成式
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
a、for循环后面还可以加上if判断
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
b、两层循环,可以生成全排列
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
3、isinstance函数可以判断一个变量是不是字符串
>>> x = 'abc'
>>> y = 123
>>> isinstance(x, str)
True
>>> isinstance(y, str)
False


十一、生成器generator:一边循环一边计算的机制
1、创建generator
方法一:只要把一个列表生成式的[]改成()
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
a、打印generator的值
如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值,
但最后一个元素时,会抛出StopIteration的错误。
>>> next(g)
0
......
b、for循环迭代
>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)
... 
方法二:如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
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>
小结:
1、可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list=[]、tuple=()、dict={key:value}、set={key1,key2,...}、str='***'等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
2、可以使用isinstance()判断一个对象是否是Iterable对象:
>>> from collections import Iterable
>>> isinstance([], Iterable)  #list
True
>>> isinstance((), Iterable)  #tuple
True
>>> isinstance({}, Iterable)  #dict
True
>>> isinstance('abc', Iterable)  #str
True
>>> isinstance((x for x in range(10)), Iterable)  #列表生成式
True
>>> isinstance(100, Iterable)  #整数
False


十二、迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
1、可以使用isinstance()判断一个对象是否是Iterator对象
2、生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
3、把list、dict、str等Iterable变成Iterator可以使用iter()函数:
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True


十三、函数式编程
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的。
特点:允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
十六、高阶函数
1、变量可以指向函数:x = abs()
2、函数名也是变量
3、传入函数:一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
4、map / reduce
4.1 map()函数接收两个参数,一个是函数,一个是Iterable。map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
例:有一个函数f(x)=x2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现如下
>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
    [1, 4, 9, 16, 25, 36, 49, 64, 81]
4.2 reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
5、filter()函数用于过滤序列:filter()接收一个函数和一个序列,
filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
6、sorted排序算法
6.1 可以接收一个key函数来实现自定义的排序
例:按绝对值大小排序
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
6.2 默认情况下,对字符串排序,是按照ASCII的大小比较的
>>> sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']
a、忽略大小写的排序
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
['about', 'bob', 'Credit', 'Zoo']
b、进行反向排序
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']


十四、返回函数
1、函数作为返回值
2、闭包:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
小结:
一个函数可以返回一个计算结果,也可以返回一个函数。
返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。
十八、匿名函数lambda *: ***  (冒号前面的*表示函数参数。)
1、只能有一个表达式,不用写return,返回值就是该表达式的结果。
2、匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
>>> f = lambda x: x * x
>>> f
<function <lambda> at 0x101c6ef28>
>>> f(5)
25
3、可以把匿名函数作为返回值返回
def build(x, y):
    return lambda: x * x + y * y
    
    
十五、装饰器
1、函数对象有一个__name__属性,可以拿到函数的名字
>>> now.__name__
'now'
>>> f.__name__
'now'
2、装饰器(Decorator):在代码运行期间动态增加功能的方式


十六、偏函数
functools.partial用来创建一个偏函数的,不需要我们自己定义int2(),可以直接创建一个新的函数int2
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
1、functools.partial作用:
把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
2、创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数
3、当传入:max2 = functools.partial(max, 10)
实际上会把10作为*args的一部分自动加到左边,也就是:
max2(5, 6, 7)
相当于:
args = (10, 5, 6, 7)
max(*args)


十七、模块
1、作用域:
正常的函数和变量名是公开的(public),可以被直接引用,比如: abc,x123,PI等;
类似_xxx和__xxx这样的函数或变量就是非公开的(private),不应该被直接引用,比如: _abc,__abc等;


十八、面向对象编程
1、类和实例
定义类:是通过class关键字
class Student(object):    #类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的
    pass
创建实例:是通过类名+()实现的
>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>    #0x10a67a590是内存地址
>>> Student
<class '__main__.Student'>
特殊方法:"__init__"
a、__init__方法的第一个参数永远是self,表示创建的实例本身
b、有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传
2、访问限制
a、在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问
让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
b、在Python中,变量名为__xxx__的,以双下划线开头,且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量
3、继承和多态
a、继承的好处是 子类获得了父类的全部功能
b、多态:当子类和父类都存在相同的run()方法时,子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()——多态
4、获取对象信息
a、判断对象类型,使用type()函数
b、如果一个变量指向函数或者类,用type()判断
c、type()函数返回类型: 对应的Class类型
d、判断一个对象是否是函数,用types模块中定义的常量
e、判断class的类型,可以使用isinstance()函数
f、能用type()判断的基本类型也可以用isinstance()判断
g、判断一个变量是否是某些类型中的一种
i、getattr()、setattr()以及hasattr(),可以直接操作一个对象的状态
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True
h、如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list
>>> hasattr(obj, 'x')       # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y')       # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19)   # 设置一个属性'y'
>>> hasattr(obj, 'y')       # 有属性'y'吗?
True
>>> getattr(obj, 'y')       # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19
j、getattr()、setattr()以及hasattr(),可以获得对象的方法
5、实例属性和类属性
a、给实例绑定属性的方法是通过实例变量,或者通过self变量:
class Student(object):
    def __init__(self, name):
        self.name = name

s = Student('Bob')
s.score = 90
b、类属性:类的所有实例都可以访问到
class Student(object):
    name = 'Student'
>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student


十九、面向对象高级编程
1、使用__slots__
在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性
__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
2、@property装饰器就是负责把一个方法变成属性进行调用的
3、定制类
a、__str__  : 返回用户看到的字符串
>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...     def __str__(self):
...         return 'Student object (name: %s)' % self.name
...
>>> print(Student('Michael'))
Student object (name: Michael)
b、__repr__()返回程序开发者看到的字符串(__repr__()是为调试服务的)
>>>class Student(object):
...     def __init__(self, name):
...         self.name = name
...     def __str__(self):
...         return 'Student object (name=%s)' % self.name
...     __repr__ = __str__
...
>>> s = Student('zhong')
>>> s
Student object (name=zhong)
c、__iter__ : 返回一个迭代对象
class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1                           # 初始化两个计数器a,b

    def __iter__(self):
        return self                                     # 实例本身就是迭代对象,故返回自己

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b        # 计算下一个值
        if self.a > 100000:                             # 退出循环的条件
            raise StopIteration()
        return self.a                                   # 返回下一个值
>>> for n in Fib():
...     print(n)
...
1
1
2
3
5
...
46368
75025
d、__getitem__()方法,像list那样按照下标取出元素
__setitem__()方法,把对象视作list或dict来对集合赋值
__delitem__()方法,用于删除某个元素
e、__getattr__  : 只有在没有找到属性的情况下,才调用__getattr__
f、__call__ : 任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用
class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)

调用方式如下:
>>> s = Student('Michael')
>>> s()                     # self参数不要传入
My name is Michael.
g、通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。
4、枚举类:默认从1开始计数
from enum import Enum
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
@unique装饰器可以帮助我们检查保证没有重复值
5、元类
type()函数可以查看一个类型或变量的类型
type()函数可以创建出新的类型
>>> def fn(self, name='world'):                      # 先定义函数
...     print('Hello, %s.' % name)
...
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class '__main__.Hello'>

type()函数依次传入3个参数:
1)class的名称;
2)继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
3)class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。

metaclass: 先定义metaclass,就可以创建类,最后创建实例. metaclass的类名总是以Metaclass结尾
class ListMetaclass(type):                       # metaclass是类的模板,所以必须从'type'类型派生
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)
使用ListMetaclass来定制类
class MyList(list, metaclass=ListMetaclass):
    pass
__new__()方法接收到的参数依次是:
1)当前准备创建的类的对象;
2)类的名字;
3)类继承的父类集合;
4)类的方法集合。


二十、错误处理
try...except...finally...的错误处理机制:
1)如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块,执行完except后,如果有finally语句块,则一定会执行执行finally语句块(可以没有finally语句)
2)可以有多个except来捕获不同类型的错误 
3)记录错误: logging模块可以把错误记录到日志文件里
# err_logging.py
import logging
def foo(s):
    return 10 / int(s)
def bar(s):
    return foo(s) * 2
def main():
    try:
        bar('0')
    except Exception as e:
        logging.exception(e)             #logging

main()
print('END')   
同样是出错,但程序打印完错误信息后会继续执行,并正常退出:
$ python3 err_logging.py
ERROR:root:division by zero
Traceback (most recent call last):
  File "err_logging.py", line 13, in main
    bar('0')
  File "err_logging.py", line 9, in bar
    return foo(s) * 2
  File "err_logging.py", line 6, in foo
    return 10 / int(s)
ZeroDivisionError: division by zero
END
4) 抛出错误: raise语句(raise语句如果不带参数,就会把当前错误原样抛出。)
# err_raise.py
class FooError(ValueError):
    pass
def foo(s):
    n = int(s)
    if n==0:
        raise FooError('invalid value: %s' % s)
    return 10 / n
foo('0')

执行,可以最后跟踪到我们自己定义的错误:
$ python3 err_raise.py 
Traceback (most recent call last):
  File "err_throw.py", line 11, in <module>
    foo('0')
  File "err_throw.py", line 8, in foo
    raise FooError('invalid value: %s' % s)
__main__.FooError: invalid value: 0


二十一、调试
1、print()
2、断言:assert  可以用-O(大写的o) 参数来关闭assert
3、logging:logging不会抛出错误,而且可以输出到文件
import logging
logging.basicConfig(level=logging.INFO)   # 有 debug,info,warning,error等几个级别
s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)

$ python err.py
INFO:root:n = 0
Traceback (most recent call last):
  File "err.py", line 8, in <module>
    print(10 / n)
ZeroDivisionError: division by zero
4、pdb:让程序以单步方式运行,可以随时查看运行状态。
以参数-m pdb启动后,输入命令 l 来查看代码
输入命令 n 可以单步执行代码
输入命令 p 变量名 来查看变量
输入命令 q 结束调试,退出程序
5、pdb.set_trace():这个方法也是用pdb,但是不需要单步执行,只需要import pdb,在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点
6、IDE


二十二、单元测试
1、单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作
2、编写单元测试,我们需要引入Python自带的unittest模块 import unittest
3、编写单元测试时,我们需要编写一个测试类,从unittest.TestCase继承
4、以test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行
5、常用断言
1) assertEqual()  例:self.assertEqual(abs(-1), 1) # 断言函数返回的结果与1相等
2) assertRaises()  例:with self.assertRaises(KeyError):
                           value = d['empty']
6、运行单元测试
1) 在mydict_test.py的最后加上两行代码:
if __name__ == '__main__':
    unittest.main()
2) 在命令行通过参数-m unittest直接运行单元测试:
$ python -m unittest mydict_test
7、setUp与tearDown
在单元测试中编写两个特殊的setUp()和tearDown()方法。这两个方法会分别在每调用一个测试方法的前后分别被执行。
例:测试需要启动一个数据库,这时,就可以在setUp()方法中连接数据库,在tearDown()方法中关闭数据库
class TestDict(unittest.TestCase):
    def setUp(self):
        print('setUp...')
    def tearDown(self):
        print('tearDown...')
        
        
二十三、IO编程
1、读取 utf-8 编码的文本文件:用'r'模式打开文件
以读文件的模式打开一个文件对象: open()
读取文件的全部内容: read()  
read(size)方法,每次最多读取size个字节的内容
readlines()一次读取所有内容并按行返回list
readline()可以每次读取一行内容
关闭文件: close()
with语句来自动帮我们调用close()方法:(与try ... finally一致)
with open('/path/to/file', 'r') as f:
    print(f.read())
2、读取二进制文件:用'rb'模式打开文件
>>> f = open('/Users/michael/test.jpg', 'rb')
>>> f.read()
b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节
3、读取非UTF-8编码的文本文件:给open()函数传入encoding参数
>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
>>> f.read()
'测试'
4、写文件: 调用open()函数时,传入标识符'w'或者'wb'表示写文本文件或写二进制文件
>>> f = open('/Users/michael/test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()

with open('/Users/michael/test.txt', 'w') as f:
    f.write('Hello, world!')
    
    
二十四、StringIO和BytesIO
1、StringIO:在内存中读写str
#把str写入StringIO
>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue())   #getvalue()方法用于获得写入后的str
hello world!
#读取StringIO
>>> from io import StringIO
>>> f = StringIO('Hello!\nHi!\nGoodbye!')
>>> while True:
...     s = f.readline()
...     if s == '':
...         break
...     print(s.strip())
...
Hello!
Hi!
Goodbye!
2、BytesIO:在内存中读写bytes
#写入bytes
>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))   #写入的不是str,而是经过UTF-8编码的bytes
6
>>> print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'
#读取bytes
>>> from io import BytesIO
>>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
>>> f.read()
b'\xe4\xb8\xad\xe6\x96\x87'


二十五、操作文件和目录:os模块
1、环境变量:os.environ
   获取某个环境变量的值: os.environ.get('key')
2、操作文件和目录:os、os.path
# 查看当前目录的绝对路径:
>>> os.path.abspath('.')
'/Users/michael'
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
>>> os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
# 然后创建一个目录:
>>> os.mkdir('/Users/michael/testdir')
# 删掉一个目录:
>>> os.rmdir('/Users/michael/testdir')
两个路径合成用: os.path.join()
拆分路径: os.path.split()
文件扩展名: os.path.splitext()
注:合并、拆分路径的函数并不要求目录和文件要真实存在,它们只对字符串进行操作
# 对文件重命名:
>>> os.rename('test.txt', 'test.py')
# 删掉文件:
>>> os.remove('test.py')
复制文件: copyfile()
过滤文件: 
>>> [x for x in os.listdir('.') if os.path.isdir(x)]
['.lein', '.local', '.m2', '.npm', '.ssh', '.Trash', '.vim', 'Applications', 'Desktop', ...]
列出所有的.py文件:
>>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
['apis.py', 'config.py', 'models.py', 'pymonitor.py', 'test_db.py', 'urls.py', 'wsgiapp.py']


二十六、序列化
序列化(pickling):把变量从内存中变成可存储或传输的过程称之为序列化
反序列化(unpickling):把变量内容从序列化的对象重新读到内存里称之为反序列化
pickle模块: 
1: 把一个对象序列化并写入文件
>>> import pickle
>>> d = dict(name='Bob', age=20, score=88)
>>> pickle.dumps(d)           #pickle.dumps()方法把任意对象序列化成一个bytes
b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'
2: 用pickle.dump()直接把对象序列化后写入一个file-like Object
>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close()
3: 反序列化  pickle.loads()反序列出对象  或者  用pickle.load()方法从一个file-like Object中直接反序列化出对象
>>> f = open('dump.txt', 'rb')
>>> d = pickle.load(f)
>>> f.close()
>>> d
{'age': 20, 'score': 88, 'name': 'Bob'}
JSON表示的对象就是标准的JavaScript语言的对象


二十七、进程和线程
1、一个进程至少有一个线程
2、Unix/Linux操作系统提供了一个fork()系统调用,普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次。
操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
子进程永远返回0,而父进程返回子进程的ID。
子进程只需要调用getppid()就可以拿到父进程的ID。
Python的os模块封装了常见的系统调用,其中就包括fork,可以在Python程序中轻松创建子进程:
import os
print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
pid = os.fork()
if pid == 0:
    print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
else:
    print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
运行结果如下:
Process (876) start...
I (876) just created a child process (877).
I am child process (877) and my parent is 876.
3、multiprocessing模块提供了一个Process类来代表一个进程对象(multiprocessing模块就是跨平台版本的多进程模块)
start()方法启动进程
join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步
4、Pool进程池
对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。
5、子进程
控制子进程的输入和输出: subprocess模块
子进程输入: communicate()方法
6、进程间通信
Python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。
7、线程是操作系统直接支持的执行单元
Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块。
任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程
current_thread()函数,它永远返回当前线程的实例

二十八、正则表达式
1、精确匹配
\d:可以匹配一个数字
\w:可以匹配一个字母或数字
. :可以匹配任意字符
\s:可以匹配一个空格(也包括Tab等空白符)
2、匹配变长的字符
* :表示任意个字符(包括0个)
+ :表示至少一个字符
? :表示0个或1个字符
{n}:表示n个字符
{n,m}:表示n-m个字符
3、进阶"[]"
[0-9a-zA-Z\_]:可以匹配一个数字、字母或者下划线;
[0-9a-zA-Z\_]+:可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','Py3000'等等
[a-zA-Z\_][0-9a-zA-Z\_]*:可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串
[a-zA-Z\_][0-9a-zA-Z\_]{0, 19}:更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
A|B:可以匹配A或B,所以(P|p)ython可以匹配'Python'或者'python'。
^:表示行的开头,^\d表示必须以数字开头。
$:表示行的结束,\d$表示必须以数字结束。


 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值