python知识杂记

1.字符集问题

windows下面尽量用#coding:gbk
Linux下面尽量用#coding:utf-8

2.什么是序列

序列是指有序和无序的数据结构
包括:字符串,列表,元组,字典,集合

3.编程规范

命名规范:
类定义用驼峰式 TestCase
其他用小写字符加下划线 test_case
常量全部用大写

注释的两种方式:
单行注释用#
类和对象的docstring用”“” “”“

import顺序:
标准库,第三方库,自定义库
不同类型的库中间空一行

空行:
类与函数之间空两行
函数与函数之间空一行
函数中,逻辑代码段之间空一行

4.库、包、模块的概念

库:python的一个项目
包:包含__init__.py文件的文件夹
模块:以.py为结尾的文件

py2中,包里面必须有__init__.py文件,否则解释器无法识别这个包,也就是包下面的.py文件,外部无法调用。

5.import导入模块搜索顺序

import导入的时候,针对模块名,首先搜索当前目录,然后查找标准库,最后查找第三方库。

6.__init__.py文件的作用

python中__init__.py文件的作用:Python中每个模块的包下面都有一个__init__.py文件,有了这个文件,我们才能导入这个包下面的module。

7.如何设置环境变量

windows环境:我的电脑-属性-高级系统设置-高级-环境变量,修改PATH,添加;$PYTHON_INSTALL_DIR(自己改)
Linux环境:export PATH=…….

8.第三方库安装位置 $PYTHON_INSTALL_DIR\Lib\site-packages

9.查看内建函数:dir(builtins)

10.type和isinstance()函数

Python在定义变量的时候不用指明具体的的类型,解释器会在运行的时候会自动检查变量的类型,并根据需要进行隐式的类型转化。
因为Python是动态语言,所以一般情况下是不推荐进行类型转化的。
比如”+”操作时,如果加号两边是数据就进行加法操作,如果两边是字符串就进行字符串连接操作,如果两边是列表就进行合并操作,甚至可以进行复数的运算。解释器会在运行时根据两边的变量的类型调用不同的内部方法。当加号两边的变量类型不一样的时候,又不能进行类型转化,就会抛出TypeError的异常。

但是在实际的开发中,为了提高代码的健壮性,我们还是需要进行类型检查的。而进行类型检查首先想到的就是用type(),比如使用type判断一个int类型。

对于内建的基本类型来说,使用tpye来检查是没有问题的。
可是当应用到其他场合的时候,type就显得不可靠了。比如:

class A():
    pass

class B():
    pass

a = A()
b = B()

print(type(a) is type(b))
代码的输出结果: True

此例中type的判断显然是有问题的。
这个时候我们就需要使用isinstance来进行类型检查。

isinstance(object, classinfo)

object表示实例,classinfo可以是直接或间接类名、基本类型或者有它们组成的元组。

>>> isinstance(2, float)
False
>>> isinstance('a', (str, unicode))
True
>>> isinstance((2, 3), (str, list, tuple))
True

可以参考此博文:https://www.jianshu.com/p/7ef549503c93

11.字典这个序列,以key作为序列中的每一项

>>> list({1:2,3:4})
[1, 3]

12.函数返回值的问题

def test():
    print('lijingkuan')

print(test())

返回值为

lijingkuan
None

为什么呢?
原因是:
字符串’lijingkuan’是test()函数打印的,而None是print()函数打印的,
None是test()函数的返回值。

修改一下

def test():
    print('lijingkuan')
    return 123

print(test())

则输出结果变为

lijingkuan
123

如果不想打印那个None,就直接执行test()就行了,不要print。

13.raw_input函数

接受用户输入,返回字符串
— 重要,返回的是字符串,不是数字或者其他类型

14.list可以用来存储任何类型的对象,不强制要求类型相同,是有序的。

15.type和isinstance的区别???

16.list的高阶特性
增删改查、排序

增:
append,extend,insert
append和extend的区别?
append是往列表中添加一个值,extend是增加一个序列。
列表a+b会生成一个新的列表,原来的a和b不会变化。
一般写作 c=a+b
a.extend(b)会修改列表a,与a+b有区别。
a.append(b),会将b当成一个值去对待,而不是当成一个列表。
例如:

a=[1,2,3],b=[4,5,6]
a.extend(b) = [1,2,3,4,5,6]
a.append(b)=[1,2,3,[4,5,6]]

因此:
append往列表中添加元素,该元素可以是任何形式的数据结构或对象,添加的对象作为列表中的一个元素,放到最后一位。
extend用于在列表末尾一次性追加另一个序列中的多个值,不是把对象整个添加,而是拿出每一项来添加。

>>> a=[1,2,3]
>>> b="abc"       
>>> a.extend(b)
>>> a
[1, 2, 3, 'a', 'b', 'c'] --字符串也是序列
>>> c={'f':1,7:9}
>>> a.extend(c)
>>> a
[1, 2, 3, 'a', 'b', 'c', 'f', 7]  
-- 字典也是序列
-- 当字典作为一个序列的时候,那么序列的每一项指的是字典的key,不包括value。

insert:往列表中添加元素,两个参数,第一个参数表示insert的位置,第二个参数表示insert的参数的value。

删:
remove,pop

>>> a
[1, 2, 3, 'a', 'b', 'c', 'f', 7]
>>>
>>>
>>> a.remove(2)
>>> a
[1, 3, 'a', 'b', 'c', 'f', 7]
>>>
>>> a.pop(2)
'a'
>>> a
[1, 3, 'b', 'c', 'f', 7]

remove删除的是具体的value,没有返回值。
pop删除的是索引对应的value,并将删除的元素返回。
如果pop()不加参数,删除的是最后一个元素。
pop(0),删除第一个元素

堆栈:坑,先进后出,通过pop()实现
队列:通道,先进先出,通过pop(0)实现

改:
通过赋值去完成(通过索引定位):
a[2]=5

查:
1.通过索引
2.通过index去进行查询
3.获取某个值在列表中的位置

>>> a
[1, 3, 'b', 'c', 'f', 7]
>>> a[1]
3
>>> a.index('f')
4

排序:
sort,sorted
sort改变列表,sorted不改变列表
sort是列表的方法,对列表中value重新排序,sorted是内建函数,对序列进行排序,输出排序后的序列。

>>> a=[6,2,1,3,9,8]
>>> sorted(a)
[1, 2, 3, 6, 8, 9]
>>> a
[6, 2, 1, 3, 9, 8]
>>> a.sort()
>>> a
[1, 2, 3, 6, 8, 9]

17.list两种遍历方式(非常重要)

  1. for item in _list
  2. for index,item in enumerate(_list)
>>> a=[5,2,1]
>>> for index,item in enumerate(a):
...     print(index,item)
...
0 5
1 2
2 1

18.列表推导式

格式1:【输出 for xx in 序列 if 条件表达式】
一句话完成列表遍历,在循环中把满足某些条件的取出来。
求1-100内能同时除尽2和3的整数

--列出10以内的偶数
>>> [x for x in range(0,11) if x%2==0]
[0, 2, 4, 6, 8, 10]

--求1-100内能同时除尽2和3的整数
>>> [x for x in range(1,101) if (x%2==0 and x%3==0)]
[6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]

格式2:【输出 if 条件 else 表达式 for xx in 序列】
一句话完成列表编列,在循环中把满足和不满足某些条件的取出来做处理。

--将10以内的奇数平方,偶数减半
>>> [i*i if i%2==1 else int(i/2) for i in range(1,11)]
[1, 1, 9, 2, 25, 3, 49, 4, 81, 5]

18.__pycache__文件夹存储之前执行过的.py文件生成的pyc文件,如果下次执行.py文件时发现.py文件未作修改,则直接去pycache里面执行pyc文件,优化python的执行效率。

19.python3中的range相当于python2中的xrange。

20.input和raw_input的区别?

21.列表的切片问题

列表的切片是前闭后开的,即a[1:4],包含1,不包含4。(索引是从0开始的)

22.字符串split()函数

split() 方法语法:

str.split(str="", num=string.count(str)).

参数
str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
num -- 分割次数。

返回值
返回分割后的字符串列表。

split()和split(’ ‘)执行结果的差别
split()将空格,换行符,制表符等作为分隔符,而split(’ ‘)只是将空格作为分隔符。

23.字符串比较,in 的用法

两种情况:
字符串情况下最小单位为字符

s = "abc 123"
ret = "ab" in s
print (ret)

数组情况下最小单位是每个字符串

li = ["tom","rose","jack"]
ret = "to" not in li
print (ret)

24.字典

用大括号包括,用逗号分隔每个键值对,键值对之间用冒号连接
键是不可改变的数据结构(不是随便一个类型的数据都可以当键的),值可以是任意的对象
a={}
a=dict()

使用:
普通查询,参数校验:
字典的访问是通过key去取value
a={1:2,’haha’:e}
a[‘haha’] 如果没有这个key,执行会报错,可用于参数校验
a.get(‘haha’) 如果没有这个key,返回值为null
注意两者的区别。

增加、修改
直接赋值,setdefault,update
a[‘test’]=’diyige’ 既可以增加,又可以修改
a.setdefault() 增加一个新的key value,如果key存在,则value不更新
a.update(k,v)效果跟直接赋值一样

setdefault()用法:

语法
setdefault()方法语法:

dict.setdefault(key, default=None)
参数
key -- 查找的键值。
default -- 键不存在时,设置的默认键值。
返回值
如果字典中包含有给定键,则返回该键对应的值,否则返回为该键设置的值。

删除:
pop(key)
删除指定给定键所对应的值,返回这个值并从字典中把它移除。注意字典pop()方法与列表pop()方法作用完全不同。

字典的遍历:两种(三种)
(1)for item in _dict:
print item
输出的是key,不输出value,因为遍历的时候是吧字典当序列遍历

(2)for k,v in a.items():
print(k,v)

(3) for item in a.values() –只遍历values,基本用不到

25.列表中的字符串过滤问题

startwith()

描述
Python startswith() 方法用于检查字符串是否是以指定子字符串开头,如果是则返回 True,否则返回 False。
如果参数 beg 和 end 指定值,则在指定范围内检查。

语法
startswith()方法语法:

str.startswith(str, beg=0,end=len(string));
参数
str -- 检测的字符串。
strbeg -- 可选参数用于设置字符串检测的起始位置。
strend -- 可选参数用于设置字符串检测的结束位置。
返回值
如果检测到字符串则返回True,否则返回False

內建函数:filter(function_name,sequence)
将sequence中的每一项作为参数传递给function,即function(item)
在python2中,将符合条件的(执行结果为True),返回list ,tuple或者dict(需要验证,是否只返回列表),视sequence的类型而定,循环遍历取出。
在python3中,将执行结果为True的item,返回一个filter的对象,使用循环遍历取结果。

26.元组

列表是[],元组是(),都是有序的,元组创建之后无法修改,而列表是可以修改的。
元组的表示是逗号‘,’不是括号(),也就是说,不是加了()就是元组,而是要有,逗号,具体解释的举例如下:

>>> a=(1,2,3)
>>> type(a)
<class 'tuple'>
>>>
>>> a= 1,2,3
>>> type(a)
<class 'tuple'>

>>> a=(1)
>>> b=(1,)
>>> type(a)
<class 'int'>
>>> type(b)
<class 'tuple'>
>>> c=1,
>>> type(c)
<class 'tuple'>

元组和列表一样,通过下标访问。

元组的使用场景:
1.函数返回多项
return a,b
2.if a in b(b是一个元组)
或者if a in (‘test1’,’hello’,’gaga’,)
– 参考前面提到过的 in 的使用

27.集合 set

描述元素种类的一种无序序列,内建函数set
1.没有重复项
2.无序


>>> a='hello'
>>> set(a)
{'e', 'l', 'o', 'h'}
>>> a=set({1:2,4:5})
>>> a
{1, 4}

集合和列表的转换
集合的一些运算,其他的序列可能没有,普通列表可能需要使用集合的特征进行运算,比如求两个列表的交集,差集,并集等等

>>> a=[1,2,3,4,5,6,7]
>>> b=[5,7,9]
>>>
>>> set(a) & set(b)
{5, 7}
>>>
>>> set(a) | set(b)
{1, 2, 3, 4, 5, 6, 7, 9}
>>>
>>> set(a) - set(b)
{1, 2, 3, 4, 6}

应用:比如IP去重
set作为序列遍历
for item in set:

28.函数

排名问题

29.字符串前面加 ‘r’ 的作用

打开文件时open(r’d:\hello\hello.txt’)
不加r会报错,因为系统认为\是转义符

30.函数

def func_name(paras):
return

参数有几种?
普通参数 ,默认参数, 可变长参数

* args代表元组,会把所有没有指定key的参数,把这一类参数放到一个元组中
* * kwargs代表字典,会把所有指定key的参数,放到字典中

>>> def test_args(*args, **kwargs):
...     print(args,kwargs)
...
>>> test_args(5,c=8)
(5,) {'c': 8}
>>> test_args(5,8,c=8,d=9)
(5, 8) {'c': 8, 'd': 9}

>>> def test_args(*args, **kwargs):
...     return args,kwargs
...
>>> test_args(5,8,c=8,d=9)
((5, 8), {'c': 8, 'd': 9})
--上面的返回结果中多了最外边的两个括号,原因是return返回的是元组(元组的应用之一)

31.深拷贝

循环遍历中的删除问题
将列表中字符串的项删除

_list = [1,'aa','123','test',8,9,7]

def filter_str(item):
    if isinstance(item,str):
        return False
    else:
        return True
#    return not isinstance(item,str):
ret = []
rst = filter(filter_str, _list)
for item in rst:
    ret.append(item)

print(ret)

深度拷贝(补充代码在github上deep_copy.py)

32.嵌套函数 & 匿名函数

可编程参数 -> 函数式编程 -> 嵌套函数 -> 闭包 -> 装饰器

def test(m,n):
    return m+n

def func(func_name, *args, **kwargs):
    ret = func_name(*args, **kwargs):
    return ret+1

print(test(8,9))
print(func(test,8,9))

嵌套函数(子函数):函数体里面包含另一个函数的完整定义
应用场景:一个函数中有一小段逻辑被多次调用
闭包,装饰器

子函数能够调用父函数的局部变量,父函数无法调用子函数的局部变量
参考github中qiantao*.py

匿名函数(lambda函数):
定义:lambda跟一个或多个参数,跟着冒号,接着是一个表达式。
lambda是一个关键字,lambda冒号前边是参数,后边返回结果
形式:lambda x,y:x+y
应用场景:
函数式编程中,函数名本应由对应的实现逻辑,对于简单的逻辑,可以用一个lambda来表示。
更多的应用,是和一些内建函数进行搭配,比如filter,map,sorted
举例:
排名问题(下) 参考github上paiming.py

>>> func_name = lambda x,y : x+y
>>> func_name
<function <lambda> at 0x0000000001D31E18>  --注意:返回的是函数名
>>> func_name(1,2)
3
>>>
效果和下面的相同
def add(x, y):
    return x,y
add(1,2)
相同点,区别是什么?
相同点:
完成的作用相似
区别:
lambda返回的是一个函数名
正常函数返回的是结果

33.内建函数 map
map(function, sequence)

定义:对sequence中的item依次执行function(item),将执行结果返回一个map迭代对象,可以通过list放入列表中

举例:输出1到15的所有数的平方
参考github中pingfang.py

34.函数式编程

定义:对别的函数进行封装,运算,操作的函数
学习目的:
(1)需要对别的函数进行封装
(2)看源码(看别人的代码)
参数:
(1)支持传别的函数名
(2)任意参数*args ,**kwargs
应用场景:
(1)对一件事进行封装
(2)闭包、装饰器(以后讲)
标识:参数是其他函数的函数名
典型的使用了函数式编程的内建函数:sorted,map,filter

35.解释器加载脚本顺序

执行脚本中的某个函数,例如run(),可以使用以下两种写法,区别是什么?
(1if __name__ == "__main__":
    run()

(2run()

参看下面的脚本:

#coding:gbk
#python解释器加载文件的顺序

var1 = 1
var2 = 2

def test():
    print("执行test")

def test1():
    print("执行test1")

print(var1)
test1()

if __name__ == '__main__':
    print(var2)
    test()

我原本以为会先执行main函数,再执行脚本中其他的函数,输出
2
执行test
1
执行test1

但实际执行结果是,先执行前面的代码,最后执行的main,输出
1
执行test1
2
执行test

结论:
程序代码入口,并不是程序开始执行时第一个执行的。在其他语言中也是同样的道理。
顺序:
(1)加载import模块
(2)加载全局变量,全局对象
(3)加载函数名(注册函数名,不执行函数体)。如果有函数执行的话,就直接执行。
(4)if name == ‘main‘:

因为:
全局变量:存放在内存的静态区域(对于你的整个代码可见)
局部变量:存放在内存的栈中,函数执行完即销毁

35.全局变量global,局部变量

全局变量:位置在全局区域的变量
局部变量:在函数内的变量

函数的作用域:
L (Local) 局部作用域
G (Global) 全局作用域

以 L –> G 的规则查找,即:在局部找不到,便会去局部外的局部找,在找不到就会去全局找。

var = 12

def change_var():
#    global var
    var = 13
    return var

print(change_var())
print(var)

输出结果:
把global注释掉,输出 13,12
不注释global,输出13,13
可以通过在代码中添加print(id(var))来看看,各个变量var的地址是否相同

(1)如果函数中的变量与全局变量重名的话,解释器会把函数内的变量当成局部变量,重名归重名,但不是同一个变量
(2)如果想修改全局变量,需要通过关键字global去声明这个变量,这样就可以在函数中修改全局变量,一旦在函数中加了global,则这个函数中,这个名字的变量都是用的全局变量

结论:自己定义的函数变量,不要跟全局变量重名

36.内建函数eval,是把字符串当做命令去执行

参考博客:https://www.cnblogs.com/dadadechengzi/p/6149930.html
博客中有更多示例

内建函数eval,是把字符串当做命令去执行
将字符串str当成有效的表达式来求值并返回计算结果
函数定义:

eval(expression, globals=None, locals=None)

参数
expression:是一个参与计算的python表达式
globals: – 变量作用域,全局命名空间,是可选的参数,如果设置属性不为None的话,就必须是dictionary对象了
locals也:– 变量作用域,局部命名空间,是一个可选的对象,如果设置属性不为None的话,可以是任何map对象了

返回值
返回表达式计算结果。

eval(expression, globals=None, locals=None) — 官方文档中的解释是,将字符串str当成有效的表达式来求值并返回计算结果。globals和locals参数是可选的,如果提供了globals参数,那么它必须是dictionary类型;如果提供了locals参数,那么它可以是任意的map对象。

python是用命名空间来记录变量的轨迹的,命名空间是一个dictionary,键是变量名,值是变量值。
当一行代码要使用变量 x 的值时,Python 会到所有可用的名字空间去查找变量,按照如下顺序:
1)局部名字空间 - 特指当前函数或类的方法。如果函数定义了一个局部变量 x, 或一个参数 x,Python 将使用它,然后停止搜索。
2)全局名字空间 - 特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python 将使用它然后停止搜索。
3)内置名字空间 - 对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或变量。
python的全局名字空间存储在一个叫globals()的dict对象中;局部名字空间存储在一个叫locals()的dict对象中。我们可以用print (locals())来查看该函数体内的所有变量名和变量值。

example:

a=1
g={'a':20}
eval("a+1",g)   -- 这里的g,就是全局名字空间中的dict,g={'a':20}
-- 返回21


#test eval() and locals()
x = 1
y = 1
num1 = eval("x+y")
print (num1)

def g():    
    x = 2    
    y = 2  
    num3 = eval("x+y")    
    print (num3)        
    num2 = eval("x+y",globals())   
    #num2 = eval("x+y",globals(),locals())    
    print (num2)

g()

print locals()["x"]
print locals()["y"] 
print globals()["x"]
print globals()["y"]

num1的值是2;num3的值也很好理解,是4;
num2的值呢?由于提供了globals()参数,那么首先应当找全局的x和y值,也就是都为1,那么显而易见,num2的值也是2。
如果注释掉该句,执行下面一句呢?根据第3)点可知,结果为4

eval函数的妙用:
eval函数就是实现list、dict、tuple与str之间的转化
str函数把list,dict,tuple转为为字符串

字符串转换成列表

>>> a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
>>> print(type(a))
<type 'str'>
>>> b = eval(a)
>>> type(b)
<type 'list'>
>>> print(b)
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
>>> 

字符串转换成字典

>>> a = "{1: 'a', 2: 'b'}"
>>> print(type(a))
<type 'str'>
>>> b = eval(a)
>>> print(type(b))
<type 'dict'>
>>> print(b)
{1: 'a', 2: 'b'}
>>> 

字符串转换成元组

>>> a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
>>> print(type(a))
<type 'str'>
>>> b=eval(a)
>>> print(type(b))
<type 'tuple'>
>>> print(b)
([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
>>> 

37.类的初步认识

class ClassNameFatherClass):
    def __init__(self, class_args1):
        self.class_args1 = class_args1

   def class_func(self):
       return

类实例 ==类对象
类参数写在__init__里(而不是写在类名后面的括号里,与其他语言不同)类后面的括号中写的是类继承的父类
类里面所有的函数第一个参数要写成self(不要问为什么,照做就是了),凡是有self的函数,都是类实例函数
self其实是类实例对象

38.初始化 def __init__(self):

格式:

    def __init__(self, a):
        print111)
        self.a =a 

当类初始化的时候,比如 a = A(‘ss’)
这个操作会打印出111,因为这个操作会执行init()函数

作用:类传参的地方,例如a,调用的时候要传入参数
用法:类实例属性(例如self.a)在类的整个范围内都可以使用

初始化实例对象的时候会执行__init__函数

39.类属性 && 类实例属性

类属性,不需要初始化实例对象就可以使用
类实例属性,在__init__()函数的列表中,需要有了实例对象之后才能调用

在程序加载过程中,类属性和类定义,函数一样,会被加载(注册),类实例属性不会,类实例方法会注册,但不执行函数体。

类属性的位置:在__init__函数的前面
类属性使用场景:
类似于其他语言中的静态参数,参看41

40.继承

参考github脚本class_inherint.py

41.类属性的应用场景

参考 db_conn_class_property.py

42.访问控制 public, protected,private

在Java,C++,以及PHP中都有对应的关键字,public,protected,private,但是在Python中却没有这些关键字来声明类成员的访问作用域。

在Python中是通过一套命名体系来识别成约的访问范围的
protected: _ 函数名开头是一个下划线
private: __ 函数名开头是两个下划线

在python中所有的以字母开头的成语名称被python命名体系自动识别为public,单个下划线开头的成员被识别为protected,最后双下划线开头的成员被识别为private。

另外,Python不支持诸如C++, Java的根据参数类型与数目的不同而进行的重载(overload),即只以函数名字做为函数身份的判断,不会依据参数。而且如果出现多个同名函数(不论参数是否数目相同),则以最后一个为准(即后出现的函数将之前的同名函数覆盖)。

参考 protected_private.py

43, python中的self其实就是类实例对象本身

参考 self.py

44.单例

监控程序,每次都要建立一个新的数据库连接,监控频繁情况下,需要创建很多很多连接,这个问题如何解决:
(1)使用前面提到的类属性
(2)初始化一个类对象,放到全局对象位置,其他想使用类的地方直接使用此对象
(3)单例(专业处理连接多的问题)
(4)数据库连接池

单例模式,在类被执行的才连接,不想类属性或者全局类对象一样,程序加载的时候就连接
是一个函数封装
通过装饰器的方式调用

场景:通过单例解决mysql等服务连接过多的问题

思路:
先判断实例是否已经初始化
如果已经初始化了对象,直接使用初始化的对象
如果没有,则初始化

参考singleton.py

45.闭包

闭包就是你调用了一个函数a,这个函数a返回了一个子函数名字b给你,这个返回的函数b就叫做闭包。

def a():

    def b():
        return 1

   return b

所以,通俗的讲,闭包就是,返回子函数名
作用:使用子函数之外的父函数的变量
参考 bibao.py

闭包到底是干嘛的?一般用来做装饰器

46.装饰器

闭包+函数式编程 = 装饰器

例子参看第五课 6-装饰器.avi

47.python中执行shell指令

执行状态(执行成功或失败)和执行结果:code,result
os.system() 返回code,result输出在console中

>>> 
>>> import os
>>> ret = os.system("free -m")
             total       used       free     shared    buffers     cached
Mem:         70619       9497      61122          0        212       1510
-/+ buffers/cache:       7774      62845
Swap:         4095          0       4095
>>> print(ret)
0


import commands
ret = commands.getoutput(shell指令或者脚本)
code,ret = commands.getstatusoutput(shell指令或者脚本)
命令不同,返回值的数量不同

py3中,将commands模块融合在了subprocess模块中

48.线程

线程能否杀死?正常情况下是不能的。
线程安全问题如何解决?锁。
多线程使用锁的话,多线程是不是就成了串行了?只是某一时刻或某一部分串行
线程的作用是什么?异步、并发

Threading模块

需要掌握老师提供的脚本

t = threading.Thread(target=func_name,args=[])
t.start

target是需要多线程执行的函数,args是函数的参数

原生调用的内部原理:
start触发,run是真正执行的
默认是等待子线程退出,主线程才退出(进程在执行完所有代码时,子线程还未执行完,进程要等待子线程执行完再退出)
如果setDaemon(True),则不等待(要在子线程start之前设置,否则会报错:RuntimeError: cannot set daemon status of active thread)

主线程退出后,子线程就没了

#不带参数
import time
import threading

def sleep():
    time.sleep(5)
    print('5 second')
    return 'money'

t = threading.Thread(target=sleep)
#t.setDaemen(True)
t.start()


#带参数
import time
import threading

def sleep(n):
    time.sleep(n)
    print('sleep %s second' % n)
    return 'money'

t = threading.Thread(target=sleep, args=[3])
# t = threading.Thread(target=sleep, args=(3,)) 元组必须加逗号
t.start()


#如何获得线程中的返回值?
#一般很难获得线程中结果,但是如果工作中需要获得结果,怎么办?
#这种需求很少
#1.写入数据库
#2.

# 原生线程的两个缺点:
#1.传参不得劲儿(用列表还好,用元组容易出错(单个参数没加逗号))
#2.函数的返回值无法获取

join
使得线程阻塞到函数执行完成后,主线程才继续进行
后者传入一个参数,表明阻塞时间,超过该时间之后,就不阻塞了,可以继续执行(不用等线程执行完成)
参考thread_join。py
使用场景是在多线程中,多个线程join,总执行时间,是几个线程中执行时间最长的线程的执行时间。

锁:

from threading import lock

lock = Lock()
lock.acquire()
lock.release()

线程池:

from concurent.futures import ThreadPoolExecutor
t = ThreadPoolExecutor(num)
t.submit(func_name)

49.队列

队列的作用:
异步:点赞业务(对于实时性要求不是很高,并且对数据库操作)
系统解耦:订单系统,发货系统
缓冲流量:秒杀

在python中使用队列
py2.7 Queue
py3.x queue

创建:queue.Queue(maxsize)
往队列中存放元素:put(obj)
取元素:get() 按顺序取,所以不需要参数
enpty()

import Queue
import time

q = Queue.Queue()

for i in range(10):
    q.put(i)

while not q.empty():
    print(q.get())
    time.sleep(0.5)

50.异常处理

(1)异常抛错机制
– 程序运行异常,解释器会首先看当前的执行环境(函数或类)有没有捕获这个异常,有没有try。
– 当函数里没有找到的话,它会将异常传递给上层的调用函数,看看那里有没有处理。
– 如果在最外层(全局‘main’)还是没有找到的话,解释器就会退出,同时打印出traceback信息在标准错误里。
注:当异常发生的时候
– 代码异常,当前执行流终止,退出
– 异常信息会打印在标准错误里

怎么样才能不让用户看到报错栈信息,自己又能捕获到报错栈信息呢?可以通过如下形式

import traceback
print(str(traceback.format_exc())) --可以存储到一个变量里面,记录在日志里

(2)异常信息的组成
Traceback信息 + 出错类型 + 出错原因

(3)捕获异常的场景
– 允许代码发生某种类型的异常不需要终止代码,可以捕获异常,继续往下走。
– 建立数据库连接或者其他的组件连接,使用完不管代码是否异常,都要关闭连接
– 线程中,代码要进行异常捕获
– 脚本:入口函数处
– 需要捕获异常信息用于展示:代码发生异常的时候,需要将异常信息汇报给上层系统,例如代码部署脚本,部署上百个机器,不可能通过登录机器去查找报错

(4)捕获异常的5种方式
– try 。。。 except 。。。 最常用的一种
– try… except Exception as e: …print(e) 打印信息不全,只打印报错信息
– try … except 特定的异常 print
– try…except … finally …

(5)异常错误类型

51.正则表达式

猜你喜欢

转载自blog.csdn.net/lijingkuan/article/details/80056779