Python语言学习笔记

前言

各种py库的api中文帮助文档:文档1 文档2
使用help、dir函数,可以实时帮助。
各种py第三方库都能下载到本地:地址


Part A. 内部函数、属性

一、获取变量的类型

内容包括:type、isinstance的使用

参考来源
1、使用type模板

import types
type('abc')==types.StringType #输出:True
type(u'abc')==types.UnicodeType #输出True
type([])==types.ListType #输出:True

2、isinstance能够解决class的继承关系判断问题

a = Animal()
d = Dog()
h = Husky()# 狗的名字。
isinstance(h, Husky)# 自己找自己的类。  # 输出True
isinstance(h, Animal)#从子类实例找父类对象也是可以的。  # 输出True
isinstance(d, Husky) #从父类实例往子类对象就不行。    # 输出False

3、判断变量的数据类型的两种方法。isinstance(变量名,类型) 、type() 参考

# 方法1
a = 1.23
isinstance(a, float)

# 方法2
type(a) == type(3.21)

4、仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

class MyObject(object):
    def __init__(self):
        self.x = 9
    def power(self):
        return self.x * self.x

obj = MyObject()
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
hasattr(obj, 'power') # 有属性'power'吗?    # 输出True
getattr(obj, 'power') # 获取属性'power'     # 输出<bound method MyObject.power of <__main__.MyObject object at 0x108ca35d0>>
fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
fn # fn指向obj.power  #输出:<bound method MyObject.power of <__main__.MyObject object at 0x108ca35d0>>
fn() # 调用fn()与调用obj.power()是一样的。    #输出:81

5、只有在不知道对象信息的时候,我们才会去获取对象信息。如果可以直接写:

sum = obj.x + obj.y
sum = getattr(obj, 'x') + getattr(obj, 'y') # 不要这么写。推荐上面。

二、装饰器

参考来源
@log(‘execute’) # log 函数先接收 ‘execute’ 然后再接收被装饰的函数。
@functools.wraps(func) # 解决 >>> now.name 输出 ‘wrapper’

三、字符编码

1、decode后返回的是一个unicode码字符,这样就能与u”xxx”拼接了。
head_path = os.getcwd().decode(“gbk”)+”\”+u”权重词林符号义原数目”
2、unicode编码的字符串,汉字的大小是1.
print u”义原数目”.len() # 输出 4
3、os.listdir()返回的字符串列表却是unicode型的。对这实验结果我比较奇怪。
print ” “.join([v for v in os.listdir(head_path) if v[-4:] == u”义原数目”]) # 输出 实验2-result-义原数目; 实验3-result-义原数目
4、参考1 参考2
待精简参考地址里面的知识点。
5、二进制文件与普通文本文件的差别。
读取时的区别:二进制可以每个字符为一位,不会出现中文字符需要占据多位问题,但是需要进行encode才能知道具体的字符串。

在python的load_word2vec_format函数里面有具体区别的代码:
gensim.models.KeyedVectors.load_word2vec_format(‘vectors.bin’, binary=True)

注:c语言的fgetc函数,暂时我觉得它不能够直接读取中文字符,不过可以读取中文字符的二进制格式。具体的我要实践后再确定。

四、chain函数

可以把一组迭代对象串联起来,形成一个更大的迭代器。

例子1:

for c in itertools.chain('ABC', 'XYZ'):
    print c # 迭代效果:'A' 'B' 'C' 'X' 'Y' 'Z'

例子2:

其中 ngrams: [[(0, 0, 0, 0, 0, 0, 0, 81), (0, 0, 0, 0, 0, 0, 81, 68), …],[…],……] 因此下面行将得到[(0, 0, 0, 0, 0, 0, 0, 81), (0, 0, 0, 0, 0, 0, 81, 68),…]

ngrams = np.array(list(chain(*ngrams))) # 注:在函数调用中使用*list/tuple的方式表示将list/tuple分开,作为位置参数传递给对应函数(前提是对应函数支持不定个数的位置参数)

五、for函数

1、把两个list 打包在以前然后顺序放下遍历。

for id_, text in zip(trainSentenceId, trainContent):
    print "id_ 为"+id_+"的内容是:"+text

2、迭代在中途暂停了,再次启动的时候依旧是从开头迭代,可以多次迭代,中途改变也是可以的。

a = [124,5,7]
for idx,v in enumerate(a):
    if idx == 0:
        a[idx] = 1
        break
for v in a: 
    print v # 输出 1 5 7

六、reduce函数

views_idx = [[1,3,5],[2,3,6],[4,5,10,123,999]]# views_idx是一个二维数组来的。lambda你可以认为它是一个函数来的,输入x,y,把x y都转化为set后取并集。reduce 意思就是把当前与下一个 作运算,得到的结果成为新一轮的当前。
print reduce(lambda x, y: set(x) | set(y), views_idx)# set([1, 2, 3, 4, 5, 6, 999, 10, 123])

七、属性名

1、doc

def func():
    """Here's a doc string"""
    pass
print func.__doc__# 输出 "Here's a doc string"

2、name

if __name__=='__main__':
    print "haha"    # 当程序执行到这里的时候,就会自动运行了。

八、报错处理

try:
    g = group.get_group(fid)
except Exception,e:
    continue
主动抛出错误的语句:
raise Exception("抛出一个异常")

九、assert断言

用于一旦条件不满足就报错,其实也就是exit了。一行替代2行。
参考来源
用法:assert 表达式 [,异常参数](异常参数可有可无)

>>> assert 1 == 0,'one does not equal zero' # 逗号后面的内容有没有都可以。
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AssertionError: one does not equal zero

在try-except语句中使用assert:

>>> try:
...     assert 1 == 0,'one does not equal zero'
... except AssertionError,args:
...     print '%s:%s' % (args.__class__.__name__,args)
... 
AssertionError:one does not equal zero            #输出

十、创建文件夹及普通文件

import os
os.mkdir(u"D:/ha")# 创建文件夹
file = open(u"D:/ha.txt",'w')# 创建普通文件,如txt

十一、对象

1、is 判断变量指向是否同一对象 【P核心 62】

a = 1.5
b = a
a is b 为 True,等价于id(a) == id(b)

2、cmp 如果obj1 小于 obj2 返回一个负整数。

a, b = "abc", "xyz"
print cmp(a,b) # 输出

3、repr、str、eval

print repr([0,1,2])
print "[0,1,2]"
print str([0,1,2]) # 三者输出一样。
repr等价于"",都是字符串输出。可用eval()重新得到该对象,对python友好。
str无法用eval获取回原对象,对用户友好。

4、type、isinstance # 推荐使用 isinstance

a = 123
if isinstance(a, (int, long, float, complex)):
    print "a 是一个数学的数值",type(a).__name__  # 后者输出 int

import types
if type(a) == types.IntType:
    print "是整型"

十二、类

学习廖雪峰面向对象的笔记,到时需要把很容易的知识点剔除掉。

1、类名通常是大写开头的单词。
2、bart = Student(‘Bart Simpson’, 59)。创建实例的时候,括号的作用是联系init的。 class Dog(Animal):编写对象时,括号内容代表父类。
3、和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:

>>> bart = Student('Bart Simpson', 59)
>>> lisa = Student('Lisa Simpson', 87)
>>> bart.age = 8
>>> bart.age # 输出:8
>>> lisa.age # 输出:Traceback (most recent call last):

4、变量下划线的特殊意义。

①单下划线开头:比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

②双下划线开头:私有变量,外面访问不到。但其实,__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量。

③双下划线开头并结尾:特殊变量,特殊变量是可以直接访问的,不是私有变量。

5、继承与多态的好处:

def run_twice(animal):# 能够接受animal类、以及继承它的所有子类,都能顺利执行完。(这是因为最高父类animal肯定有run这个函数,那么子类必须也有,所以肯定没错。)
    animal.run()
    animal.run()
class Dog(Animal): # 随意一个继承animal的类,并且可以选择性的该与不该原父类的函数。
    def run(self):
        print 'Dog is running...'
    def eat(self):
        print 'Eating meat...'
run_twice(Dog()) # 输出:2次的 Dog is running...

6、init.py 的作用
当你使用import 时,如果你新建的包没有这个东西,该包就不能被识别到。
7、如何调用另一个包中的类

from data_processing.data_util import DataUtil # data_processing是py包、data_util是py格式的文件、DataUtil 是类class
data_util = DataUtil() #新建一个实例

8、为实例添加新的属性

>>> class Student(object):
...     pass

然后,尝试给实例绑定一个属性:

>>> s = Student()
>>> s.name = 'Michael' # 动态给实例绑定一个属性
>>> print s.name # 输出 Michael

还可以尝试给实例绑定一个方法:

>>> def set_age(self, age): # 定义一个函数作为实例方法
...     self.age = age
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s, Student) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果 25

但是,给一个实例绑定的方法,对另一个实例是不起作用的:

>>> s2 = Student() # 创建新的实例
>>> s2.set_age(25) # 尝试调用方法
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'set_age'

为了给所有实例都绑定方法,可以给class绑定方法:

>>> def set_score(self, score):
...     self.score = score
>>> Student.set_score = MethodType(set_score, None, Student)

9、super(B, self)表示找到B的父类(class B(A): 就是类A)
10、参数带 * 、**

* 用来传递任意个无名字参数,这些参数会一个Tuple的形式访问。
**用来处理传递任意个有名字的参数,这些参数用dict来访问

11、@staticmethod 、 @classmethod 参考来源

@staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
@classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。

12、类的实例属性,是实例对象的独有属性,是动态的。不需要预先声明。

one_class.none_def = 1

13、类的self会自动传入,不需要人工显式传入,不过继承父类时,就需要把子类实例传过去,不然那边不知道。

class Son(Father):
    "这时一个儿子类"  # 通过Son.__doc__ 可以获得这类定义
    def __init__(self, one_attr):
        Father.__init__(self, one_attr) # 这时才需要显式传self

14、命名规则
类名开头大写,其余用骆驼记法,如 updateEmail、update_email
15、_name用在type中

print type("one_string!!").__name__ # 原输出 <type 'string'>  加name限制后输出 'string' 

16、module_ 获取类在哪个模板(py文件中)

from main import Son
print Son.__module___ # 输出main

十三、open:打开文件

1、open、io.open、codecs.open之间的区别?
参考来源
最早的时候,只有open。
你知道的,Python 2的编码多么蛋疼,所以,就有了codecs.open.
至于io.open,其实是因为Python 2的open实际上是file模块提供的,而Python 3的open是io模块提供的。然后,Python 2.6引入了这个Python 3的特性,叫做io.open,以便和原来的open相区分。
个人建议:
Python3直接用open。
Python2.x下用codecs.open,特别是有中文的情况,然后也可以避免踩到2.6下面io.open的坑。
如果希望代码同时兼容Python2和Python3,那么推荐用codecs.open。
个人经验:在py2.7中,codecs.open可以直接调encoding,如果你写得此处正确,len函数得到的结果就正确。

2、自动关闭文件的机制。

with open('/Users/michael/test.txt', 'w') as f:
    f.write('Hello, world!')

十四、除法、以及保留小数点

参考来源
向上取整

>>> math.ceil(3.25)
4.0

四舍五入

>>> a=3.25;b=3.75
>>> round(a);round(b)
3.0
4.0

向下取整

>>> a = 3.75
>>> int(a)
3

保留小数点后5位

print "%.5f" % ans

十五、write、read、print

1、raw_input:读取一行,当做一个字符串读取进来。只识别换行符。
2、格式化输出 如%s等等 参考来源

3、python 导出词向量文件的两种方式

(1)print >>可以代替write。使用round限定小数点位数。(推荐使用) 参考

def print_word_vectors(word_vectors, write_path):
    """
    This function prints the collection of word vectors to file, in a plain textual format.
    """
    print "Saving the counter-fitted word vectors to", write_path, "\n"
    with open(write_path, "wb") as f_write:
        for key in word_vectors:
            print >>f_write, key, " ".join(map(str, numpy.round(word_vectors[key], decimals=6)))
(2)、直接open后write。用%.f限制小数点位数 。 参考
def print_word_vecs(wordVectors, outFileName):
    outFile = open(outFileName, 'w')
    for word, values in wordVectors.iteritems():
        outFile.write(word+' ')
        for val in wordVectors[word]:
          outFile.write('%.4f' %(val)+' ')
        outFile.write('\n')
    outFile.close()

十六、nan与inf的判断问题

参考
1、使用 math 模块的 math.isinf 和 math.isnan 函数:

>>> inf = float("inf") # 正无穷
>>> ninf = float("-inf") # 负无穷
>>> nan = float("nan")

>>> import math
>>> math.isinf(inf)
True
>>> math.isinf(ninf)
True
>>> math.isnan(nan)
True

2、用 numpy 模块的函数

>>> import numpy as np
>>> np.isnan(np.nan)
True
>>> np.isnan(float("nan"))
True
>>> np.isinf(np.inf)
True
>>> np.isinf(np.NINF)
True
>>> np.isinf([np.inf, -np.inf, 1.0, np.nan])
array([ True,  True, False, False])
>>> x = np.array([-np.inf, 0., np.inf])
>>> y = np.array([2, 3, 4])
>>> np.isinf(x, y) # 判断x数组,并把结果写到y数组中。
array([1, 0, 1])
>>> y
array([1, 0, 1])

十七、函数参数

参考
(1)位置参数:直接按照位置映射参数具体数值,可以不写参数名。
(2)默认参数: 形如 def power(x, n=2) 带有默认值的
(3)可变参数:形如 def calc(*numbers) ,意思是传入进来的多个参数,会被认为是一个,用元组格式合并起来,如 calc(1, 2) 。所以调用时,如果参数本来就是一个元组或list,就需要用*把它解开元组,如 calc(*nums)。
(4)关键字参数:形如 def person(name, age, **kw),意思是kw是一个dict结构,传入一个多个参数时需要写等号 city=”eee”,这样他们就能在kw中获取了。如果本来就是字典格式,就需要加 ** 符号来解开dict结构【就是用符号对应起来的意思】。
(5)命名关键字参数:形如 def person(name, age, *, city, job)。加个*符号作为分隔符(它自身无用),后面的就是命名关键字参数 。必须传入参数名,位置参数。如果没有传入参数名,调用将报错。


Part B. 数据类型

一、float类型

1、浮点数与整数的等号判断,可以不必像C语言那样加一个极小的阈值。
print float(1) == int(1) # 输出True
2、向上向下取值 参考来源

round(3.25) # 四舍五入取整
int(1.923) # 向下取整
math.ceil(3.25) # 向上取整

二、list

1、取出一个list最大元素的索引(下标)

aa = [5,2,16,4,8]
print aa.index(max(aa))# 输出2

2、list的合并
方法 1:相加

list1 += list2

方法2:用list的extend方法,L1.extend(L2),该方法将参数L2的全部元素添加到L1的尾部,例如:

L1 = [1, 2, 3, 4, 5]
L2 = [20, 30, 40]
L1.extend(L2) # 输出 L1[1, 2, 3, 4, 5, 20, 30, 40]

方法3:用切片(slice)操作,L1[len(L1):len(L1)] = L2和上面的方法等价,例如:

L1 = [1, 2, 3, 4, 5]
L2 = [20, 30, 40]
L1[len(L1):len(L1)] = L2
L1 # 输出 [1, 2, 3, 4, 5, 20, 30, 40]

但切片方法用起来更灵活,可以插入到头部,或其他任意部位,例如:
加到开头:

L1[0:0] = L2
L1[20, 30, 40, 1, 2, 3, 4, 5]

加到中间:

L1[1:1] = L2
L1[1, 20, 30, 40, 2, 3, 4, 5]

3、定义的多维数组,大小是逆着的。

a = [[0]*3]*5  # 5行3列
print a[4][2]  # 输出0,但是a[2][4]就会超出范围。

4、矩阵的浅复制、深复制。

正确:matrix= [ [ -1 for i in range(3) ] for j in range(4) ]
然而:matrix = [[-1]*3]*4,这是浅复制,比如:matrix[0][0] 与 matrix[1][0] 是同步的。

5、排序。三大参数:cmp、key、reverse
cmp(x,y):函数用于比较2个对象,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1。
key:在sort()函数中的作用,key和cmp参数一样,使用时都需要提供可以做为排序依据的函数
reverse:控制是否逆序,这样就不用在cmp中控制了。

print ['aa','zxczxc','a'].sort(key=len,reverse=False)# 结果 ['a', 'aa', 'zxczxc']。这是简写形式,实际用要拆分:a = ['aa','zxczxc','a']然后a.sort().
print [('b',6),('aggg',1),('c',3),('sd',4)].sort(cmp=lambda x,y:cmp(len(x[0]),len(y[0]))) # 结果[('b', 6), ('c', 3), ('sd', 4), ('aggg', 1)]

6、它是无shape的,只有np.array有。而且它无 .array() 这样的转换。只能:

list_1 = np.array(list_1)

7、pop 直接改变原数组地弹出一个元素出来。

file_list = ["dfg","hh","jjj","ttt"]
for i in xrange(4):
    tmp =file_list.pop(0)# 依次输出 dfg   hh   jjj   ttt

8、使用map。它可以用于自定义函数,也能int等转换格式。

def f(x):
    return x * x
map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) # 输出[1, 4, 9, 16, 25, 36, 49, 64, 81]
map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])

9、使用reduce。使用目前的结果继续与往下一个元素做同样的运算。可自定义运算方式。

def add(x, y):
    return x + y
reduce(add, [1, 3, 5, 7, 9]) # 输出 25

def fn(x, y):
    return x * 10 + y
def char2num(s):
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
reduce(fn, map(char2num, '13579')) # 输出 13579

10、使用匿名函数
通过对比可以看出,匿名函数lambda x: x * x实际上就是:

def f(x):
    return x * x

关键字lambda表示匿名函数,冒号前面的x表示函数参数。

f(5)# 输出 25
map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])# 输出 [1, 4, 9, 16, 25, 36, 49, 64, 81]

11、sort排序

x = [4, 6, 2, 1, 7, 9]
x.sort()# 或者 x = sorted(x) 注意着两个是有区别的,list.sort直接在原序列中改变,sorted(x)可以赋值 但不改变原序列。
print x

12、append是返回值是None。

print a = [v  for v in one_list].append(a) # 输出 None
print [v  for v in one_list].append(a) # 得到想要的值。

13、使用pop函数,实现stack栈的功能。

stack = [235475]
top = stack.pop()

14、使用heapq 模板 很容易list转化成堆排序的list。

heapq.heapify(one_list) # 处理后one_list 就有堆排序的功能了,使用heappush 进行添加元素,详情见该模板。

15、[:]作为深度复制

a= [1,5,7]
b=a[:] , b=a#这两种方式是不同的,前一种是深度复制,后一种是b指向a的意思。

三、字符串

1、是否以某字符结尾。

if(v.endswith(u'车')):
    print "该字符串以‘车’字结尾"

2、对于unicode字符串,想要改变特定字符,只能是复制一遍。不能指定某个下标进行修改。

text_lower_tmp = text_lower_tmp[:idx] + u'#' * len(view) + text_lower_tmp[idx+len(view):]

3、使用% 进行格式化参考来源

print("I'm %s. I'm %d year old" % ('Vamei', 99))# %x 十六进制整数。%s 字符串。%d 十进制整数。%e 指数 (基底写为e)。
print("I'm %(name)s. I'm %(age)d year old" % {'name':'Vamei', 'age':99})# 使用字典,结果与上面一样的。
print("%+10x" % 23)# +表示右对齐。-表示左对齐。' '表示在正数的左侧填充一个空格,从而与负数对齐。0表示使用0填充。

4、format输出。它 与% 格式化,有异曲同工的作用。它是更高级的,以后直接用它就行了。 参考1 参考2 参考3

for i in range(1, 6):
    print  'split_{}.csv'.format(i)# 结果split_1、split_2等。

【等等其他……(待摘录网址中有用的)】

使用 :. 符号控制输出浮点的数位。
3.1415926   {:.2f}  3.14    保留小数点后两位

5、其他的字符串处理函数 参考1 参考2

str.strip() # 去两边空格
cmp(sStr1,sStr2) # 比较字符串
【等等其他……(待摘录网址中有用的)】

6、find函数,返回第一次发现的下标。

idx = v_lower.find(text_one_view)
while idx != -1:        
    idx = v_lower.find(text_one_view)

7、字符串的替换 参考1 参考2
例子1 使用replace(old, new[, max])。max是最大替换次数:

one = ur"F:\workbench_chj\aa".replace("\\",r"\\")  # 里面使用了两种转义ur、r来取消转义。不过r"\"你应该要 "\\" 。 其实如果只是为了写地址,只需要使用r取消转义就好了

例子2:使用正则替换。

strinfo = re.compile('word') # import re
a = "hello word"
b = strinfo.sub('python',a) # 输出 hello python

8、判断字母、数字等。下面的全部判断正确。

print "1".isdigit()# 判断是否只有数字。
print "a".isalpha()# 判断是否只有字母。
print "1".isalnum()# 合并上面两种,判断是否只有字母或数字。
print "a".islower()# 判断是否只有小写字母。
print "ABC".isupper()# 判断是否只有大写字母。
print "AB1".isupper()# 也是判断正确的。但是“11”就判断是错了。

9、str.startwith()、str.endwith() 直接匹配字符串前面后面,返回True or False。支持多匹配模式。
10、str.replace(“待替代”, “新的”)
11、split函数 参考

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

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

12、rsplit函数。与split相似,只不过它是从后往前切分 参考

str.rsplit([sep=None][,count=str.count(sep)])
参数
sep -- 可选参数,指定的分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
count -- 可选参数,分割次数,默认为分隔符在字符串中出现的总次数。
In[2]: "ff.f.ee.r".split(".",1)
Out[2]: ['ff', 'f.ee.r']
In[3]: "ff.f.ee.r".rsplit(".",1)
Out[3]: ['ff.f.ee', 'r']

四、dict

1、分类器使用的都是array、list格式,你可以.toarray()或者np.array(list_xx)、list(xx)或xx.tolist()进行格式的转化。
2、dict转化为list

params={'subsample':0.7, 'min_child_weight':3,'eta': 0.007}
print list(params.items())# 输出[('subsample', 0.7), ('eta', 0.007), ('min_child_weight', 3)]
print list(params)# 输出['subsample', 'eta', 'min_child_weight']

3、dict字典是否含有某个键,使用:had_key()

注:py3里面没有这函数,只能用 in 来判断。

a = {1:'aaa',2:'bbb','abc':'ccc','3':'ddd'}
print a.has_key(1) #返回True
print 1 in a #返回True

4、dict.keys()、dict.values() 分别返回所有的关键字、所有的值

print type(dict.keys()),type(dict.values())# 两个都是list。分别是关键字、值。他们的顺序是一一对应的。

5、使用dict关键字可以实现等号起到冒号的作用

print params = dict(dim_n=[2, 5, 10],clf_C=[0.1, 10, 100])# 输出{'dim_n': [2, 5, 10], 'clf_C': [0.1, 10, 100]}

6、加 for 迭代。items()返回一个列表。iteritems()返回生成器,在py3中不可使用。

for k,v in dict.items():
    print "dict[%s]=" % k,v

7、利用zip建立dict字典

feed_dict = dict(zip(holder_list, feed_list))

8、defaultdict 初始化 参考来源

from collections import defaultdict
>>> s = 'mississippi'
>>> d = defaultdict(int) #另一种常用 d = defaultdict(list)
>>> for k in s:
...     d[k] += 1
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]

9、调用函数的作用

map(lambda y: np_utils.to_categorical(y, 4), ner_target) # ner_target是一个(19L, 100L)的矩阵。返回ner_target被处理后的值 (19L, 100L, 4L)。

10、字典排序参考来源
按照key进行排序

print sorted(dict1.items(), key=lambda d: d[0]) 

按照value进行排序

print sorted(dict1.items(), key=lambda d: d[1]) 

11、利用两个list转为dict参考来源

>>>list1 = ['key1','key2','key3']
>>>list2 = ['1','2','3']
>>>dict(zip(list1,list2)) 结果得到:{'key1':'1','key2':'2','key3':'3'}

12、合并两个字典

d = {"o":2,"i":88}
d2 = {"e":2,"r":88}
d.update(d2) # 内部更新的。
len(d)
Out[5]: 4

五、set

参考
1、元素去重。并转回list。

real_list = list(set(tmp_list)) #list的元素去重

2、增加一个元素。字符串应该先放入list中,再放入set中才能保持整体。否则将会被拆成多个单字符。

s1 = [u"分数分数我是"]
tmp_set1 = set(s1) #只有1个元素
s2 = u"分数分数我是"
tmp_set2 = set(s2) # 有4个元素
tmp_set2 |= set([s2]) # 并集
tmp_set2 &= set([s2]) # 交集
tmp_set2.add(s2) # 增加一项
tmp_set2.update([s2]) # 增加多项

3、删除一项 remove()。

tmp_set2.remove('H')

4、set的无序性。
因为对同一个list,每次执行的set,得到的结果不一样。需要转list后用sort进行规范。

六、zip

1、基本用法 参考来源

x = [1, 2, 3]
y = [4, 5, 6, 7]
xy = zip(x, y)
print xy # 输出 [(1, 4), (2, 5), (3, 6)]

2、与dict结果快速建立字典【结合下面的只是可以知道它的原理:zip会从x取一个元素、y取一个元素,组成新元素。这个新元素恰好符合字典映射的需求。】 参考来源

>>> x=['bob','tom','kitty']
>>> y=[80,90,95]
>>>d=dict(zip(x,y)) # 输出 [('bob', 80), ('tom', 90), ('kitty', 95)]

3、自己的实践,* 有解压的意思。总体意思就是,zip函数中外围肯定是[],然后不断选择元素组加(),它会每个list参数选择一个元素进行组合 参考来源

x = [1, 2, 3]
print [x] * 3 # 输出 [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
r = zip( [x] * 3)
print r# 输出 [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
r = zip( [x,x,x] ,[1,9,8])
print r# 输出 [([1, 2, 3], 1), ([1, 2, 3], 9), ([1, 2, 3], 8)]
print ""
r = zip(* [x] * 3)# 解压的意思。
print r# 输出 [(1, 1, 1), (2, 2, 2), (3, 3, 3)]
r = zip( *[x,x,x] )
print r# [(1, 1, 1), (2, 2, 2), (3, 3, 3)]
print ""
r = zip( [x],[x],[x] )
print r# [([1, 2, 3], [1, 2, 3], [1, 2, 3])]
r = zip( x,x,x )
print r # [(1, 1, 1), (2, 2, 2), (3, 3, 3)]

4、号的作用:在函数调用中使用 list/tuple的方式表示将list/tuple分开,作为位置参数传递给对应函数(前提是对应函数支持不定个数的位置参数)

5、如果进行zip时,数组大小不统一,将会只保留大家都有的。

print zip([[1,2,3],[4,5],[6]]) # 输出 [([1, 2, 3],), ([4, 5],), ([6],)]
print zip(*[[1,2,3],[4,5],[6]])# 输出 [(1, 4, 6)]

Part C. 第三方库

一、numpy库

1、axis的值,最小的0代表最小的粒子的意思,数值越大越往上推。

np.array([[0, 2, 1], [4, 5, 6]]).sum(axis=0) # np最小的粒子是单个元素(逐列)。所以axis=0表示逐列,axis=1表示逐行。 # 输出 [4 7 7]。 而axis=1时,输出[ 3 15]
data_df.drop('col_2', axis=1) # df最小的粒子是一行数据。因此axis=0表示找行编号为"two",而axis=1表示找列编号。这是与np的不同。

2、在numpy类型的数据中,寻找一个恰好大于某特定整数的下标。

ndarray.searchsorted(model.random.randint(INF)) 

3、argmax 取元素的最大值的下标 参考来源
4、只有numpy才能使用numpy格式的一组下标,获取特定的一组元素。比如一个矩阵跳着挖元素。list是不可行的。
5、矩阵的拼接。concatenate。 参考来源

>>> a = np.array([[1, 2], [3, 4]])
>>> b = np.array([[5, 6]])
>>> np.concatenate((a, b), axis=0) # 上下拼接
array([[1, 2],
       [3, 4],
       [5, 6]])
>>> np.concatenate((a, b.T), axis=1) # 左右拼接
array([[1, 2, 5],
       [3, 4, 6]])

【本节下面还没有精简】

2、格式函数 astype()、dtype、type# np的astype()来调整dtype【数据格式】会更加好

b = np.array([1., 2., 3., 4.])
print b.dtype # dtype("float64")
print c = b.astype(int)# 用 astype(int) 得到整数,并且不改变数组长度 # 输出 array([1, 2, 3, 4])  长度为4
print c.dtype # 输出 dtype('int32')
b.dtype = 'int'# 直接控制dtype.如果直接改变b的dtype的话,b的长度翻倍了,这不是我们想要的(当然如果你想的话)
print b.dtype  # 输出 dtype('int32')
print b # 输出 array([0,  1072693248, 0,  1073741824, 0,  1074266112, 0,  1074790400])  长度为8

(插多一个知识点)、shape reshape 使用后者转变矩阵大小 参考来源

arr=array(range(5))  
print shape(arr) # 输出 (5,)
a=array([[1,2,3],[4,5,6]])  
reshape(a, 6)  # 输出 [1,2,3,4,5,6]
reshape(a, (3, -1)) #为指定的值将被推断出为2  。输出 [[1,2],[3,4],[5,6]
image = np.array([[1,2,3], [4,5,6]])
print image.shape(2L, 3L)
print image.reshape(-1, 6)# 行数为-1代表它自动计算,列数为6,得 [[1 2 3 4 5 6]]
Xtr, Ytr, Xte, Yte = load_CIFAR10('data/cifar10/') # 加载图像分类的数据集,此时Xtr为50000(张图片) x 32(长) x 32(宽) x 3(红绿蓝三色)
Xtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3) # Xtr_rows 变成 50000 x 3072

3、concatenate 联结不同np.array

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
print np.concatenate((a, b), axis=0)# array([[1, 2],[3, 4],[5, 6]])
print np.concatenate((a, b.T), axis=1)# array([[1, 2, 5],[3, 4, 6]])

4、计算平均值
Yte_predict、Yte 分别是一个list。

print 'accuracy: %f' % ( np.mean(Yte_predict == Yte))

5、nditer 可以逐个元素进行迭代

x =np.array([[1.0,5,2],[6,3,9]])
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
    ix = it.multi_index
    old_value = x[ix]
    print old_value# 输出:1.0 , 5.0 , 2.0 , 6.0 , 3.0 , 9.0
    it.iternext() # 下一个元素

6、randint 可以生成固定大小,固定取值范围的np数组。random 生成 [0, 1) 范围的值。

data = np.random.random((1000, 784))
labels = np.random.randint(2, size=(1000, 1))

7、计算两向量的欧式距离

dist = numpy.sqrt(numpy.sum(numpy.square(vec1 - vec2)))
dist = numpy.linalg.norm(vec1 - vec2) # 结果也是欧式距离。同上。

8、矩阵乘法。 dot才是矩阵相乘。* 没有使用到矩阵思想。你只需要记得:点积有累加的过程,叉积只有两数两数的相乘。
例一:

a = np.array([[1,4,5,7]])
b = np.array([[4],[6],[3],[0]])
print a.shape,b.shape # 输出 (1L, 4L) (4L, 1L)
print a.dot(b) # 矩阵乘法 输出(1L, 1L)的矩阵 即[[43]]
print b.dot(a) # 矩阵乘法 输出(4L, 4L)的矩阵
print a * b # 每个元素依次相乘 输出(4L, 4L)的矩阵

例二:(只有dot)

a = np.array([[1,4,7],[1,2,0]])
b = np.array([[4,1],[6,2],[3,1]])
print a.shape,b.shape # 输出 (2L, 3L) (3L, 2L)
print a.dot(b) #输出 [[49 16] [16  5]]
print b.dot(a) #输出 [[ 5 18 28] [ 8 28 42] [ 4 14 21]]

例三:(只有*)

a = np.array([[1,4],[2,0]])
b = np.array([[4,1],[6,2]])
print a * b #输出 [[ 4  4] [12  0]]

9、空。
10、dtype 可以把一字符串的list转化为浮点型,如[“1.55”,”6457”]->array([1.55, 6457])

    print (dfsd)
    coefs = np.asarray(values[1:], dtype='float32')

11、 numpy.random.choice 用于随机选样本。 参考来源
参数 replace = False 表示无放回抽样。重置的意思。参考来源
12、argsort函数:返回的是数组值从小到大的索引值

x = np.array([3, 1, 2])
np.argsort(x) #按升序排列
array([1, 2, 0])
np.argsort(-x) #按降序排列
array([0, 2, 1])

13、numpy.zeros与zeros_like的区别就是,Return a new array 是否返回新的数组,内存还是操作系统。你别管就行。 参考来源

np.zeros(5)
array([ 0.,  0.,  0.,  0.,  0.])

14、array、asarray的区别是前者可以选择是深复制,而后者限定是浅复制。参考1 参考2

arr1=np.ones((3,3))  
arr2=np.array(arr1)  
arr3=np.asarray(arr1)  
arr1[1]=2  
print 'arr1:\n',arr1  # [[ 1.  1.  1.]  [ 2.  2.  2.]  [ 1.  1.  1.]]  
print 'arr2:\n',arr2  # [[ 1.  1.  1.]  [ 1.  1.  1.]  [ 1.  1.  1.]]  深复制,不与arr1一致。
print 'arr3:\n',arr3  # [[ 1.  1.  1.]  [ 2.  2.  2.]  [ 1.  1.  1.]]  因为是浅复制,所以与arr1一致。

15、shape 如果np.array中,内部(某个维度)长度大小不一致,array.shape 将忽略该维度。 参考来源

print np.array([[3, 1, 2],[8, 9]]).shape # 输出 (2L,)
print np.array([[3, 1, 2],[8, 9, 5]]).shape # 输出 (2L, 3L)

16、mean的使用

print np.mean([1,5,3]) # 输出 3.0

17、高斯分布 参考来源

tmp = np.random.normal(loc=0.0, scale=1.0, size=None)

loc:float 此概率分布的均值(对应着整个分布的中心centre)
scale:float 此概率分布的标准差(对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高)
size:int or tuple of ints 输出的shape,默认为None,只输出一个值

18、连续array,并保存。

np.save(filename, np.ascontiguousarray(array_data))
data = np.load(filename)

二、OS库

参考来源

python文件和目录操作方法大全,推荐看网址

1、os.getcwd():得到当前工作目录,即当前Python脚本工作的目录路径。
2、os.listdir(“d:\aa”):返回指定目录下的所有文件和目录名。
3、os.chdir(“c:\qtest”):改变当前工作目录 参考来源
4、os.path.abspath(path) 返回绝对路径
5、os.path.relpath(path):返回相对路径,如..\MyFile.txt
6、os.getcwd():输出当前路径 参考来源
7、os.path.isfile(“名称”) :返回T/F,判断是否是文件还是文件夹。
8、os.path.dirname(“路径名”):调用一个该函数,返回上一层目录一次。参考来源
9、assert os.path.exists(path), path:判断是否存在路径
10、os.system(‘ls’): 调用ubuntu的shell或者win的dos,它不返回字符串的。它暂时够用了。更高级的调用终端的方法 见参考 参考1 参考2
11、os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]]) 参考1 参考2
topdown 参数:默认为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录(默认为开启)。

for root, dirs, files in os.walk(".", topdown=False):
    for name in files:
        print(os.path.join(root, name))
    for name in dirs:
        print(os.path.join(root, name))

三、chardet库:检验编码

参考来源

import chardet
chardet.detect("abc")
{'confidence': 0.98999999999999999, 'encoding': 'GB2312'}#confidence是检测精确度,encoding是编码形式

四、multiprocessing库:多线程

1、《多线程基础》参考1 参考2

如果你的代码是IO密集型,多线程可以明显提高效率。例如制作爬虫
Python的多线程是有compromise的,在任意时间只有一个Python解释器在解释Python bytecode。

如果你不知道你的代码到底算CPU密集型还是IO密集型,教你个方法:
假设你使用的是multiprocessing的Pool,是使用多进程实现了concurrency
from multiprocessing import Pool
如果把这个代码改成下面这样,就变成多线程实现concurrency
from multiprocessing.dummy import Pool
两种方式都跑一下,哪个速度快用哪个就行了。

2、多线程关闭matplotlib的窗口参考来源

3、matplotlib绘制表格参考来源


五、datetime库、time库:时间函数

1、获取当前时间

import datetime
d1 = datetime.datetime.now()
print d1

2、当前时间加上半小时。可以使用不断加1天,进行全年日期的迭代

d2 = d1 + datetime.timedelta(hours=0.5)

3、格式化字符串输出

d3 = d2.strftime('%Y-%m-%d %H:%M:%S')

4、将字符串转化为时间类型

d4 = datetime.datetime.strptime(date,'%Y-%m-%d %H:%M:%S.%f') # date为自己写的字符串

5、使用time库,输出程序运行耗时、当前日期 时间等。

import time
t1 = time.time()
print "%f" %  time.time()# 1484742867.036000 秒
print "耗时(分钟)", (time.time() - t1) / 60 
print time.localtime(time.time())# time.struct_time(tm_year=2017, tm_mon=1, tm_mday=18, tm_hour=20, tm_min=34, tm_sec=27, tm_wday=2, tm_yday=18, tm_isdst=0)
print time.asctime(time.localtime(time.time()))# Wed Jan 18 20:34:27 2017

六、random库:随机函数

1、设置固定的随机数,然后按比例划分测试集、训练集

np.random.seed(1)
ratio = 0.8
size = int(len(data)*ratio)     # 训练集长度
shuffle = range(len(data))      # 训练集索引
np.random.shuffle(shuffle)      # 随机打乱索引。函数返回值是None,它是直接对shuffle内部改变的。
train = data.iloc[shuffle[:size]]
test = data.iloc[shuffle[size:]]
print np.random.randint(100) # 随机得到一个整数。

2、另一种不是np包的随机

import random
random.seed(123456)
print random.randint(0,99) # 随机得到一个整数。
print random.uniform(10, 20)# 随机得到一个浮点数。

七、Queue库:队列

myqueue = Queue.Queue(maxsize = 10) 队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。
myqueue.put(10) 方法在队尾插入一个项目
myqueue.get() 从队头删除并返回一个项目

八、heapify库:堆排序

堆排序。堆顶是最小元素。 参考来源


九、argparse库:解析命令行

如果是想直接在代码中写参数,就用namedtuple,它既有元组的优势,也有字典的优势,它相当于是建立了一个类。参考

参考来源
argparse模块的作用是用于解析命令行参数.

import argparse
parser = argparse.ArgumentParser()
parser.add_argument()
parser.parse_args()

解释:首先导入该模块;然后创建一个解析对象;然后向该对象中添加你要关注的命令行参数和选项,每一个add_argument方法对应一个你要关注的参数或选项;最后调用parse_args()方法进行解析;解析成功之后即可使用,下面简单说明一下步骤2和3。

下面拓展一个 ConfigParser 也能解析命令行。argparse的更多内容。

1、使用argparse第三方库。(推荐使用) 参考

import argparse # 参数解析库。
parser = argparse.ArgumentParser() # 创建分析器,下面几行是设置分析器的参数有哪些。
parser.add_argument("-i", "--input", type=str, default=None, help="Input word vecs")
parser.add_argument("-l", "--lexicon", type=str, default=None, help="Lexicon file name")
parser.add_argument("-o", "--output", type=str, help="Output word vecs")
parser.add_argument("-n", "--numiter", type=int, default=10, help="Num iterations")
args = parser.parse_args() # 获取参数

wordVecs = read_word_vecs(args.input)# 获取分析器的具体设置过的参数
lexicon = read_lexicon(args.lexicon, wordVecs)
numIter = int(args.numiter)
outFileName = args.output
# 运行。retrofit.py 是上面的代码文件名。
python retrofit.py -i word_vec_file -l lexicon_file -n num_iter -o out_vec_file

拓展:argparse 还可以设置 action 参数。其中一个选项是store_true:代表着一旦有这个参数,做出动作“将其值标为True”,不需要设定具体数值。 也就是没有时,默认状态下其值为False。

2、使用ConfigParser库 参考

import ConfigParser # 配置解析库。需要多生成一份文件,作为配置文件。
class ExperimentRun:
    def __init__(self, config_filepath):
        self.config = ConfigParser.RawConfigParser() # 初始化,返回类的实例。逐行读取配置文件。
        try:
            self.config.read(config_filepath) # 开始读取配置文件。
        except:
            print "Couldn't read config file from", config_filepath
            return None

        vocabulary_filepath = self.config.get("data", "vocabulary_filepath") # get是返回字符串、getfloat是返回浮点数。
        synonym_list = self.config.get("data", "synonyms").replace("[","").replace("]", "").replace(" ", "").split(",")

        self.load_experiment_hyperparameters() # 调用下面的函数。
    def load_experiment_hyperparameters(self):
        self.hyper_k1 = self.config.getfloat("hyperparameters", "hyper_k1")

config_filepath = sys.argv[1] # 读取第2个参数,也就是执行命令的 experiment_parameters.cfg
current_experiment = ExperimentRun(config_filepath)
;TIP: 这份是配置文件。分号开头行会被注释掉的。

[data]

pretrained_vectors_filepath = word_vectors/glove.txt
;pretrained_vectors_filepath = word_vectors/paragram.txt

vocabulary_filepath = linguistic_constraints/vocabulary.txt
synonyms = [linguistic_constraints/ppdb_synonyms .txt, linguistic_constraints/wordnet_synonyms .txt]

[hyperparameters]
hyper_k1 = 0.1
# 运行代码
python counterfitting.py experiment_parameters.cfg # 后面一个是配置文件名,名字后缀是任意的。

下面这个 argparse 是我写项目时的重要参考,是精华版。可能与上面的有重复。

import argparse # 参数解析库。
parser = argparse.ArgumentParser(description='test model') # 创建一个解析器。里面的参数可以全部不设置。
parser.add_argument("-n", "--numiter", type=int, default=10, help="Num iterations")
parser.add_argument('--network_dir', type=str, help='the network dir')
parser.add_argument('--test', action='store_true', help='test network')

args = parser.parse_args()  # 调用函数,进行解析参数。
numIter = args.numiter # 获取解析器里面的参数

# bash使用下面语句进行输入参数
python train_model.py -n 56 --enetwork_dir sdf --test

ArgumentParser.add_argument(name or flags…[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])
注意点:
(1)一个参数的别名可以多个。没有-符号开头的参数是位置参数,直接按位置对应输入,调用时不能写参数名字。而有-符号,调用时就需要写参数名字。
(2)action的意思是,该参数是动作参数。不能输入数值。如上面的例子,只要调用是有–test,就会认为test变量是True。

十、gzip库:压缩或解压文件

参考来源
解压gzip文件示例:

import gzip
f = gzip.open('file.txt.gz', 'rb')
file_content = f.read()
f.close()

创建gzip文件:

import gzip
content = "Lots of content here"
f = gzip.open('file.txt.gz', 'wb')
f.write(content)
f.close()

gzip压缩现有文件:

import gzip
f_in = open('file.txt', 'rb')
f_out = gzip.open('file.txt.gz', 'wb')
f_out.writelines(f_in)
f_out.close()
f_in.close()

使用追加的模式,可以实现创建、追加两种功能。

f = open("filename.txt","a")
f.write("GGG")
f.close()

十一、re库:正则匹配

参考1 参考2
sub 部分替代
\W 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。 ^ 这是否定 非的意思。 _ 是下划线字符,普通用的。

1、split 原字符串对象的split不支持多个分隔符,所以要用正则的split
re.split(r”[0-9]”,one_str)
注:使用括号匹配(即捕获组)的split,如(0-9) 而如(?:…)就取消括号是捕获组。捕获组不会删除分隔符,捕获的内容会保留下来。

\d 可以匹配一个数字,\w 可以匹配一个字母或数字

[\u4e00-\u9fa5]是匹配一个汉字的意思。在范围前面加个^ 意思是取反,而不是限制开头。 + 意思是连在一起的会当做一个。

p = re.compile(ur'[^\u4e00-\u9fa5]+')#先进行编译,然后得到的p就能在很多地方使用了。 r 是为了避免不用\\ 表示一个\。
text = p.sub(u' ', text).strip()

text = re.split(ur'!|,|。|?|;', text) # 遇到这些东西都会被舍弃而切分成一个个地小段

[]的作用 :[]内的字符可以以任意次序出现。
[]后有了+,[]内的字符可以取任意多个。于是[]内的字符可以以任意次序出现任意多次,直到遇到第一个非[]内的字符。
如[AB]+ 既可以匹配AAABBB又可以匹配BBBAAA BABAAABA等,不是一定要A….B….的次序。
2、加?变非贪婪模式。
例如:正则表达式”ab*”如果用于查找”abbbc”,将找到”abbb”。而如果使用非贪婪的数量词”ab*?”,将找到”a”。
3、使用r处理反斜杠。
这样你才能用如\w去匹配,不然你要\w。
4、re.compile(strPattern[, flag]) # strPattern是匹配模式串。flag是可选的模式,如re.X是详细模式。以下两个等价

a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)
a = re.compile(r"\d+\.\d*")

5、match与search都是为了返回一个match对象,match只能固定位置开始,而search如果当前位置开始匹配不成功,它会找下一个下标。
match对象:里面有分组,其实就是切分后的模式串。当然还有其他子函数。
例子:

pattern = re.compile(r'hello')
match = pattern.match('hello world!')
if match:
    print match.group() # 输出 hello

例子2:此例使用match()无法成功匹配

pattern = re.compile(r'world') 
match = pattern.search('hello world!') 
if match: 
    print match.group()  # 输出 world

6、findall才能返回全部匹配的子串。

p = re.compile(r'\d+')
print p.findall('one1two2three3four4') # 输出 ['1', '2', '3', '4']

7、sub或subn进行替换字符串。


十二、yaml库

直观的能够被电脑识别的的数据序列化格式,容易被人类阅读。它会比xml、josn更好。
假设已有一个.yaml格式的文件,就能load进来了。

one_dict = yaml.load(file('one_file.yaml')) # 得到dict格式的。也就是一个参数配置文档。

十三、logging库

调节适合自己的 debug输出方式 。通过logging.basicConfig函数对日志的输出格式及方式做相关配置
可以实现:既然控制台上输出,或者只导出到日志中。 参考1 参考2 参考3

仅输出到日志中的例子:

import logging
logging.basicConfig(level=logging.DEBUG,# 设置可输出的等级
                    filename='./log/log.txt',
                    filemode='w',
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
logging.debug('this is a loggging debug message')# 最低等级
logging.info('this is a loggging info message')
logging.warning('this is loggging a warning message')
logging.error('this is an loggging error message')
logging.critical('this is a loggging critical message')# 最高等级

各个模块共用一个log文件。无需把logger实例在中传递。

logging.getLogger([name]):返回一个logger实例,如果没有指定name,返回root logger。只要name相同,返回的logger实例都是同一个而且只有一个。只要知道name,就能得到同一个logger实例。

常用的使用方法:

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
head = '%(asctime)-15s Node[' + str(train_params['kvstore'].rank) + '] %(message)s'
formatter = logging.Formatter(head)
console_handler = logging.StreamHandler() # 设置处理器。handler对象负责发送相关的信息到指定目的地。如有些Handler可以把信息输出到控制台,等等。
console_handler.setFormatter(formatter) # 设置输出格式。
logger.addHandler(console_handler)

一次迭代中,新建多个logger

# 注:不要直接使用logging库来直接info()写,而是需要调用logging.Logger()新建后,再用info()写内容。

global logger  # 不同函数之间调用才需要用的。
log_file = logging.FileHandler(filename='./log/model_'+str(j+1)+"_DATA_"+dataset_dir_paths[i].split("/")[3], mode='a', encoding='utf-8')
fmt = logging.Formatter(fmt='%(asctime)s -  %(message)s')
log_file.setFormatter(fmt)

logger = logging.Logger(name='this is logger', level=logging.INFO)
logger.addHandler(log_file)

logger.info("这是一处输出。")

十四、sys库

1、获取当前路径

print __file__ # 输出 D:/aa/untitled6/main.py
print sys.argv[0] #网上说,比__file__更稳定些。 # 输出D:/aa/untitled6/main.py
print os.path.dirname(__file__) # dirname返回文件名前面的目录名 # 输出D:/aa/untitled6

2、sys.stdout 重定向输出
重定向的意义就是输入或者输出不是控制台,而是从文件。初始时 sys.stdout指向控制台。参考来源
使用本方法后,控制台打印的东西将会是空值,除非你自己写一个buff(见总启)就能够既在控制台有东西输出,又在文件中有输出。
此外也可以选择性地,在控制台输出一部分,在文档中输出一部分,我觉得这个才是你最需要的。(保留下一stdout的原指向,然后恢复就能输出到控制台了,见总启)。

3、增加环境变量(即引用模块的路径)参考来源
当我们导入一个模块时:import xxx,默认情况下python解析器会搜索当前目录、已安装的内置模块和第三方模块,搜索路径存放在sys模块的path中。

但是从实践中发现,只能import 才有用,如果想直接 word2vec.load(“文件名称”) 依旧要当前工作环境下才可行。

>>> print(sys.path) # 输出所有会被搜索的路径名称列表。 
>>> sys.path.append("引用模块的路径")  # 增加新的作为环境变量的作用。程序运行结束后失效。

4、sys.argv 获取运行python文件的时候命令行参数,返回一个list。
例如,第一个是py文件,后面的是输入py文件的参数:

['/media/private/fg_ConvNet_s0.5_16_24_48/../train_model.py', '/media/private/fg_ConvNet_s0.5_16_24_48']

十五、pprint模块

提供了打印出任何Python数据结构类和方法,输出时比较整齐。 参考来源

data = [(1,{'a':'A','b':'B','c':'C','d':'D'}),
        (2,{'e':'E','f':'F','g':'G','h':'H',
            'i':'I','j':'J','k':'K','l':'L'
            }),
        ]
from pprint import pprint
print 'PRINT:'
print data
print 
print 'PPRINT:'
pprint(data)

输出:

PRINT:
[(1, {'a': 'A', 'c': 'C', 'b': 'B', 'd': 'D'}), (2, {'e': 'E', 'g': 'G', 'f': 'F', 'i': 'I', 'h': 'H', 'k': 'K', 'j': 'J', 'l': 'L'})]
PPRINT:
[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
 (2,
  {'e': 'E',
   'f': 'F',
   'k': 'K',
   'l': 'L'})]

十六、自己写的模块(即 .py文件) 参考

1、假如在同一项目主目录下,假设名为A.py的文件需要调用B.py文件内的C(x,y)函数则只需

# 方法1
import B 
if __name__ == "__main__":
    B.C(x,y)

# 方法2
from B import C 
if __name__ == "__main__":
    C(x,y)

2、假如在同一项目主目录下,假设有 E:/myproject/son_folder/A.py 的文件只需

import son_folder.A # 因为你当前运行环境就在E:/myproject 下,所以不需要写这一块,而且也不能写。

3、若A.py和B.py位于不同的目录下,可以用以下方法(假设B.py位于D盘的根目录下)

引用所在路径

import sys
sys.path.append('D:/')
import B
if __name__=="__main__":
    print B.pr(x,y)

十七、virtualenv库-虚拟环境

1、安装库并且虚拟出环境 参考
-m 意思是将库中的python模块用作脚本去运行。参考

python3 -m pip3 install virtualenv # 安装库
virtualenv --no-site-packages venv # venv 是虚拟环境的名字。所有第三方的包都会被pip安装到site-packages目录下,所以no-site-packages 的意思是该目录下的不要复制过来的,想要一个干净的环境。
source venv/bin/activate # source 是mac系统运行脚本的命令,win直接用脚本名字运行。active在win下是放在venv/Scripts文件下
pip install jinja2 # 在该虚拟环境下安装某些库。
deactivate # 推出虚拟环境。

2、导出、导入环境。参考 参考2

pip freeze --all > f:\requirements.txt # 1、>是导出文件的意思,缺了就会在显示屏中打印。参考中有一个tee的linux命令,它与>一样是输出到文件用的。2、--all 是全体导出的意思,缺了就会少几个包,如pip , wheel , setuptools 等包,是自带的而无法(un)install的。3、f:\ 是win系统的f盘路径。
pip install -r f:\requirements.txt # -r 是从文件中加载需要安装库的名字。

十八、itertools库

1、groupby 在统计区间频数的应用 参考

from itertools import groupby
lst= [2648, 2648, 2648, 63370, 63370, 425, 425, 120]
for k, g in groupby(sorted(lst), key=lambda x: x//50):
    print('{}-{}: {}'.format(k*50, (k+1)*50-1, len(list(g))))

十九、collections库

(1)namedtuple
参考
常用在参数定义中,它既有元组的优势,也有字典的优势,它相当于是建立了一个类。

    from collections import namedtuple
    args = namedtuple('args', ['video_path', 'output_dir', 'step', 'begin_frame'])
    return args(
        video_path='/home/like_videos/video20181202',
        output_dir='/home//like_videos/video20181202-frames',
        step=1,
        begin_frame=0
    )

二十、importlib库:导入其它模块文件

下面是可能会使用到的功能:

# ===== 导入模块、以及判断模块是否有某属性 ======
sys.path.insert(0, args.network_dir)  # 临时改变系统变量,增加运行的主路径进去,这样才方便导入模块。 '/media/xxxxxxx'
train_info = importlib.import_module('train_info') # train_info是一个py脚本。

print(hasattr(train_info, 'gpus')) # 返回True或者False,判断是否有某变量,该变量需要是全局变量。

Part D. 按功能分

一、复制文件

参考1 参考2
os.system (“cp %s %s” % (filename1, filename2)) # 调用系统终端命令。
shutil.copyfile( src, dst) 从源src复制到dst中去。这个是很慢。建议调用系统终端命令。

二、下载第三方库

1、–user 参数可以不适用管理员权限,而下载库到用户目录下。 参考1
python -m pip install 包名 --user

三、python命令行参数

参考
1、 -u 可以不缓存,print的时候直接打印。否则等缓冲区满了才会打印数据。
2、-V 参数,或者–version,输出Python的版本
python -V

猜你喜欢

转载自blog.csdn.net/qimiejia5584/article/details/78525496