python list转换成array_一文掌握Python【不定期更新】

目录

一、Numpy

1 基本操作

2 随机数

3 打乱训练数据

4 得到元素的最值

5 拼接数组

6 得到函数的信息

7 得到累乘即各项相乘的结果

8 判断一个数是否在数组中

9 数组的变换

10 排序

11 元素的筛选

12.保存文件/打开文件

13.限制范围

二、PIL

1.安装

2.PIL与Numpy的互相转化

3.获取Image信息

4.打开/显示/保存图像

5.在图像上进行绘制

6.一些Image里面的操作

7.膨胀和腐蚀

三、OpenCV

1.安装

2.打开/显示/保存图像

3.图像尺寸变换

4.绘制文字

5.绘制半透明红色矩形框

6.底层依赖Numpy的一些操作

7.实现图像的JPEG质量等级压缩

8.创建高斯模糊图像

9.高斯模糊处理

10.一些报错的处理

四、变量、对象、函数

1.可变对象与多进程

2.动态创建变量

3.获取对象的所有属性和方法

4.获取Python占用空间的大小

5.判断变量类型

6.文档字符串

7.*args与**kwargs

8.pass

9.slicing

10.字符串相关

11.序列解包

12.链式赋值

13.增量赋值

14.断言assert

15.with

16.list和dict查找效率比较

17.取整函数的比较

18.三元表达式(三目运算符)

19.enumerate函数

20.zip函数

21.将list转为tuple

22.列表推导式、字典推导式、集合推导式

23.lambda及函数式编程

24.读写文档

25.exec语句与eval函数

26.repr函数

27.进制等之间的转换
28.any()函数

29.生成器

五、Python库

1.安装

2.单元测试unittest

3.唯一ID生成库UUID

4.pickle

5.Flask

6.os

7.读写excel库xlrd

8.platform

9.sys

10.XML解析库xml.etree.ElementTree

11.matplotlib

12.PyTorch

13.FontTool

14.logging

15.base64

16.数据读写库json与pickle

17.requests

18.CharlesShang/TFFRCNN

19.attention_ocr

六、类

1.基本概念

2.基本应用

3.元类metaclass

4.装饰器

5.abc

6.多态

7.__str__

七、Python语言

1.什么是Python?使用Python有什么好处?

2.PEP8 Python编程规范

3.管理内存

4.静态分析

5.Python的编译机制

6.内存泄露问题

7.Python 2.x和Python 3.x的区别

8.单下划线和双下划线

9.GIL线程全局锁

10.sys.stdout

11.Python3的bytes/str之别

12.模块和包

13.异常

14.猴子补丁

15.单例模式

16.字典的内部实现

17.内置算法的复杂度

18.__all__的作用

19.面向切面编程

八、深度学习相关


一、Numpy

1 基本操作

大部分简单的操作都位于Quickstart tutorial(有一篇中文的文章Python Numpy 数组的初始化和基本操作不错),这里列举几个常用的操作:

Numpy数组类是ndarray,也可以叫array。array的属性经常用到的有两个:

ndarray.shape:求维度大小;

ndarray.dtype:数组元素类型,比如构建RGB图要用到的np.uint8,在构建数组时如果指定效果会更佳,后期也可以使用astype()方法转换数据格式,比如:

>>> a = np.array([1, 2], dtype=np.float64)
>>> b = a.astype(np.uint8)
>>> b
array([1, 2], dtype=uint8)

生成array:

>>> a = np.array(1,2,3,4)    # WRONG
>>> a = np.array([1,2,3,4])  # RIGHT

这个我的理解是需要先生成一个list,即[1,2,3,4],在将该list转为array,我也经常用np.array(list)将列表转为array:

a = [1,2,3,4]
b = np.array(a)

二维或高维list转换成数据要注意数组不匹配的问题,即二维list每行的列数不完全相等,这样肯定是无法转换的。

如果想通过矩阵维度构建数据可使用np.ones()和np.zeros()两个函数,结合之后讲过的ndarray的属性shape可构建一个与原数组相同维度的数组:

b = np.zeros(a.shape)

生成纯白图像需要指定元素类型为uint8类型,因此需要特别指定元素类型:

newImg = np.ones(img.shape, np.uint8) * 255

如果生成纯黑图像可以这么做:

newImg = np.zeros(img.shape, np.uint8)

还有一些基本操作,比如np.exp()、np.add()等,这里不一一赘述。

浅复制与深复制。Numpy里面":"的作用与list是不同的,这里做一个实验,对list:

>>> a = [1, 2, 3]
>>> b = a[:]
>>> a is b
False
>>> b[1] = 10
>>> a
[1, 2, 3]

可以看出这里是深复制。

对Numpy:

c = np.array([1, 2, 3])
>>> d = c[:]
>>> c is d
False
>>> d.base is c
True
>>> d[1] = 10
>>> c
array([ 1, 10,  3])

可以看出这里只是浅复制,需要特别注意,深复制需要使用copy函数:

>>> e = c.copy()
>>> e is a
False
>>> e.base is a
False
>>> e[2] = 5
>>> c
array([ 1, 10,  3])

2 随机数

官方文档位于Random sampling。

基本用法为:

print (np.random.random())

如果要生成随机整数,可使用numpy.random.randint函数:

print (np.random.randint(1, 2))

如果要生成标准正太分布的随机矩阵,可使用numpy.random.randn函数:

print (np.random.randn())

文章也指明了正太分布与标准正太分布的关系,调用也可以使用这个关系:

bfc49eaadff58baf3d6fa0a5619758c3.png

设置种子,减少随机性的影响可参考Michael:深度学习代码复现之减少随机性的影响。

3 打乱训练数据

参考numpy.random.shuffle,TensorFlow里也有这个函数tf/data/Dataset,没怎么用过,暂且记录下。

另外还有一个函数numpy.random.permutation,与numpy.random.shuffle的作用相当,按照【Python】Numpy 中的 shuffle VS permutation的说法,numpy.random.permutation内部调用的就是numpy.random.shuffle。

4 得到元素的最值

得到元素最值很简单,直接使用numpy.amax即可。

得到元素最值所在的下标参考numpy.argmax

例如:

>>>a
array([[0, 1, 9, 3],[4, 5, 2, 8],[8, 2, 5, 1],[9, 2, 5, 5]])
>>>idx = np.argmax(a, axis=1)
>>>idx
array([2, 3, 0, 0])

可以看出,在数组a中,第0行中最大值的下标为2,第1行中最大值的下标为3,与结果符合。

使用idx可以得到每行的最大值:

>>>a[xrange(a.shape[0]), idx]
array([9, 8, 8, 9])

这与numpy.amax是一致的:

>>> np.amax(a, axis=1)
array([9, 8, 8, 9])

5 拼接数组

numpy.column_stack等函数只提供一维或二维数组的拼接,对多维数组或需要指定维度的情况Quickstart tutorial也推荐使用numpy.concatenate,而且这个函数可以一次完成多个数组的拼接,非常棒棒了。

6 得到函数的信息

一般可以使用help(np.max)来调用np.max的信息,在使用help(np.maximum)的过程中意外发现numpy有些函数是用C语言编写,所以Python的help()函数有时候得不到正确的函数信息,官方推荐使用下列指令来得到信息:

np.info(np.maximum)

7 得到累乘即各项相乘的结果

参考【python学习笔记】23:numpy的add和multiply:

>>>np.multiply.accumulate([1,2,3,4])[-1]
24

或者使用numpy.prod函数:

>>> np.prod([1, 2, 3, 4])
24

8 判断一个数是否在数组中

>>>a = np.arange(10).reshape((2, 5))
>>>9 in a
True

9 数组的变换

numpy.reshape非常常用,这里再介绍一个非常好用的函数numpy.swapaxes:

Interchange two axes of an array.
>>>np.swapaxes(a, axis1, axis2)

一个魔改方法是进行矩阵的转置:

>>>x = np.array([[1,2,3]])
>>>np.swapaxes(x, 0, 1)
array([[1],[2],[3]])

增加维度可以使用numpy.expand_dims:

>>> x = np.array([1,2])
>>> x.shape
(2,)
>>> y = np.expand_dims(x, axis=0)
>>> y
array([[1, 2]])
>>> y.shape
(1, 2)

同样可以删掉特定的维度,这个可以参考请问numpy中怎么删掉值为1的维度?:

>>> x = np.array([[[0], [1], [2]]])
>>> x.shape
(1, 3, 1)
>>> np.squeeze(x).shape
(3,)
>>> np.squeeze(x, axis=(2,)).shape
(1, 3)

10 排序

两个函数,numpy.sort和numpy.argsort。

11 元素的筛选

可以过滤特定的元素:

>>>x = np.random.rand(6)
>>>x
array([0.28071468, 0.59360709, 0.87036219, 0.93709868, 0.4646627 ,0.27824566])
>>>x[x>0.5]
>>>x
array([0.59360709, 0.87036219, 0.93709868])

可以赋值给特定的元素:

>>> x = np.random.rand(6)
>>> x
array([0.40602006, 0.58211841, 0.63038674, 0.733807  , 0.8008934 ,0.63986259])
>>> x[x>0.5] = 1
>>> x
array([0.40602006, 1.        , 1.        , 1.        , 1.        ,1.        ])

参考Numpy where function multiple conditions,也可以使用多个条件:

>>> x = np.random.rand(6)
>>> x
array([0.45593443, 0.61549711, 0.88832625, 0.81612841, 0.944428  ,0.55101566])
>>> x[(x>0.6) & (x<0.9)] = 0.7
>>> x
array([0.45593443, 0.7       , 0.7       , 0.7       , 0.944428  ,0.55101566])

可以使用numpy.argwhere函数得到特定元素的下标:

>>>a
array([[0, 1, 9, 3],[4, 5, 2, 8],[8, 2, 5, 1],[9, 2, 5, 5]])
>>>numpy.argwhere(a==9)
array([[0, 2],[3, 0]])

还有一个很简单的函数numpy.any,作用,作用是排查数组中是否有真值。

12.保存文件/打开文件

参考numpy.save,保存为npy文件,保存神经网络参数会经常用到这个,好处是不用管所用深度学习框架的模型文件,比如CharlesShang/TFFRCNN里面VGG的预训练模型就保存在numpy文件中,与TensorFlow模型文件.ckpt的转化可参考Michael:[代码分享]将ckpt模型文件转成npy模型文件。

将Numpy数据保存为图像数据可参考将Numpy数组保存为图像 - 纯净的天空,里面有很多硬核的方法。

13.限制范围

参考numpy.clip - NumPy v1.16 Manual

>>> import numpy as np
>>> a = np.arange(10)
>>> aClip = np.clip(a, 1, 8)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> aClip
array([1, 1, 2, 3, 4, 5, 6, 7, 8, 8])

一些不错的文章:

numpy教程:排序、搜索和计数


二、PIL

1.安装

参考Installing PIL with pip,PIL基本已经消失了,可以使用Pillow:

pip install Pillow

2.PIL与Numpy的互相转化

PIL转成Numpy:

参考Python(5) Image和Ndarray互相转换:

image = np.array(imageArray)

里面也提到了numpy.asarray函数与numpy.array的区别,区别在于前者是浅复制,后者是深复制:

>>> a = np.array([1, 2])
>>> b = np.array(a)
>>> b is a
False
>>> c = np.asarray(a)
>>> c is a
True

不过要注意这里只有当传入的参数是array类型的时候,numpy.asarray函数才是浅复制,要不然也是深复制的:

No copy is performed if the input is already an ndarray with matching dtype and order.

这里是实验部分:

>>> b
<PIL.Image.Image image mode=RGB size=200x100 at 0x7FD7993BF630>
>>> c = np.array(b)
>>> c is b
False
>>> d = np.asarray(b)
>>> d is b
False

参考PIL中的Image和numpy中的数组array相互转换 - 龚细军 - 博客园,如果出现read-only错误,并不是转换的错误,一般是你读取的图片的时候,默认选择的是"r","rb"模式有关。

修正的办法是手动修改图片的读取状态:

img.flags.writeable = True  # 将数组改为读写模式

Numpy转PIL:

参考PIL.Image.fromarray,我写好的代码是:

imageArray = Image.fromarray(np.uint8(image), mode="RGB")

3.获取Image信息

Image的属性可参考Image.html#attributes,有format, size等信息。

4.打开/显示/保存图像

参考用python简单处理图片(1):打开显示保存图像 - denny402 - 博客园:

from PIL import Image
img = Image.open(‘dog.png’)
img.show()	# 使用操作系统自带的图片浏览器来显示图像
img.save(‘dog.jpg’)	# 保存图像

5.在图像上进行绘制

可参考Pillow (PIL Fork) 3.1.2 documentation,里面有矩形、直线等的绘制方法。

这里举个矩形的例子:

draw.rectangle([(0,300),(100,400)], fill=(0,0,255))

绘制的左上角为(0, 300),右下角为(100, 400),原点位于左上角,x轴水平向右,y轴水平向下。

也可以绘制字,可能是字体绘制的原因,并不是字所有的值都与传进的RGB值相同,边缘会过渡至背景,这里是实验:

from PIL import Image, ImageDraw, ImageFont
>>> img = Image.new("RGB", (200, 200), (0, 0, 0))
>>> font = ImageFont.truetype("arialuni.ttf", 40)
>>> d = ImageDraw.Draw(img)
>>> d.text((10, 10), "hello", font=font, fill=(255, 255, 255, 255))
>>> img.show()

图片看上去很好的:

4a830c91f574afbed026f28afce932cf.png

但是打印具体的值还是能发现一些问题的:

>>> import numpy as np
>>> e = np.array(img)
>>> e[50, :, :]
array([[  0,   0,   0],...,[  0,   0,   0],[ 84,  84,  84],[255, 255, 255],[255, 255, 255],[255, 255, 255],[ 48,  48,  48],[  0,   0,   0],...,[  0,   0,   0]], dtype=uint8)

从RGB过渡到灰度图像等应用场景,如果考虑边缘连续光滑的话可以考虑下这个问题。

6.一些Image里面的操作

缩放:参考PIL.Image.Image.resize,注意差值方法,与内存占用相关。

粘贴:参考PIL.Image.Image.paste,如果想复制RGBA图片,可以使用mask参数。

获取单个点的像素:参考PIL.Image.getpixel。

7.膨胀和腐蚀

OpenCV的函数对膨胀和腐蚀更友好。

参考Equivalents to OpenCV's erode and dilate in PIL?,里面也有PIL的方法:

dilation_img = src_img.filter(ImageFilter.MaxFilter(3))
erosion_img = src_img.filter(ImageFilter.MinFilter(3))

一些比较好的文章:Python图像处理库PIL中图像格式转换(一)


三、OpenCV

1.安装

使用pip安装:

参考Ubuntu下安装Opencv(cv2),首先搜索可用的包:

pip search opencv

从中选择合适的,我一般使用:

pip install opencv-python

使用conda安装:

conda install opencv

2.打开/显示/保存图像

官方文档在Getting Started with Images,中文写的比较好的博客在openCV-Python笔记一:图像的读取、显示和保存。

读取:

img = cv2.imread('1.jpg',cv2.IMREAD_GRAYSCALE)

显示:

cv2.imshow(‘image’, img)
cv2.waitKey()
cv2.destroyAllWindows()

保存:

cv2.imwrite('1.png',img)

3.图像尺寸变换

可参考Michael:[OpenCV]遇到的一些坑(汇总贴,不经常更新)

4.绘制文字

参考puttext,遗憾是不能使用中文。在实际使用之前可以使用gettextsize函数获取待绘制文字框的尺寸。

其它的如绘制矩形之类的可以参考同一页面下的rectangle等函数,在此不再赘述。

5.绘制半透明红色矩形框

参考Michael:[OpenCV]增加半透明矩形

6.底层依赖Numpy的一些操作

BGR格式转为RGB格式:

rgb = bgr[...,::-1]

沿x轴翻转:

imgFlip = img[::-1, :, :]

也可以使用官方函数flip。

旋转90度,参考Python Opencv旋转图片90度:

img90 = np.rot90(img)

7.实现图像的JPEG质量等级压缩

参考opencv实现图像的JPEG质量等级压缩::

img_encode = cv2.imencode('.jpeg', self.imageArray, [cv2.IMWRITE_JPEG_QUALITY, 20])[1]
self.imageArray = cv2.imdecode(img_encode, cv2.IMREAD_COLOR)

8.创建高斯模糊图像

noise = np.zeros((h, w, c))
cv2.randn(noise, np.ones(3)*0, np.ones(3)*50)
_print (noise)
[[[-8.01547384e-08  7.90675282e+00 -3.50463986e+01][-2.14297995e+01  6.19371057e+01 -1.39004111e+01]...]
>>>_print (noise.astype(np.uint8))
[[[  0   7 221][235  61 243]...]

改成uinit8的原因在于OpenCV的元素格式只能是np.uint8,另外,这里负数也会换算成对应的uint8值的,以第一行三列为例,float数为-3.50463986e+01,换算成 np.uint8为(256-3.50463986e+01)=221。

9.高斯模糊处理

模糊函数文档位于Smoothing Images,一篇不错的博客Python+OpenCV实现图像高斯模糊。

高斯模糊:

arr = cv2.GaussianBlur(arr, (radius, radius), 0)

均值模糊:

arr = cv2.blur(arr, (radius, radius))

高斯模糊会占用过多的CPU资源,最好换成普通的Blur。

10.一些报错的处理

/io/opencv/modules/imgproc/src/resize.cpp:3662: error: (-215:Assertion failed) func != 0 in function 'resize'n

参考cv2.error: modulesimgprocsrcimgwarp.cpp:2114: error: (-215) func != 0 in function cv::resize,原因在于Array元素的精度太高,转换成np.uint8即可:

imgArr = np.uint8(np.array(imgArr))

四、变量、对象、函数

1.可变对象与多进程

参考Michael:[Python]可变对象与多进程

讲述了在多进程中需要利用共享数据类型进行通信,期间讲解了可变对象与不可变对象、传参、命名空间等知识。

2.动态创建变量

如果需要创建100个变量,int1,int2,...int100,那么就可以利用locals()创建:

>>> for i in range(100):
...     locals()["int%s" % i] = i
... 
>>> int7
7

3.获取对象的所有属性和方法

对于一个变量,参考python 获得对象的所有属性和方法,可通过如下方法:

>>> a = [1, 2, 3]
>>> dir(a)
['__add__',..., 'reverse', 'sort']

对于类,如果还想获得属相的值,可参考Python打印对象的全部属性-来玩魔王的咚!-51CTO博客:

>>> class Teacher(object):
...     display = "教师"  # 有公有属性
...     def __init__(self,name,age,course,salary):
...         self.name = name
...         self.age = age
...         self.course = course
...         self.__salary = salary  # 也有私有属性
>>> 
>>> 
>>> t1 = Teacher("Jerry",36,"Python",20000)
>>> 
>>> dir(t1)
['_Teacher__salary', '__class__',..., '__weakref__', 'age', 'course', 'display', 'name']
>>> 
>>> t1.__dict__
{'name': 'Jerry', 'age': 36, 'course': 'Python', '_Teacher__salary': 20000}

4.获取Python占用空间的大小

参考How do I determine the size of an object in Python?,并不是很好用:

>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
24

5.判断变量类型

参考python判断变量类型时,为什么不推荐使用type()方法

>>>a = 111
>>>isinstance(a, int)
>>>True

6.文档字符串

即docstring,作用是为函数、模块和类注释生成文档。可以这么写:

>>> def square(x):
...     'Calculates the square of the number x.'
...     return x*x

通过如下方式访问:

>>> square.__doc__
'Calculates the square of the number x.'

7.*args与**kwargs

*args:往函数传入任意个参数,或者想以列表或元组的形式传参;

**kwargs:往函数传入任意个关键词参数,或者想以字典的值作为关键词参数;

两标识符是约定俗称的取法,也可以使用*a和**b代替。

举例:

>>> def print_params(x, y, z=3, *pospar, **keypar):
...     print (x, y, z)
...     print (pospar)
...     print (keypar)
... 
>>> 
>>> print_params(1, 2, 3, 4, 5, 6, foo=1, bar=2)
1 2 3
(4, 5, 6)
{'foo': 1, 'bar': 2}

参数收集的逆过程:

>>> def add(x, y):
...     return x + y
... 
>>> params = (1, 2)
>>> add(*params)
3

关键字参数是一类使用参数名提供的参数,主要作用在于可以明确每个参数的作用,每个参数的含义变得更加清晰,就算弄乱了参数的顺序,对于程序的功能也没有任何影响,即可以回避位置问题,如:

>>> def hello(greeting='hello', name='world'):
...     print ("%s, %s!" % (greeting, name))
... 
>>> hello(greeting="hello", name="world")
hello, world!
>>> hello(name="world", greeting="hello")
hello, world!

8.pass

pass是一个在python中不会被执行的语句,在复杂语句中,如果一个地方需要暂时被留白,它常常被用于占位符。

9.slicing

slicing是一种在有序的对象类型中(数组,元组,字符串)节选某一段的语法。

Python中的索引可以是正也可以是负。如果是正索引,0是序列中的第一个索引,1是第二个索引,如果是负索引,-1是最后一个索引,-2是倒数第二个索引。

10.字符串相关

翻转字符串:参考Reverse a string in Python

>>> 'hello world'[::-1]
'dlrow olleh'

将数字转换成字符串:使用自带函数str()将一个数字转换成字符串。如果你想要八进制或者十六进制,可以用oct()或hex()。

大小写转换:参考Python 字符串大小写转换 | 菜鸟教程

>>>str = "www.runoob.com"
>>>print(str.upper())          # 把所有字符中的小写字母转换成大写字母
WWW.RUNOOB.COM
>>>print(str.lower())          # 把所有字符中的大写字母转换成小写字母
www.runoob.com
>>>print(str.capitalize())     # 把第一个字母转化为大写字母,其余小写
Www.runoob.com
>>>print(str.title())          # 把每个单词的第一个字母转化为大写,其余小写
Www.Runoob.Com

ASCII码与字符相互转换:参考Python ASCII码与字符相互转换

>>>c = ‘a’
# 打印ASCII码
>>>print (ord(c))	
97>>>a = 97
# 对应的字符
>>>print (chr(a))
a

对于非ASCII码,返回的是Unicode码(实际上Unicode兼容了ASCII码)。

去除字符串首尾的字符:

参考https://blog.csdn.net/qq_39208536/article/details/79267234:

>>> str = "0000000Runoob0000"
>>> print (str.strip('0000000'))
Runoob

字符串尾部的"0000"其实是不希望截掉的,所以建议使用如下方法:

>>> print (str.replace('0000000', ''))
Runoob0000

判断是否为数字或字母:

参考https://blog.csdn.net/a1007720052/article/details/81365976

>>>str.isalnum()	# 所有字符都是数字或者字母(这个慎用,中文也会判断为字母)
>>>str.isalpha()	# 所有字符都是字母(这个慎用,中文也会判断为字母)
>>>str.isdigit()	# 所有字符都是数字
>>>str.isspace()	# 所有字符都是空白字符、t、n、r

官方方法还是慎用。

最好的判断数字的方法是使用正则表达式:

import re
def is_number(num):pattern = re.compile(r'^[-+]?[-0-9]d*.d*|[-+]?.?[0-9]d*$')result = pattern.match(num)if result:return Trueelse:return False>>>: is_number('1')
True>>>: is_number('111')
True>>>: is_number('11.1')
True>>>: is_number('-11.1')
True>>>: is_number('inf')
False>>>: is_number('-inf')
False

自动给数字前面补"0":

>>>n = 123
>>>s = "%05d" % n
>>>assert s == "00123"

格式化字符串:参考Python格式化字符串 - 田小计划 - 博客园

格式化操作符:%c %r %s等

格式化操作符辅助符:"-"用作左对齐,"m.n"用作“m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话)”等

字符串模板、字符串內建函数format()等也不错。

排序:参考How to sort the letters in a string alphabetically in Python:

''.join(sorted(a))

保留有效数字:参考在python中利用Formatter保留有效数字:

>>> format(12.456789, '.3g')
'12.5'

11.序列解包

序列解包(sequence unpacking)或递归解包:将多个值的序列解开,然后放到变量的序列中。它允许函数返回一个以上的值并打包成元组,然后通过一个赋值语句很容易进行访问。所解包的序列中的元素数量必须和放置在赋值符号=左边的变量数量完全一致,否则Python会在赋值时引发异常。如:

>>>x, y, z = 1, 2, 3
>>>print x, y, z
1 2 3
>>>score = {‘name’:’Robin’, ‘girlfriend’: “Marion’}
>>>key, value = score.popitem()
>>>key
‘girlfriend’
>>>value
‘Marion’

12.链式赋值

链式赋值(chained assignment)是将同一个值赋给多个变量的捷径。如:

>>>x = y = somefunction()

和下面语句的效果是一样的:

>>>y = somefunction()
>>>x = y

13.增量赋值

将表达式运算符(如=、-)放置在赋值运算符=的左边。如:

>>>x = 2
>>>x += 1
>>>x
3

14.断言assert

如果要确保程序中的某个条件一定为真才能让程序正常工作的话,assert语句就有用了,它可以在程序中置入检查点。

条件后可以添加字符串,用来解释断言:

>>>age = -1
>>>assert 0 < age < 100, ‘The age must be realistic’
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AssertionError: The age must be realistic

15.with

参考浅谈 Python 的 with 语句及理解Python的With语句

with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

with语句的语法格式为:

with context_expression [as target(s)]:with-body

16.list和dict查找效率比较

参考python中in在list和dict中查找效率比较

list的查找效率远远低于dict的效率,原因为:

Python中list对象的存储结构采用的是线性表,因此其查询复杂度为O(n),而dict对象的存储结构采用的是散列表(hash表),其在最优情况下查询复杂度为O(1)。

17.取整函数的比较

参考https://blog.csdn.net/guizaijianchic/article/details/71191807

math.ceil():向上取整,返回类型为int(与参考文章不同,是Python版本原因,在Python 2.7下验证为float)

>>> math.ceil(2.1)
3
>>> math.ceil(2.9)
3

math.floor():向下取整,返回类型为int

>>> math.floor(2.1)
2
>>> math.floor(2.9)
2

round():四舍五入,返回类型为int,值得注意的点为*.5是向下取整的

>>> round(2.1)
2
>>> round(2.9)
3
>>> round(2.5)
2
>>> round(2.51)
3

int():截去小数部分,返回类型为int,与math.floor()在正数时没有差异,在负数时是有差异的(参考题 Python 3中的int()和floor()有什么区别?,详见示例代码)

>>> int(2.1)
2
>>> int(2.9)
2
>>> int(-2.1)
-2
>>> math.floor(-2.1)
-3

18.三元表达式(三目运算符)

参考python中的三元表达式(三目运算符) - 我是天涯边的小白鹤 - 博客园

Python没有与其它语言类似的三元表达式,只有类似的替代方法,如:

>>>h = “变量1” if a>b else “变量2”

19.enumerate函数

参考Python enumerate() 函数:

用于将一个可遍历的数据对象(如列表、元组或字符串)组合成一个索引序列,同时列出数据和数据下标,一般用在for循环当中:

>>>seq = [‘one’, ‘two’, ‘three’]
>>>for I, element in enumerate(seq):
>>>	print I, element
0 one
1 two
2 three

20.zip函数

参考Python3 zip() 函数:

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。

我们可以使用 list() 转换来输出列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b)     # 返回一个对象
>>> zipped
<zip object at 0x103abc288>
>>> list(zipped)  # list() 转换为列表
[(1, 4), (2, 5), (3, 6)]
>>> list(zip(a,c))              # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]>>> a1, a2 = zip(*zip(a,b))          # 与 zip 相反,zip(*) 可理解为解压,返回二维矩阵式
>>> list(a1)
[1, 2, 3]
>>> list(a2)
[4, 5, 6]

21.将list转为tuple

参考Convert list to tuple in Python:

>>>l = [4, 5, 6]
>>>tuple(l)
(4, 5, 6)

22.列表推导式、字典推导式、集合推导式

参考python的各种推导式(列表推导式、字典推导式、集合推导式) - 苍松 - 博客园

推导式(comprehensions,又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体,有列表推导式、字典推导式、集合推导式3种。

1.列表推导式

>>> multiples = [i for i in range(30) if i % 3 is 0]
>>> print(multiples)
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

也可以使用()生成generator:

>>> multiples = (i for i in range(30) if i % 3 is 0)
>>> print(type(multiples))
<class 'generator'>

2.字典推导式

>>> mcase = {'a': 10, 'b': 34}
>>> mcase_frequency = {v: k for k, v in mcase.items()}
>>> print (mcase_frequency)
{10: 'a', 34: 'b'}

3.集合推导式

>>> squared = {x**2 for x in [1, 1, 2]}
>>> print (squared)
{1, 4}
>>> print (type(squared))
<class 'set'>

23.lambda及函数式编程

参考python函数式编程 - 虫师 - 博客园及Python学习笔记(十二):lambda表达式与函数式编程

匿名函数lambda没有语句的原因,是它被用于在代码被执行的时候构建新的函数对象并且返回。lambda并不会带来程序运行效率的提高,只会使代码更简洁。

lambda的一般形式是关键字lambda后面跟一个或多个参数,紧跟一个冒号,以后是一个表达式。如:

>>> g = lambda x,y=2,z=3 : x+y+z
>>> print (g(1,z=4,y=5))
10

几个定义好的全局函数:filter,map,reduce。这也是函数式编程的思想,优点是:

1.代码更简单了;

2.数据集、操作、返回值都放到了一起;

3.没有循环体,少了些临时变量,以及变量倒来倒去逻辑;

4.代码变成了在描述你要干什么,而不是怎么去干;

24.读写文档

参考人类身份验证 - SegmentFault及可爱的 Python:Python中的文本处理及Python File readline() 方法及Python File(文件) 方法:

read:读取整个文件;
readline:读取下一行,使用生成器方法;
readlines:读取整个文件到一个迭代器以供我们遍历;
content = ""
with open("test.txt", "r") as f:line = f.readline()while line:line = line.strip()print (f"line = {line}")content += lineline = f.readline()

注意最后一行是换行符,一般可以去掉。

写文档:

with open("test.txt", "w") as f:f.write("thresholdtfalseNegativetfalsePositiven")

需要在最后加n才会换行.

w表示打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

25.exec语句与eval函数

exec语句用于执行Python程序相同的方式来执行字符串,如:

>>> exec ("print ('Hello, world!')")
Hello, world!

eval会计算Python表达式(以字符串形式书写),并且返回结果值。如:

>>> eval(input("Enter an arithmetric expression: "))
Enter an arithmetric expression: 6+18*2
42

26.repr函数

参考Python中的repr()函数 - 波比12 - 博客园,将任意值转换为字符串有两种方法:传入repr()函数或str()函数。

区别:函数str()将值转换为适于人阅读的形式,repr()将值转换为供解释器读取的形式。

通常情况下repr()与eval()结合的对象是相同的,如:

>>> str = "I love Python"
>>> str == eval(repr(str))
True
>>> l = [0, 1, 2]
>>> l == eval(repr(l))
True

对元组是不成立的:

>>> tup = (1, 2, 3)
>>> tup == eval(repr(l))
False

而str()函数也要分情况判断:

>>> s = "I love Python"
>>> s == eval(str(s))
Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<string>", line 1I love Python^
SyntaxError: invalid syntax
>>> l = [0, 1, 2]
>>> l == eval(str(l))
True
>>> tup = (1, 2, 3)
>>> tup == eval(str(tup))
True

27.进制等之间的转换

参考python常用的十进制、16进制、字符串、字节串之间的转换(长期更新帖)

10进制转16进制: hex(16) ==> 0x10

28.any()函数

参考Python any() 函数 | 菜鸟教程

用于判断给定的可迭代参数iterable是否全部为空对象,如果都为空、0、False,返回False,如果不都为空、0、False,则返回True。

>>> any([0, "", False])
False
>>> any(['a', 'b', '', 'd'])
True

29.生成器

参考深入理解Python中的生成器 - Python - 伯乐在线

生成器(generator)不会把结果放在一个系列中,而是保存生成器的状态,在每次进行迭代时返回一个值,直到遇到StopIteration异常结束。

生成器函数功能的实现依赖于yield表达式,任何包含yield语句的函数称为生成器。生成器不像return那样返回值,而是每次产生多个值。每次产生一个值(使用yield语句),函数就会被冻结:即函数停在那点等待被重新唤醒。函数被重新唤醒后就从停止的那点开始执行。

生成器是包含有__iter__()和__next__()方法(可参考python之__iter__函数与__next__函数)的,所以可以直接使用for来迭代,而没有包含StopIteration的自编Iter只能通过手动循环来迭代。


五、Python库

1.安装

安装单独的包:

>>>pip install time

通过requirements.txt一次性安装大量的包:

>>>pip install -r requirements.txt

requirements.txt里每行都是一个包的名字。

安装指定版本的包:

>>>pip install tensorflow-gpu==1.9.0

如果出现如下报错:

Permission denied: '/home/dao/anaconda2/lib/python2.7/site-packages/easy-install.pth'

问题在于安装权限不够,将anaconda2的用户所有者由root改为自己的用户名即可:

sudo chown -R ‘a’ /home/a/anaconda2

2.单元测试unittest

参考单元测试

在Python中,unittest是Python中的单元测试框架。它拥有支持共享搭建、自动测试、在测试中暂停代码、将不同测试迭代成一组,等等的功能。

测试类需要从unittest.TestCase继承,测试方法需要以test开头。

一种常见的运行方法是:

>>>python -m unittest mydict_test
-m mod : run library module as a script (terminates option list)

参考python自动化-unittest批量执行用例(discover) - anlcy - 博客园,可以使用unittest模块中的TestLoader类中的discover方法来批量执行用例。

一个典型的用法是:

>>>python -m unittest discover -p  '*_test.py'
-case_dir:这个是待执行用例的目录。
-pattern[-p]:这个是匹配脚本名称的规则,test*.py意思是匹配test开头的所有脚本。
-top_level_dir:这个是顶层目录的名称,一般默认等于None就行了。

3.唯一ID生成库UUID

参考Python使用UUID库生成唯一ID - dkcndk - 博客园

UUID是128位的全局唯一标识符,通常由32字节的字符串表示。可以保证时间和空间的唯一性,也称为GUID。

它通过MAC地址、时间戳、命名空间、随机数、伪随机数来保证生成ID的唯一性。

UUID主要有五个算法,使用方面:

1.Python中没有基于DCE的,所以uuid2可以忽略;

2.uuid4存在概率性重复,由无映射性,最好不用;

3.若在Global的分布式计算环境下,最好用uuid1;

4.若有名字的唯一性要求,最好用uuid3或uuid5。

>>>import uuid
>>>print(str(uuid.uuid4()))
9c0786a4-619e-4c07-9862-0409200437d3

4.pickle

安装参考How to install cPickle on Python 3.4?:

import _pickle as cPickle

Python 3找不到cPickle可参考python错误之ImportError: No module named 'cPickle'::

将cPickle改为pickle即可

5.Flask

入门文档可参考Tutorial - Flask 1.0.2 documentation

获取访问者的IP地址可参考使用Python Flask获取访问者的IP地址 - 代码日志:

>>>from flask import request
>>>from flask import jsonify>>>@app.route("/get_my_ip", methods=["GET"])
>>>def get_my_ip():
>>>    return jsonify({'ip': request.remote_addr}), 200

参考How to prevent Unicode representation for Latin1 characters?及Flask设置返回json格式数据 - Penguin及人类身份验证 - SegmentFault

使用Python官方的jsonify模块有可能会出错,没有正确使用UTF-8去传输中文数据:

return jsonify(code=1000, message=decodeText, decodeType=decodeType)

可以使用json代替:

return json.dumps({"code":1000, "message":decodeText, "decodeType":decodeType}, ensure_ascii=False)

一个实例就是应该返回的是't这',而得到的是'tè¿™',遗憾的这个转换怎么来的我还没有能力推导,一个思路是:

>>> u"这".encode("utf-8")
b'xe8xbfx99'
>>> hex(ord("è"))
'0xe8'
>>> hex(ord("¿"))
'0xbf'
>>> hex(ord("™"))
'0x2122'

但是这个依然是有问题的,别人测试我代码是在Windows系统中测试的,里面的默认编码是GBK而不是UTF-8,所以还是需要指定好。

参考不要相信requests编码后返回的text - 猿人学Python及Python HTTP库requests中文页面乱码解决方案!,其编码头(在Python中打印可以参考python 调试 requests 打印 HTTP 请求与响应)一般是这样的:

Content-Type: text/html

而不是:

Content-Type: text/html; charset=utf-8

所以会使用默认的GBK进行解码,而不是想象中的UTF-8。

另外一个问题就是最好使用"application/json"而不是"text/html"设计编码头,这个可以参考What does "Content-type: application/json; charset=utf-8" really mean?及https://stackoverflow.com/questions/477816/what-is-the-correct-json-content-typeWhat is the correct JSON content type?。

在Python的设置可以参考Forcing application/json MIME type in a view (Flask)及Python Flask, how to set content type:

import json
from flask import Response
ret = json.dumps({"code":1010, "message":”hello, world!"}, ensure_ascii=False)
return Response(response=ret, status=200, mimetype="application/json; charset=utf-8")

6.os

获取文件路径:参考记录下os.path.dirname(__file__)使用:

import os
print (os.path.dirname(__file__))

一般来说返回的是相对路径,所以最好先求绝对路径:

import os
print (os.path.dirname(os.path.abspath(__file__)))

统计文件夹内文件个数:参考python (9)统计文件夹下的所有文件夹数目、统计文件夹下所有文件数目、遍历文件夹下的文件

统计以.jpg结尾的文件个数:

>>>import os
>>>len([i for i in os.listdir(“./”) if i.split(".")[-1] == "jpg"])

判断文件和文件夹是否存在:参考python 判断路径是文件还是文件夹、判断是否存在、获取文件大小

import os
if os.path.isdir(path):print "it's a directory"
elif os.path.isfile(path):print "it's a normal file"
else:print "it's a special file(socket,FIFO,device file)"

获取文件夹下所有文件:参考Python获取文件夹下的文件和子文件夹,os.walk()函数执行之后得到一个三元tupple(dirpath, dirnames, filenams),os.listdir()函数返回指定路径下的文件和文件夹列表。

创建文件夹:参考python创建文件和文件夹:

>>>os.makedirs("/root/tmp")

重命名:参考How to move a file in Python:

os.rename("path/to/current/file.foo", "path/to/new/destination/for/file.foo")

客观上,改变文件路径也可以起到移动文件的效果。

7.读写excel库xlrd

参考python操作Excel读写--使用xlrd - lhj588 - 博客园

打开文件:

import xlrd
# read the sheet
try:data = xlrd.open_workbook(os.path.join(cfg.DATA_FOLDER, name))
except Exception, e:print str(e)table = data.sheets()[6]

读取目标行列值:

print (table.cell(i, 4).value)

表示读取第i行、第4列的值,注意index从0开始。

8.platform

获取平台名称:参考Python判断当前操作系统类型以及os/sys/platform模块简介:

>>>import platform
>>>platform.node()
‘a’

9.sys

获取系统目录:sys.path,返回一个列表:

['',..., '/home/a/anaconda2/envs/python36/lib/python3.6/site-packages']

该列表可修改,参考python 在不同层级目录import 模块的方法,可通过往系统目录插入需求目录的方法改变Python解释器的入口:

this_dir = os.path.dirname(__file__)
sys.path.append(this_dir + '/..')

10.XML解析库xml.etree.ElementTree

参考Python XML 解析 | 菜鸟教程,XML指可扩展标记语言(eXtensible Markup Language).XML被设计用来传输和存储数据.XML是一套定义语义标记的规则,这些标记将文档分成许多部件加以标识.它也是元标记语言,即定义了用于定义其他与特定领域有关的,语义的,结构化的标记语言的句法语言。

参考用 ElementTree 在 Python 中解析 XML,可使用xml.etree.ElementTree来解析xml。官方文档在19.7. xml.etree.ElementTree - The ElementTree XML API - Python 2.7.16 documentation。

可能有用的文章Python xml属性/节点/文本的增删改[xml.etree.ElementTree]及深入解读Python解析XML的几种方式| 编程派 | Coding Python。

11.matplotlib

基本方法可参考python 画图--简单开始及折线图,绘制文字可参考四、Matplotlib系列---pyplot的文本显示,绘制散点图可参考使用Matplotlib绘制散点图 | 烂笔头,绘制图例说明可参考matplotlib.pyplot.legend - Matplotlib 3.1.0 documentation,设置坐标轴范围可参考【Matplotlib】线设置,坐标显示范围 - Chris*Chen - 博客园。

如果报错:

QXcbConnection: Could not connect to display

参考https://www.douban.com/note/612063589/,原因在于无界面操作的Linux系统不能在界面里画图,所以需要隐藏该操作,改show为save,将图片保存下来,转到有界面的操作系统里观看。

在import matplotlib.pyplot as plt前添加引用:

import matplotlib
matplotlib.use('Agg')

12.PyTorch

在PyTorch下载依赖包,安装,再安装torchvision:

pip install torchvision

13.FontTool

一个应用在Michael:解决了困扰了一个礼拜的一个坑,只在Windows下可以使用的一个字体终于可以在Linux下使用了,源代码在fontTools/ttLib/ttFont.py。

14.logging

参考python logging模块使用教程:

6c1f49b26469831a79efbe2e89958eef.png

15.base64

本地图片转base64格式:

import base64
with open(imgPath, 'rb') as f:rawContent = f.read()imgBase64 = base64.b64encode(rawContent)

base64格式转numpy格式:

imgData = base64.b64decode(dataInput)
imgData = np.fromstring(imgData, np.uint8)
print (imgData.shape)	# (94180,)
imgArr = cv2.imdecode(imgData, cv2.IMREAD_COLOR)
print (imgArr.shape)	# (816, 610, 3)

如果报错:TypeError: Incorrect padding,参考python base64解码TypeError: Incorrect padding错误及http://www.phperz.com/article/15/1002/45577.html,对base64解码的string补齐等号就可以了:

def decode_base64(data):"""Decode base64, padding being optional.:param data: Base64 data as an ASCII byte string:returns: The decoded byte string."""missing_padding = 4 - len(data) % 4if missing_padding:data += b'='* missing_paddingreturn base64.decodestring(data)

OpenCV转base64,参考python PIL/cv2/base64相互转换及OpenCV-Python cv2.imdecode()和cv2.imencode() 图片解码和编码:

# encode the image
base64_str = cv2.imencode('.png', thumbnail)[1].tostring()
jsImg = base64.b64encode(base64_str)

16.数据读写库json与pickle

参考在Python里创建JSON文件及读写保存JSON数据及PYTHON将list或/dict对象写入txt/json文件

写文件:

jsonDictResult = json.dumps(dictResult, ensure_ascii=False)
with open(os.path.join('data', 'result.json'), 'w') as f:f.write(jsonDictResult)

读文件:

with open("result.json", "r") as f:dictResult = json.load(f)

另一个相似的库是Pickle,参考What is Pickle in python ?及Understanding Python Pickling with example - GeeksforGeeks。pickle模块可以读入任何Python对象,将它们转换成字符串,然后使用dump函数将其存储到一个文件中——这个过程叫做pickling。反之,从存储的字符串文件中提取原始Python对象的过程,叫做unpickling。

# pickling
>>> a = {"h":1, "e":2}
>>> import pickle
>>> with open("a.log", "wb") as f:
...     pickle.dump(a, f)# unpicling
>>> with open("a.log", "rb") as f:
...     b = pickle.load(f)
>>> b
{'h': 1, 'e': 2}

json与pickle几点不一样的地方:

  1. pickle只能将变量存储进文件中,而json是先将变量转换为字符串,这字符串可以存入文件,也可以传给其它对象或函数使用;
  2. pickle存储的文件可读性很差,但是恢复后能恢复之前的数据类型,比如例子里字典的值依然是int,json存储的文件可读性很好,基本与打印的一致,但是恢复后有可能不能恢复之前的数据类型,这个原因待查;

17.requests

参考Python 使用requests发送POST请求及快速上手 - Requests 2.18.1 文档

HTTP协议规定post提交的数据必须放在消息主体中,但是协议并没有规定必须使用什么编码方式。服务端通过请求头中的Content-Type字段来获知请求中的消息主体是用何种方式进行编码,再对消息主体进行解析。

具体的编码方式包括:

1.application/x-www-form-urlencoded。最常见的post提交数据的方式,以form表单形式提交数据;

只需要将请求的参数构造成一个字典,然后传给requests.post()的data参数即可:

url = 'http://httpbin.org/post'
d = {'key1': 'value1', 'key2': 'value2'}
r = requests.post(url, data=d)
print (r.text)

2.application/json。以json串提交数据;

rl = 'http://httpbin.org/post'
s = json.dumps({'key1': 'value1', 'key2': 'value2'})
r = requests.post(url, data=s)
print (r.text)

3.multipart/form-data。一般使用来上传文件;

url = 'http://httpbin.org/post'
files = {'file': open('report.txt', 'rb')}
r = requests.post(url, files=files)
print (r.text)

18.CharlesShang/TFFRCNN

报错:

tensorflow.python.framework.errors_impl.NotFoundError: ./faster_rcnn/../lib/roi_pooling_layer/roi_pooling.so: undefined symbol: _ZTIN10tensorflow8OpKernelE

参考Undefined symbol: _ZTIN10tensorflow8OpKernelE · Issue #108 · CharlesShang/TFFRCNN,需要加上:

-L $TF_LIB -ltensorflow_framework

报错:

RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). max_open_warning, RuntimeWarning)

参考warning about too many open figures:

import matplotlib.pyplot as plt
plt.rcParams.update({'figure.max_open_warning': 0})

报错:

you may need to pass the encoding= option to numpy.load

参考python3中的np.load编码问题,原因在于在Python2 中的默认编码为ASCII,但是在Python3中的默认编码为UTF-8。 需要指定编码格式为ASCII,使用下列指令:

np.load(det.npy, encoding="latin1")

19.attention_ocr

报错:

str' object has no attribute 'decode'.

参考'str' object has no attribute 'decode'. Python 3 error?:

You are trying to decode an object that is already decoded. You have a str, there is no need to decode from UTF-8 anymore.
Simply drop the .decode('utf-8') part.

报错:

AttributeError: type object '_io.StringIO' has no attribute 'StringIO'

参考AttributeError: type object '_io.StringIO' has no attribute 'StringIO' · Issue #111 · pgbovine/OnlinePythonTutor:

try:from io import StringIO
except:import StringIO

保存图片可以这样:

io = BytesIO()
image_pil = PILImage.fromarray(image)
image_pil.save(io, image_format, subsampling=0, quality=100)

一个相关的博客StringIO和BytesIO。

20.faiss

安装很简单:

pip install faiss

运行报错:

ImportError: libopenblas.so.0: cannot open shared object file: No such file or directory

参考Scipy installation issue, getting ImportError: libopenblas.so.0: cannot open shared object file or directory:

sudo apt-get install libopenblas-dev

运行报错:

ImportError: libomp.so: cannot open shared object file: No such file or directory

参考ImportError: No module named '_swigfaiss · Issue #821 · facebookresearch/faiss:

sudo apt-get install libomp-dev

在Centor中安装可参考llvm-toolset-7-libomp-5.0.1-2.el7.x86_64.rpm CentOS 7 Download:

yum install centos-release-scl-rh
yum install llvm-toolset-7-libomp

需要将库放到环境变量下:

export LD_LIBRARY_PATH="/opt/rh/llvm-toolset-7/root/usr/lib64/:$LD_LIBRARY_PATH"

六、类

1.基本概念

参考Python 面向对象 | 菜鸟教程

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。局部变量:定义在方法中的变量,只作用于当前实例的类。实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。实例化:创建一个类的实例,类的具体对象。方法:类中定义的函数。对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

我认为主要要弄明白的概念是类和对象的区别。

2.基本应用

举例:

#!/usr/bin/python
# -*- coding: UTF-8 -*-class Employee:'所有员工的基类'empCount = 0def __init__(self, name, salary):self.name = nameself.salary = salaryEmployee.empCount += 1def displayCount(self):print ("Total Employee %d" % Employee.empCount)def displayEmployee(self):print ("Name : ", self.name,  ", Salary: ", self.salary)
empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount 访问。
第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法
self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。

可以使用以下函数的方式来访问属性:

getattr(obj, name[, default]) : 访问对象的属性。
hasattr(obj,name) : 检查是否存在一个属性。
setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
delattr(obj, name) : 删除属性。

对Python的固有类型int等也可以通过上述方法去访问其属性。

Python 对象的实例化过程及[深入Python]__new__和__init__ - 鸪斑兔 - 博客园介绍了除__init__外的另一种构造方法__new__。

3.元类metaclass

参考python 类和元类(metaclass)的理解和简单运用及深刻理解Python中的元类(metaclass) - 文章 - 伯乐在线及使用元类

元类就是创建类的类。函数type实际上就是一个元类,type就是Python在背后用来创建所有类的元类。如:

>>>age = 35
>>>age.__class__
<type ‘int’>
>>>age.__class__.__class__
<type ‘type’>
>>>def foo(): pass
>>>foo.__class__
<type ‘function’>
>>>foo.__class__.__class__
<type ‘type’>

4.装饰器

参考[转载]python中的@符号的作用_程序猿妞妞妞_新浪博客及PEP 318 -- Decorators for Functions and Methods

一个修饰符就是一个函数,它就被修饰的函数作为参数,并返回修饰后的同名参数或其它可调用的东西。

要想使被修饰函数能正常运行,必须加返回值,@decorator是一个statement,会将被修饰函数当作参数传入来执行:

>>> def decorator(fn):
...     def test(*args):
...             print ("My god!"*3)
...             return fn(*args)
...     return test
... 
>>> @decorator
... def other(a, b)File "<stdin>", line 2def other(a, b)^
SyntaxError: invalid syntax
>>> def other(a, b):
...     print (a**2+b**2)
... 
>>> other(4, 3)
25

参考Python装饰器 - 田小计划 - 博客园,装饰器是可以叠加使用的,那么这是就涉及到装饰器调用顺序了。对于Python中的"@"语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。

装饰器本身也可以支持参数,如:@demo(False)。

在Python中有三个内置的装饰器,都是跟class相关的:@staticmethod、@classmethod和@property。

1.@staticmethod是类静态方法,其跟成员方法的区别是没有self参数,并且可以在类不进行实例化的情况下调用。@staticmethod是把函数嵌入到类中的一种方式,函数就属于类,同时表明函数不需要访问这个类。通过子类的继承覆盖,能更好的组织代码;

参考飘逸的python - @staticmethod和@classmethod的作用与区别,类静态方法调用自身不是使用self.static_foo()函数,而是使用A.static_foo()函数。

2.@classmethod与成员方法的区别在于所接收的第一个参数不是self(类实例的指针),而是cls(当前类的具体类型)。@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码;

@classmethod与@staticmethod之间的区别可以参考python中@classmethod @staticmethod区别及Python 中的 classmethod 和 staticmethod 有什么具体用途?。

3.@property是属性的意思,表示可以通过类实例直接访问的消息。可以将返回变量设为只读,防止修改变量引发的问题;

可以参考使用@property。

参考How to strip decorators from a function in Python,如果想调用未带装饰器的函数,可以这样:

def with_connection(f):def decorated(*args, **kwargs):f(get_connection(...), *args, **kwargs)decorated._original = freturn decorated
@with_connection
def spam(connection):# Do something
spam._original(testcon) # calls the undecorated function

作用就是在修饰符函数中定义被修饰函数。

5.abc

参考abc - Abstract Base Classes - Python 3.7.3 documentation及abc — 抽象類別 — 你所不知道的 Python 標準函式庫用法 03 | louie_lu's blog

使用 Python abc 套件的原因,是為了要解決 Python 沒有「抽象類別 (abstract class)」的問題。透過抽象類別,我們可以建立一個比起使用 hasattr() 還要更嚴格的類別介面 (class interface) 檢查。

6.多态

参考继承和多态及再谈python中的多态

对象最重要的优点包括:

1.多态(Polymorphism)。意味着可以对不同类的对象使用同样的操作,它们会像被“施了魔法一般”工作;

2.继承(Inheritance)。以通用的类为基础建立专门的类对象;

3.封装(Encapsulation)。对外部世界隐藏对象的工作细节。

7.__str__

参考python: 理解__str__

当打印一个类的时候,print首先调用的就是类里面的的定义的__str__。

一些可能有用的网址:Are functions objects in Python?

python类的继承 - Bigberg - 博客园

Python super() 函数

Python 面向对象 | 菜鸟教程


七、Python语言

1.什么是Python?使用Python有什么好处?

Python是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理。

Python简洁、简单、方便、容易扩展,有许多自带的数据结构,而且Python开源。

Python是一种解释型语言,Python代码在运行之前不需要编译,源代码可以直接运行,Python解释器会将源代码转换成中间语言,之后再翻译成机器码再执行。其他解释型语言还包括PHP和Ruby。

Python是动态类型语言,动态语言指的是一类在运行时可以改变其结构的语言,即在声明变量时,不需要说明变量的类型,动态语言能动态给实例绑定属性。

Python非常适合面向对象的编程(OOP),因为它支持通过组合与继承的方式定义类。Python中的类没有访问说明符(类似C++中的public和private)。

Python代码编写快,因此程序员可以专注于算法和数据结构的设计,而不用处理底层的细节。

2.PEP8 Python编程规范

参考PEP8 Python 编码规范整理,PEP8是一个编程规范,内容是一些关于如何让你的程序更具可读性的建议,比如缩进使用4个空格而不是Tab键。

3.管理内存

Python作为一种动态语言,其变量和对象是分离的,关于此部分的介绍可以参考Michael:[Python]可变对象与多进程。对象存在于内存之中,Python采用引用计数的垃圾回收机制来释放内存。

Python的内存管理是由私有heap空间管理的,所有的Python对象和数据结构都在一个私有的heap中。只有解释器才有访问heap的权限,而为heap空间分配内存是由Python的内存管理模块负责的,其核心API会提高一些接口供外部访问(比如gc.collect()可以手动回收内存)。

参考简单理解python下的变量和内存,Python是有小整数对象池和大整数对象池概念的,Python 对小整数的定义是[-5, 256],这些整数对象是提前建立好的,不会被垃圾回收,可以做这么一个实验:

>>> id(4)
93991663884928
>>> id(5)
93991663884960
>>> id(6)
93991663884992
>>> x = 4
>>> id(x)
93991663884928
>>> x = 5
>>> id(x)
93991663884960
>>> x = 6
>>> id(x)
93991663884992

内存的分配也是跟解释器相关的,个人猜测是建立解释器的时候就会申请一批内存给小整数对象池。

参考Python深入06 Python的内存管理,其它不可变对象中对其所有的引用都是指向同一对象的:

>>> a = "good"
>>> b = "good"
>>> id(a)
140479393598744
>>> id(b)
140479393598744
>>> a is b
True

垃圾回收机制依赖引用计数,对每个对象,解释器都会记录指向该对象的引用总数,称为引用计数(reference count)。可以使用sys库中的getrefcount()函数来查看某个对象的引用计数。值得注意的是,在调用getrefcount()的过程中,因为传参也相当于在函数体局部命名空间创建了一个指向该对象的变量,因此该函数所得到的结果会比期望的多1:

>>> import sys
>>> a = [1, 2, 3]
>>> sys.getrefcount(a)
2
>>> b = a
>>> sys.getrefcount(a)
3

可以使用del()语句来删除某个引用,也可以用于删除容器元素中的元素,因为容器内的元素也只是对象的应用:

>>> import sys
>>> sys.getrefcount(1)
765
>>> a = 1
>>> sys.getrefcount(1)
766
>>> b = [a]
>>> sys.getrefcount(1)
767
>>> del(b[0])
>>> sys.getrefcount(1)
766

Python在运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数,当两者的数值高于某个阈值时,垃圾回收才会启动。

可以通过gc模块的get_threshold()方法来查看该阈值:

>>> import gc
>>> gc.get_threshold()
(700, 10, 10)

可以看到一共有三个数,第一个数700表示的是垃圾回收启动的阈值,可以通过gc.set_threshold()方法重新设置阈值,后两个数代表的是Python分代(generation)回收的策略。这一策略的基本假设是:存活时间越久的对象,越不可能变为垃圾对象。因此,Python将所有的对象分为0、1、2三代。所有的新建对象都是0代对象,当某一代对象经历过垃圾回收,依然存活,那么它就被归入下一代对象。上述的(700, 10, 10)就表示每10次0代的垃圾回收,会配合1次1代的垃圾回收,而每10次1代的垃圾回收,才会有1次2代的垃圾回收。

也可以手动启动垃圾回收,即使用gc.collect():

>>> a = "hello"
>>> id("hello")
140701853023568
>>> del(a)
>>> id("hello")
140701853023568
>>> import gc
>>> gc.collect()
0
>>> id("hello")
140701853500672
>>> id("hello")
140701853500672

可以看到,通过del(a)删掉"hello"的引用后,"hello"依然存在于内存之中,且通过id可以知道是之前分配的内存,手动回收之后发现id已经变化,表示已经消除了"hello",只是在提取id的过程中重新分配了内存。

引用环的意思是两个对象相互引用,从而构成了一个引用的环,比如:

>>> import sys
>>> a = []
>>> sys.getrefcount(a)
2
>>> b = [a]
>>> sys.getrefcount(a)
3
>>> sys.getrefcount(b)
2
>>> a.append(b)
>>> a
[[[...]]]
>>> sys.getrefcount(a)
4
>>> sys.getrefcount(b)
3

可以看到,a.append(b)后就构成了一个引用环,然后,a和b的引用都增加了1,这个现象也是非常的有趣。

可以看到,就算把引用a,b都删掉了,两个对象的引用计数也没有降到0,因此不会被垃圾回收。为了回收这样的引用环,Python复制每个对象的引用计数,可以记为gc_ref。对于每个对象i引用的对象j,将相应的gc_ref_j减1。在结束遍历后,gc_ref不为0的对象,和这样对象引用的对象,以及继续更下游的对象,需要被保留,而其它的对象则被垃圾回收。

我理解的解决策略是不仅仅记录对象被引用的次数,还记录引用的次数,而环则表示相互引用、相互被引用,非环状引用则没有这个问题。

如何释放Python占用的内存?里面有些不错的内容,有时间可以看看。

4.静态分析

PyChecker是一个静态分析工具,它不仅能报告源代码中的错误,并且会报告错误类型和复杂度。Pylint是检验模块是否达到代码标准的另一个工具。

5.Python的编译机制

参考Python学习笔记之二——Python的运行机制及谈谈 Python 程序的运行原理

解释器是一种让其它程序运行起来的程序,它是代码与机器的计算机硬件之间的软件逻辑层,Python解释器是能够让Python程序在机器上执行的一套程序。

Python解释器执行的步骤:

1.将原始代码编译成字节码对象

在运行期间,编译结果是字节码对象PyCodeObject,只存在于内存中,是特定于Python的一种表现形式,它不是二进制的机器码,需要进一步编译才能被机器执行;而该模块执行完后,编译结果保存到了.pyc文件中,这样下次就不用编译,直接加载到内存中,因此,.pyc文件是PyCodeObject对象在硬盘上的表现形式。

PyCodeObject对象包含了Python源代码中的字符串、常量值以及通过语法解析后编译生成的字节码指令。PyCodeObject对象还会存储这些字节码指令与原始代码行号的对应关系,这样当出现异常时,就能指明位于哪一行的代码。

.pyc文件包含了三部分信息:Python的magic number、.pyc文件创建的时间信息以及PyCodeObject对象。

2.将编译好的字节码对象转发到Python虚拟机(Python Virtual Machine, PVM)中进行执行

PVM是Python的运行引擎,是Python系统的一部分,它是迭代运行字节码指令的一个大循环,一个接一个地完成操作。

Python解释器有三种主要的实现方式:

1.CPython

CPython是标准的实现,是用C语言编写的,是大多数Linux和Mac OS X机器预装的Python解释器,也是所有Python解释器中运行最快、最完整、最健全的。

2.Jython

设计的目的是为了与Java编程语言继承,Jython要比CPython慢,而且也不够健壮,它往往看作是一个主要面向寻找Java代码前端脚本语言的Java开发者的一个有趣的工具。

3.IronPython

设计的目的是让Python程序可以与Windows平台上的.NET框架以及与之对应的Linux上的开源的Mono编写成的应用集成。

参考谈谈 Python 程序的运行原理,Python通过一个全局解释器锁GIL(Global Interpreter Lock)来实现线程同步的,线程调度机制会为线程分配GIL,获取到GIL的线程就能开始执行,而其它线程则必须等待。由于GIL的存在,Python的多线程性能十分低下,无法发挥多核GPU的优势,性能甚至不如单线程。因此如果想用多核GPU,一个建议是使用多进程。

6.内存泄露问题

参考如何解决Python2的内存泄漏问题 - 程序园

pymalloc在一轮暴虐之后进程内存下不去。

不使用pymalloc容易导致不少兼容性的问题出现,而且许多python的新feature会用不了,不建议这么做。

而tcmalloc果然名不虚传,run方法结束后,内存马上释放到解放前。建议生产环境尝试使用tcmalloc编译的Python解释器,其它兼容性的问题有待考证。

C++上的安装可参考tcmalloc安装与使用。

其它可参考的文章:内存优化总结:ptmalloc、tcmalloc和jemalloc、白山云科技:Python 进程内存增长解决方案。

7.Python 2.x和Python 3.x的区别

参考Python3.x和Python2.x的区别 - 紫红的泪 - 博客园

这里摘抄几条比较重要的:

1.Python 3运行较慢,大概15%到30%;
2.Python 3默认使用UTF-8编码;
3.去除print语句,加入print()函数实现相同的功能;
4.整型除法返回浮点数,要得到整型结果,请使用//;
5.捕获异常的语法改变,引入了as关键字来标识异常实例,即except NotImplementedError as error;
6.去除了xrange(),range()返回的一个迭代器,而不是列表;

8.单下划线和双下划线

参考http://python.jobbole.com/81129/及python 里面的单下划线与双下划线的区别(私有和保护)

单下划线:会在以下三种场景中使用:

1.在解释器中:_代表交互式解释器回话中上一条执行的语句的结果;

2.作为一个名称:_作为临时性的名称使用,如:for _ in range(10);

3.国际化:作为一个函数来使用,_通常用于实现国际化和本地化字符串之间翻译查找的函数名称,源自并遵循相应的C约定,如output = _(“Welcome to my site.”);

另外,使用名称前的单下划线,用于制定该属性为“私有”,在模块或类外不可以使用。

名称前的双下划线:为了避免与子类定义的名称冲突,__spam这种形式(至少两个前导下划线,最多一个后续下划线)的任何标识符将会被__classname__spam这种形式取代。另外,表示的是私有类型的变量,只能允许这个类本身进行访问,连子类也不可以;

名称前后的双下划线:为了确保不会与用户自定义的名称冲突,如__init__;

9.GIL线程全局锁

参考Python的GIL是什么鬼,多线程性能究竟如何及python GIL 全局锁

GIL(Global Interpreter Lock,全局锁)是一个防止多线程并发执行机器码的一个Mutex。

GIL不是Python的特性,是实现Python解析器CPython时所引入的一个概念,Python完全可以不依赖于GIL。

Python的多线程在多核CPU上,只对于IO密集型计算产生正面效果;而当有至少有一个CPU密集型线程存在,那么多线程效率会由于GIL而大幅下降。

解决方法:

1.用multiprocessing替代thread;

2.用其它解析器;

协程可参考协程:协程,又称微线程,纤程,英文名Coroutine。

优势:

1.极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显;
2.不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多;

10.sys.stdout

参考Python 标准输出 sys.stdout 重定向

Python打印对象事实上是调用了sys.stdout.write(obj+'n')。

因此,可以从控制台重定向到文件:

>>> import sys
>>> sys.stdout=open('out.log', 'w')
>>> print ("hello")

sys.stdout.flush()可以参考sys.stdout.flush()在Linux和Windows系统下的作用-YHT的运维笔记-51CTO博客,但我实验显示没有加该指令刷新也很及时。

另外分享一个很不错的打印方法:

print (f"content = {content}")

11.Python3的bytes/str之别

Unicode与UTF-8之间的关系可以参考Unicode 和 UTF-8 有什么区别?:

Unicode:字符集,全名为Universal Multiple-Octet Coded Character Set,简称“UCS",为每一个字符分配一个唯一的ID(学名为码位/码点/Code Point);
UTF-8:编码规则,全名为UCS Transfer Format-8,将码位转换为字节序列的规则,是一套以8位为一个编码单位的可变长编码,会将一个码位编码为1到4个字节;

dd6fab9414ec3cc0ed5ea019db2117f4.png

在Python里可以这样求解:

>>> a = u"知"
>>> hex(ord(a))
'0x77e5'
>>> a.encode("utf-8")
b'xe7x9fxa5'

可以看到与上图是对应的。

参考Python 3的bytes/str之别,Python 3中,对文本和二进制数据做了更为清晰的区分,文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。

字符串是文本的抽象表示,字符串由字符组成,字符则是与任何特定二进制表示无关的抽象实体。

b3605a95743531918f11ebb6235e2627.png

参考Python对中文字符的处理(utf-8/ gbk/ unicode),对各种中文编码方式的转换可以依赖中间值unicode编码(即上图的string):

s.decode('utf-8').encode('gbk')

该句子的意思即为将utf-8编码转为gbk编码。

如果报错:

UnicodeEncodeError: 'ascii' codec can't encode character u'u5e74' in position 26: ordinal not in range(128)

参考UnicodeEncodeError: 'ascii' codec can't encode character u'xa0' in position 20: ordinal not in range(128)

如果不能保存中文即utf-8字符,需要将ASCII字符转码成utf-8字符:

>>>cv2.imwrite(os.path.join(“/root", "%s.png" % dateName.encode('utf-8')), img)

Python2中关于UTF-8的写法可参考python2编码总结 - 晋好林 - 博客园及[Python]编码声明:是coding:utf-8还是coding=utf-8呢。

12.模块和包

一个包含多个Python代码的文件夹是一个包,一个包可以包含模块和子文件夹。

模块是搭建程序的一种方式,每一个Python代码文件都是一个模块。模块的真正用处在于可以像类一样保持自己的作用域,这意味着定义的 所有类和函数以及赋值后的变量都称为了模块的特性。

导入模块需要告知编译器模块位置,求解编译器模块位置:

>>> import sys
>>> print (sys.path)
['', '/home/dao/anaconda2/envs/python36/lib/python36.zip', 
'/home/dao/anaconda2/envs/python36/lib/python3.6', 
'/home/dao/anaconda2/envs/python36/lib/python3.6/lib-dynload',
'/home/dao/anaconda2/envs/python36/lib/python3.6/site-packages']

sys.path是一个可修改列表,在本文5.9节介绍了在Python环境下改变Python路径的方法。

在Linux环境下增加Python路径的方法:

export PYTHONPATH=$PYTHONPATH:~/python

通过字符串名导入模块的方法可参考10.10 通过字符串名导入模块:

import importlib
configLib = importlib.import_module("lib.config%s" % args.element)
cfg = configLib.cfg

参考Python包的相对导入时出现“ ‘Parent module ' not loaded, cannot perform relative import”的解决方法_python_何问起,文件夹被Python解释器视为包需要满足两个条件:

1.文件夹中必须有__init__.py文件,该文件夹可以为空,但必须存在该文件;
2.不能作为顶层模块来执行该文件夹中的.py文件(即不能作为主函数的入口);

所以,引用同一目录下的文件使用from . import xxx可能会有这样的两个错误:

SystemError: Parent module '' not loaded, cannot perform relative import
ValueError: attempted relative import beyond top-level package

参考SystemError: Parent module '' not loaded, cannot perform relative import,可以这样解决:

try:from .mymodule import myclass
except Exception: #ImportErrorfrom mymodule import myclass

13.异常

参考8. Errors and Exceptions

Python用异常对象(exception object)来表示异常情况。遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(traceback,一种错误信息)终止执行。

处理异常可以使用try/except语句来实现,重新引发可以调用不带参数的raise.

示例:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

捕捉所有异常是危险的,因为它会隐藏所有程序员未想到并且未做好准备处理的错误。它同样会捕捉用户终止执行的Crtl+C企图,以及用sys.exit函数终止程序的企图,等等。这时用except Exception, e会更好些,或者对异常对象e进行一些检查。

14.猴子补丁

“猴子补丁”指的是在函数或对象已经对弈之后,再去改变它们的行为。

15.单例模式

参考单例模式_百度百科及[python实现设计模式]-1. 单例模式 - abstract未央 - 博客园

单例模式是一种常用的软件设计模式,在它的核心结构中只包含一个被称为单例的特殊类,通过单例模式可以保证系统中一个类只有一个实例。对于系统中的某些类来说,只有一个实例很重要,例如,一个系统可以存在多个打印任务,但是只能有一个正在工作的任务。

16.字典的内部实现

参考Python dictionary implementation,中文翻译为深入 Python 字典的内部实现 - Python - 伯乐在线。

17.内置算法的复杂度

参考python中各种结构的复杂度 - mrbean - 博客园及Python中list的实现 - Vito.K - 博客园。

18.__all__的作用

参考Can someone explain __all__ in Python?及python中模块的__all__属性

作用是:

If the __all__ above is commented out, this code will then execute to completion, as the default behavior of import * is to import all symbols that do not begin with an underscore, from the given namespace.

在引用是,除了__all__列表里指定的属性,其它都会被隐藏。

19.面向切面编程

参考面向切面编程_百度百科

Aspect Oriented Programming(AOP),面向切面编程。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。


八、深度学习相关

设定TensorFlow使用GPU显存可参考Michael:[Python]设定TensorFlow使用GPU显存。


附件

一些可能有用的网址:

很全的 Python 面试题 - Python - 伯乐在线

常见的25个python面试问答,让你顺利拿到offer!

Python面试必须要看的15个问题 - Vito.K - 博客园

Python初学者需要注意的问题 - walkingp - 博客园

很全的 Python 面试题 - Python - 伯乐在线

【已完结】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源netcore前后端分离,前端服务端渲染方案

SPA单页面应用容器 开源地址&#xff1a; https://github.com/yuzd/Spa功能介绍前端应用开发完后打包后自助上传部署发布配合服务端脚本(javascript)实现服务端业务逻辑编写渲染SSR功能可以快速回滚到上一个版本可以设置环境变量供SSR功能使用服务端脚本提供执行日志 redis db三…

[蓝桥杯2016初赛]方格填数-next_permutation

代码如下&#xff1a; #include <iostream> #include <algorithm> using namespace std;int main() {int a[10] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};int cnt 0;do {if ((abs(a[0] - a[1]) ! 1) && (abs(a[1] - a[2]) ! 1) && (abs(a[3] - a[4]) ! …

word List 13

word List 13 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

ASP.NetCore+VUE 实现学生成绩管理系统(一)

周三陪伴是最长情的告白还有两天情人节&#xff1a;「无论是在家里&#xff0c;还是在工作&#xff0c;或者是在自我防护中&#xff0c;多给家人爱人发句平安&#xff0c;是最有心意、最重要的一件事。」♥感谢老李????近来一段时间一直没有学习新的东西&#xff0c;闲暇的…

下拉菜单实现树状结构_树形图:复杂层次结构的数据可视化

树形图&#xff1a;复杂层次结构的数据可视化作者&#xff1a;Page Laubheimer[1]树形图是一种复杂的&#xff0c;基于区域的数据可视化&#xff0c;用于复杂层次结构的数据&#xff0c;可能难以精确解释。在许多情况下&#xff0c;最好使用更简单的可视化效果&#xff08;例如…

[蓝桥杯2016决赛]路径之谜

题目描述 小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡地面是 n x n 个方格。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或纵向移动&#xff0c;但不能斜着走&#xff0c;也不能跳跃…

数据结构---二叉平衡排序树的删除

数据结构—二叉平衡排序树的删除 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> typedef struct avlTree {int data;struct avlTree *lchild, *rchild;int height; }avlTree;int height(avlTree* AVLTree);//声明av…

Magicodes.IE 2.0发布

Magicodes.IE是我们维护的开源的导入导出通用库&#xff0c;去年年底已加入NCC开源组织。Github地址&#xff1a;https://github.com/xin-lai/Magicodes.IEMagicodes.IE不是一蹴而就&#xff0c;而是根据实际需求不断迭代出来的&#xff0c;而且历经多次重构。这一次&#xff0…

《ASP.NET Core 微服务实战》-- 读书笔记(第11章)

第 11 章 开发实时应用和服务在本章&#xff0c;我们将讨论“实时”的准确含义&#xff0c;以及在大部分消费者看来应该属于这一范畴的应用类型接着&#xff0c;我们将探讨 WebSocket&#xff0c;并分析为什么传统的 WebSocket 与云环境完全不相适应&#xff0c;最后我们将构建…

word List 14

word List 14 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

python编程模式是什么_python 开发的三种运行模式详细介绍

Python 三种运行模式 Python作为一门脚本语言&#xff0c;使用的范围很广。有的同学用来算法开发&#xff0c;有的用来验证逻辑&#xff0c;还有的作为胶水语言&#xff0c;用它来粘合整个系统的流程。不管怎么说&#xff0c;怎么使用python既取决于你自己的业务场景&#xff0…

重磅!K8S 1.18版本将内置支持SideCar容器。

作者&#xff1a;justmine头条号&#xff1a;大数据与云原生微信公众号&#xff1a;大数据与云原生创作不易&#xff0c;在满足创作共用版权协议的基础上可以转载&#xff0c;但请以超链接形式注明出处。为了方便阅读&#xff0c;微信公众号已按分类排版&#xff0c;后续的文章…

word List 15

word List 15 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

.NET Core 如何验证信用卡卡号

_点击上方蓝字关注“汪宇杰博客”导语最近在家闲的蛋疼需要写点文章。正好我本人在金融科技公司工作&#xff0c;对信用卡业务略有了解。我们看看如何在 .NET Core 里验证一个信用卡的卡号是否合法。信用卡卡号组成首先&#xff0c;信用卡的卡号一般为16位&#xff0c;也有少许…

数据结构---关键路径

数据结构—关键路径 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> #include "stack.h" #define typeNode int //每个头结点的标识数据类型 #define N 100 //最大结点数 int degree[N];//结点入度数,通过…

SkyWalking学习笔记(Window环境 本地环境)

基于 Windows 环境使用 SkyAPM-dotnet 来介绍一下 SkyWalking&#xff0c; SkyAPM-dotnet 是 SkyWalking 的 .NET Agent环境要求JDK8Elasticsearch8080,9200,10800,11800,12800 端口不被占用Elasticsearch安装Elasticsearch下载安装 参考官方教程.Elasticsearch下载安装官方教程…

word List16

word List16 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

python二分法求方程的根_Python查找函数f(x)=0根的解决方法

线性代数分享方程f(x)0的根 函数F(x)0的重根与F(x)0的根有什么关系&#xff1f;有些人一旦错过了&#xff0c;就是一辈子不再主动联系&#xff0c;不愿打扰你的生活&#xff0c;连偶尔的寒暄都没有&#xff0c;成长就是这样的&#xff0c;不断的告别&#xff0c;不断的遇见。 请…

word List 17

word List 17 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

pb 如何导出csv_如何计算指数温度?

指数温度的高低与价格高低没有必然的联系&#xff0c;指数温度的高低反映的是在历史中低于指数当前估值出现的概率。温度越低说明在历史上低于当前估值的概率越小&#xff0c;指数的价值越被低估&#xff0c;上涨的概率越大&#xff1b;温度越高说明在历史上低于当前估值的概率…