1小时学会Python-深度学习原理与实现的1.4节

Python tutorial:Learning Python in an hour

Posted by xuepro on August 11, 2019

1小时学会Python ( Learning Python in an hour )

Python是一个动态类型的高级语言,所谓“动态类型”是指Python能自动从变量值推断其类型。可以用Python内置函数type()查询一个值的类型。如

type(2)

int

type(3.14)
float

Python的print()函数可以输出一系列用逗号’,’隔开的对象,如:

print(2,3.14,"http://hwdong.net",True)
print(type(2),type(3.14),type("http://hwdong.net"),type(False))
2 3.14 http://hwdong.net True
<class 'int'> <class 'float'> <class 'str'> <class 'bool'>

Python的bool类型只有2个逻辑值:True、False,分别表示真和假。Python的str类型表示字符串,字符串是多个字符构成的一个字符序列。Python用双引号或单引号包围一个字符序列表示一个字符串。如果一个字符串中内容占据多行,则用三引号’'’包围来表示。如:

print('''http://hwdong.net is
         a blog teaching computer programming''')
http://hwdong.net is
         a blog teaching computer programming

Python的所有值都以对象形式表示,一个对象包含了值的:内容、类型、id(相当于地址)。如值10的内容是10,它的类型是int,可以用内置函数id()得到其id。

id(10)
140731301598304

变量

给一个对象其一个名字,叫做变量,一个对象可能被多次使用,通过变量名去访问这个对象可避免多次创建同样值得对象,另外还增加了代码得可读性。如:

blog = "hwdong-net.github.io"
print(blog)
blog = "http://"+blog
print(blog)
hwdong-net.github.io
http://hwdong-net.github.io

Python的变量仅仅是对象的名字而不是对象本身,可以随时将同一个变量指向不同的对象。Python的变量仅仅是引用对象。而其他语言如C语言中,变量就是对象本身。

a = 3.14              #a是对象3.14的引用
b = a                 #b和a引用同一个对象3.14
a = "hwdong-net.github.io"      #a引用了新的字符串对象"hwdong.net"
print(a)
print(b)
hwdong-net.github.io
3.14

可以用内置函数,将一种类型值转化为另外一种类型的值,如:

a = int(3.14)
print(a)
print(type(a))
b= float("3.14")
print(b)
print(type(b))
3
<class 'int'>
3.14
<class 'float'>

Python内置函数input(“提示串”)可以用于从键盘输入一个字符串,可以给该函数传递一个提示串,在接受输入字符串,该函数先输出这个提示串。可以将输入的字符串用上述类型转换函数转换为某种类型的数据,如:

score = input("请输入一个学生的分数:")
print(score)
请输入一个学生的分数:78.9
78.9

运算符

可以用运算符直接对(对象)值进行运算。不同类型的值支持的运算是不尽相同的。例如对数值类型(int、float)可以进行算术运算如+、-、*、/、%、//、**。其中%、//、**分别表示求余数、整数除、平方运算。如:

x = 15
y = 2
print('x + y =',x+y)
print('x - y =',x-y)
print('x * y =',x*y)
print('x / y =',x/y)
print('x // y =',x//y)
print('x ** y =',x**y)
print('x % y =',x%y)
x + y = 17
x - y = 13
x * y = 30
x / y = 7.5
x // y = 7
x ** y = 225
x % y = 1

Python的2个字符串可以用加法运算符+,产生的是一个拼接的新字符串,只能对用一个整数和一个字符串用乘法运算符,如:

print("http:"+"//"+"hwdong.net") 
print("hello "*3)
http://hwdong.net
hello hello hello 

不能对2个字符串用乘法运算符或其他运算符如减法运算符。下列语句将出错。

print("hello "*"world")
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-19-f3e4123ae63f> in <module>
----> 1 print("hello "*"world")


TypeError: can't multiply sequence by non-int of type 'str'

对2个值进行比较的比较运算符==、!=、>、<、>=、<=分别表示等于、不等于、大于、小于、大于等于、小于等于。如:

x = 15
y = 2
print('x > y is',x>y)
print('x < y is',x<y)
print('x == y is',x==y)
print('x != y is',x!=y)
print('x >= y is',x>=y)
print('x <= y is',x<=y)
x > y is True
x < y is False
x == y is False
x != y is True
x >= y is True
x <= y is False

逻辑运算符and、or、not分别表示逻辑与逻辑或逻辑非。在逻辑运算中,True或非0或非空对象就是真(True),而False或0或空对象就是假(Fasle)。运算运算符的运算规则是:

  • 对一个对象x,当x是真 (True或非0值或非空值)时,not x就是False,当x是假(False或0或空值)时,not x就是True(真)。
print(not 0)
print(not "")           
print(not False)
print(not 2)
print(not "hwdong")          
True
True
True
False
False
  • 对于2个对象x、y,当x是真时,x or y的结果就是x,当x是假时,x or y的结果就是y。
print(3 or 2)      #因为3是真,3 or 2的结果就是3
print(0 or 2)      #因为0是假,0 or 2的结果就是2
print(False or True)
print(False or "")
print("" or 2)     #因为空字符串""是假,"" or 2的结果就是2
3
2
True

2
  • 对于2个对象x、y,当x是真时,x and y的结果就是y,当x是假时,x and y的结果就是x。
print(3 and 2)           #因为3是真,3 and 2的结果就是2
print(0 and 2)           #因为0是假,0 and 2的结果就是0
print(False and True)
print(True and "")
print("" and 2)          #因为空字符串""是假,"" and 2的结果就是{}
2
0
False
Python还有移位运算符(如位与&、位或 、异或^、取反~、左移«、右移»)等其他运算符。有兴趣读者可以去搜索相关信息。

和C语言等编程语言不同,运算符=主要用于给一个变量起一个名字而不是修改一个变量的值。如:

x=2       # 给对象2起了一个变量名x
x+=3      # 等价于 x= x+2,即变量名x指向了原来x引用的2和3相加的结果对象。

其中“x=2”给对象2起了一个变量名x,而“x+=3”是“x = x+3”的简写形式,即将变量名x指向了原来x引用的2和3相加的结果对象。可以看到运算符=和其他运算符结合如“x+=b”相当于“x = x+b”。运算符=可以和算术运算符和位运算符结合使用。如:

+=  -+   *=  /=   %=   **=  &=  |=  ^=  ~= <<= >>=  
x=3
x**=2
print(x)
x%=2
print(x)
9
1

注意:python没有其他语言的自增运算符++和自减运算符–。

Python的成员运算符用于判断一个值(对象)是否在一个容器对象中。如:

print("h"in"hwdong")
print("h"not in"hwdong")
True
False

身份运算符is和is not用于判断两个变量(标识符)是不是引用的同一个对象。

a = 3.14
b = 3.15
c = a
print(id(a))
print(id(b))
print(a is b)
print(a is not b)
print(a is  c)
1727166941440
1727166941776
False
True
True

对字符串进行操作

除前面的加法运算符+、*外,通常用一些处理字符串的内置函数或字符串类型str的方法对一个字符串进行处理。如:

s = "http://Hwdong.Net"
print(s)                # 用print输出s引用的字符串内容
print(len(s))           # 用len()函数得到s引用的字符串的长度,即字符个数
print(s.capitalize())   #首字母大写
print(s.upper())        #所有字母大写
print(s.lower())        #所有字母小写
print(s.rjust(20))      #右对齐
print(s.center(20))     #中心对齐
print(s.replace('//', '//www.'))    #替换
print('  hwdong '.strip()+".net")   #裁剪
print(s)
http://Hwdong.Net
17
Http://hwdong.net
HTTP://HWDONG.NET
http://hwdong.net
   http://Hwdong.Net
 http://Hwdong.Net  
http://www.Hwdong.Net
hwdong.net
http://Hwdong.Net

注意,字符串对象是“不可以被修改的”,所有修改性操作实际返回的是一个新字符串,而原来的字符串并没有被修改!

还有可以在字符串里用格式符%来将一些数据格式化到字符串中,创建一个新字符串。如:

s2 = '%s %s %f' % ("The score", "of LiPing is: ", 78.5)
print(s2)
The score of LiPing is:  78.500000

也可以用字符串str的format()方法对一个字符串格式化,即将字符串中的占位符{}依次替换为format()方法中的数据。如:

print ("{} {} {}".format("The score", "of LiPing is: ", 78.5)) 
The score of LiPing is:  78.5

可以通过指定一个下标访问字符串的某个字符,下标从0开始,长度为n的字符串的下标为$0,1,2\cdots,n-1$,下标甚至可以是负整数,其中-1指的是最后一个字符,-n指的是第1个字符。

s = "hwdong"
print(s[0], s[1], s[2], s[3], s[4], s[5])
print(s[-1],s[-5],s[-4],s[-3],s[-2],s[-1])
h w d o n g
g w d o n g

对于一个字符串s,s[start:end:step]表示创建一个从起始位置start开始,直到结束位置end,间隔步长为step的所有字符(不包括end位置的字符)构成的一个新字符串。如果没有指定step,则默认为1。如:

s = "hwdong.net"
print(s[1:6:2])
print(s[-1:-6:-2])
print(s[1:6])
wog
tng
wdong

if语句

if关键字后面跟一个表示某种条件的表达式,当该表达式为True或非空值时,就执行if语句中的程序块。其格式如下:

if 表达式:
    程序块

如:

score = 65.5
if score>=60:
   print("恭喜你!")
   print("通过了考试。")

恭喜你!
通过了考试。

注意:

  • if 表达式后面要有冒号:
  • Python中通过对齐方法表示一组语句属于同一个程序块,而其他语言如C、Java通常需要用一对{}包为统一程序块的语句。

Python中属于同一个程序块的代码如果正确的缩进,Python解释器会报错的。如:

score = 65.5
if score>=60:
   print("恭喜你!")
  print("通过了考试。")
  File "<tokenize>", line 4
    print("通过了考试。")
    ^
IndentationError: unindent does not match any outer indentation level

if和else可以结合使用,表示“如果…否则…”的意思。即当if中的条件表达式为True,则执行if子句中的程序块,否则执行else子句中的程序块。else后面不需要条件表达式。 其格式是:

if 表达式:
    程序块
else
    程序块2

如:

score= int(input("请输入学生成绩:"));
if score>=60:
    print("恭喜你!")
    print("通过了考试。")
else:
    print("你未通过考试。")
    print("继续努力,加油!")
请输入学生成绩:45
你未通过考试。
继续努力,加油!

对于多个条件可以用if的另一种形式“if…elif…else”,即“如果…否则如果…否则”的意思。

if 表达式1:
   程序块1
elif 表达式2:
   程序块2
elif 表达式3:
   程序块3.
else:
   程序块k

如:

score= int(input("请输入学生成绩:"));
if score<60:
    print("不及格")
elif score<70:
    print("及格")
elif score<80:
    print("中等")
elif score<90:
    print("良好")
else:
    print("优秀");
请输入学生成绩:79
中等

while语句

while语句的格式如下

while 表达式:
      程序块

即,当关键字while里的“表达式”为True,就重复执行其中的程序块。如:

i = 1
s = 0
while i<=100:
   s = s+i;      #等价于  s += i
   i+=1
print(s)
5050

再如,统计键盘输入的一组学生分数的平均分,可以用下列代码是实现:

total_score=0
i= 0
score = float(input("请输入学生成绩:"))
while True:
    total_score += score
    i += 1
    score = float(input("请输入学生成绩:"))
    if  score<0:
        break                           #关键字break用于跳出循环   
    
print('平均成绩为:', total_score/i) 
请输入学生成绩:45
请输入学生成绩:78
请输入学生成绩:93
请输入学生成绩:-1
平均成绩为: 72.0

在循环的程序块里嵌套了一个if条件语句,其中又有一个break关键表示的语句,表示跳出整个循环。

for语句

for关键表示的也是一个循环语句,表示迭代访问一个容器对象中的每个元素。格式为:

for e in container:
    程序块

表示循环访问容器对象container中的每个元素e,执行其中程序块的语句。如:

for ch in "hwdong":
    print(ch,end=" ")
h w d o n g 

print()函数的参数end表示print()函数输出内容后的结束字符,默认是”\n”表示换行符,这里用空格符” “代替了”\n”。因此,输出ch后,print并没有换行,而是输出一个空格。

Python常用容器类型

如同一个字符串是一些字符的容器一样,Python提供了list、tuple、set、dict等容器类型。

list(列表)

列表list是一组数据元素(对象)的有序序列,定义列表对象是用一对左右方括号[ ]包围、数据元素之间用逗号隔开。如:

[1,2,3]
type([1,2,3])

list中的数据元素可以是不同的类型,甚至是包含其他对象的list对象,如:

[2, 3.14, 'python']
[2, 3.14,True,[3,6,9],'python']

和字符串一样,可以用一个下标访问(修改)其中的一个元素,也可以用[start:end:step]访问(修改)其中的多个元素。

my_list =[2, 3.14,True,[3,6,9],'python']
print(type(my_list))  #打印my_list的类型,即list类型
print(my_list)
print("my_list[0]:",my_list[0])
print("my_list[3]:",my_list[3])
print("my_list[-2]:",my_list[-1])
print("my_list[:]:",my_list[:])        #所有元素
my_list[2:4] = [13, 9]
print(my_list)
<class 'list'>
[2, 3.14, True, [3, 6, 9], 'python']
my_list[0]: 2
my_list[3]: [3, 6, 9]
my_list[-2]: python
my_list[:]: [2, 3.14, True, [3, 6, 9], 'python']
[2, 3.14, 13, 9, 'python']

当然可以用for循环等访问一个list对象中的元素。如:

for e in my_list:
    print(e,end=" ")
2 3.14 13 9 python 

甚至可以用for循环遍历一个容器或可迭代对象的方式来创建一个新的list对象。如:

alist = [e**2 for e in [0,1,2,3,4,5]]
print(alist)
[0, 1, 4, 9, 16, 25]

表示对[1,2,3,4,5]的每个元素e计算e**2,用这些值创建了一个list对象。python的一个内置函数range(n)是一个产生0到n之间整数(不包括n)的迭代器对象。下列代码可产生同样的结果:

alist = [e**2 for e in range(6)]
print(alist)
[0, 1, 4, 9, 16, 25]
上述这种通过在[]中迭代计算产生值创建一个新list对象的式子叫做列表解析式”。其中还可以包括更加复杂的计算式子如包含条件语句
alist = [0, 1, 2, 3, 4,5]
alist = [x ** 2 for x in alist if x % 2 == 0]
print(alist)  
[0, 4, 16]

tuple(元组)

和list一样,tuple(元组)也是一组数据元素(对象)的有序序列,也就是每个元素也有唯一的下标。定义tuple是用圆括号而不是方括号。如:

t = ('python',[2,5],37,3.14,"https://hwdong.net")
print(type(t))
print(t[1:4])
print(t[-1:-4:-1])
<class 'tuple'>
([2, 5], 37, 3.14)
('https://hwdong.net', 3.14, 37)

list中的元素是可以修改的。

print(alist)
alist[1] = 22
print(alist)
[0, 4, 16]
[0, 22, 16]

tuple中的元素是不可以被修改的,如同字符串中的元素是不可以被修改的。

t[1]=22
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-142-70d00e4ef536> in <module>
----> 1 t[1]=22


TypeError: 'tuple' object does not support item assignment

可以用()的解析式创建一个可迭代对象而不是tuple对象,如:

nums = (x**2 for x in range(6))
print(nums) 
for e in nums:
    print(e,end= " ")
<generator object <genexpr> at 0x00000192233DB8B8>
0 1 4 9 16 25 

set(集合)

set是不包含重复元素的无序集合。set是用左右花括号{}包围的以逗号隔开的一组元素。元素的类型可以是不同的。如:

s = {5,5,3.14,2,'python',8}
print(type(s))
print(s)
<class 'set'>
{2, 3.14, 5, 8, 'python'}

可以用add()和remove()函数向一个集合中添加和删除一个元素,而list对象可以用append()或insert()函数追加或插入元素,pop() 用于删除最后一个元素,remove()则是删除第一个指定值的元素。

s.add("hwdong")
print(s)
s.remove("hwdong")
print(s)
alist.append("hwdong")
print(alist)
alist.insert(2,"net")
print(alist)
alist.pop()
print(alist)
alist.remove("net")
print(alist)
{2, 3.14, 5, 'hwdong', 8, 'python'}
{2, 3.14, 5, 8, 'python'}
[0, 22, 16, 'hwdong']
[0, 22, 'net', 16, 'hwdong']
[0, 22, 'net', 16]
[0, 22, 16]

但不可修改对象如tuple则没有append()或insert()之类的函数用于添加元素。下列代码是错误的:

t.append("hwdong")
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-133-34fd50c7f43a> in <module>
----> 1 t.append("hwdong")


AttributeError: 'tuple' object has no attribute 'append'

可以用{}的解析式创建一个set对象,如:

nums = {x**2 for x in range(6)}
print(nums) 
{0, 1, 4, 9, 16, 25}

dict(字典)

dict是一个 (key-value pairs) “键-值”对的无序集合。每个元素都以“键:值(key:value)”的形式存储的。如:

d = {1:'value', 'key':2, 'hello': [4,7]}
print(type(d))
print(d)
<class 'dict'>
{1: 'value', 'key': 2, 'hello': [4, 7]}

需要通过key(键,也称为关键字)才能访问dict中这个key对应元素的值value。如:

d['hello']
[4, 7]

如果一个key对应的元素不存在,通过这个key访问元素是非法的,如:

d[3]
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-156-0acadf17a380> in <module>
----> 1 d[3]


KeyError: 3

但可以给一个不存在的key赋一个值(value),将在这个set中添加一个“键-值”对的元素。如:

d[3] = "python"
print(d)
print(d[3])
{1: 'value', 'key': 2, 'hello': [4, 7], 3: 'python'}
python

可以定义一个表示学生信息并以名字作为关键字的dict对象:

students={"LiPing":[21,"计科01",15370203152],"ZhangWei":[20,"计科02",17331203312]
         ,"ZhaoSi":[22,"机械03",16908092516]}
print(students)
print(students["ZhangWei"])
{'LiPing': [21, '计科01', 15370203152], 'ZhangWei': [20, '计科02', 17331203312], 'ZhaoSi': [22, '机械03', 16908092516]}
[20, '计科02', 17331203312]

可以通过for…in循环语句访问字典中的元素,如:

for name in students:
    info = students[name]
    print('{}\'s info: {} '.format(name, info))   
LiPing's info: [21, '计科01', 15370203152] 
ZhangWei's info: [20, '计科02', 17331203312] 
ZhaoSi's info: [22, '机械03', 16908092516] 

注意:单引号’的字符串中不能直接包含单引号’需要用反斜杠字符\和单引号’构成的转义字符表示单引号字符’。在双引号字符”的字符串中包含双引号字符,则也需要用转移字符"。

上述for循环中的name表示的是字典对象的key(键),如果向同时获得键(key)和值(value),则可以用dict类的item()方法获得一个字典对象的所有键-值:

for key,value in students.items():
    value = students[key]
    print('{}\'s info: {} '.format(key,value)) 
LiPing's info: [21, '计科01', 15370203152] 
ZhangWei's info: [20, '计科02', 17331203312] 
ZhaoSi's info: [22, '机械03', 16908092516] 

当然,也可以用一个{}解析式创建一个字典对象,如:

points = {x:x**2 for x in range(6)}
print(points) 
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

函数

Python通过关键字def定义函数,给一个程序块起一个名字,然后就可以通过函数名去调用执行这个函数块中的代码。

下面的代码首先用关键字import导入了数学函数库math,其中有一个表示PI的常量math.pi,然后定义了一个函数名是circle_area的函数,此后,可以通过函数名circle_area调用上面的circle_area()函数。

#定义一个函数名是circle_area的函数
import math             #导入数学函数库math,其中有一个表示PI的常量math.pi
def circle_area():
    area = math.pi*2.5**2
    print("半径是2.5的圆面积是:%f"%area)    

circle_area()    #通过函数名circle_area调用上面的circle_area()函数
半径是2.5的圆面积是:19.634954

函数名后面的()里是函数的参数,调用该函数的代码可以将相应的数值传给对应的函数参数。如给上面函数添加一个表示半径的参数r。在调用时,也必须提供实际数值给这个参数r。

import math             
def circle_area(r):
    area = math.pi*r**2
    print("半径是%5.2f的圆面积是:%5.2f"%(r,area))    #格式符%5.2f表示输出的是float类型的数,占据5位宽,小数点后是2位

circle_area(2.5)    #通计算半径是2.5的圆面积
circle_area(3.5)    #通计算半径是3.5的圆面积
半径是 2.50的圆面积是:19.63
半径是 3.50的圆面积是:38.48

函数内部可以通过return返回,即结束函数的执行,return还可以返回一些数值。如:

import math             
def circle(r):
    area = math.pi*r**2
    perimeter = 2*math.pi*r
    return area,perimeter    

area,p = circle(2.5)   
print("半径是2.5的圆面积和周长是:%5.2f,%5.2f"%(area,p))
area,p =circle(3.5)   
print("半径是3.5的圆面积和周长是:%5.2f,%5.2f"%(area,p))
半径是2.5的圆面积和周长是:19.63,15.71
半径是3.5的圆面积和周长是:38.48,21.99

函数的参数可以有默认值,如果调用函数时,没有提供相应的参数。

def pow(x,n=2):
    ret = 1
    for i in range(n):
        ret *=x
    return ret

print(pow(3.5))
print(pow(3.5,3))        
12.25
42.875

定义函数时,默认参数必须排在非默认参数的后面。下面函数定义是错误的。

def pow(a,b=2,c):
    return a+b+c

一个函数内部可以存在调用其他函数的语句,函数也可以作为另外函数的参数。

下面的函数solve_iterative()用于求f(x)=y的方程的根,参数lower、 upper是求解区间的左右端点,参数f可以接受一个函数,参数y是一个数值。假设f表示的是一个单挑递增的函数,函数solve_iterative()采用二分法去计算区间中点middle的值f(middle)是否和y足够接近。如果没有,则在左半区间或右半区间重复这个过程。

函数area()计算半径r的圆面积,最后调用solve_iterative()去求半径0.5和0.6之间圆面积为1的那个圆的半径是什么?

import math   
def solve_iterative(f, y, lower=0, upper=1):
    middle = (lower + upper) / 2
    while math.fabs(f(middle) - y) >= 1e-6:
        print("lower:", lower, "upper:", upper)
        if f(middle) < y:
            lower = middle
        else:
            upper = middle        
        middle = (lower + upper) / 2
    return middle

def area(r):    
    return (r ** 2) * math.pi

print("0.5和0.6之间圆面积为1的那个圆的半径是:", solve_iterative(area, 1, 0.5, 0.6))
lower: 0.5 upper: 0.6
lower: 0.55 upper: 0.6
lower: 0.55 upper: 0.575
lower: 0.5625 upper: 0.575
lower: 0.5625 upper: 0.56875
lower: 0.5625 upper: 0.565625
lower: 0.5640625 upper: 0.565625
lower: 0.5640625 upper: 0.5648437500000001
lower: 0.5640625 upper: 0.564453125
lower: 0.5640625 upper: 0.5642578125
lower: 0.56416015625 upper: 0.5642578125
lower: 0.56416015625 upper: 0.564208984375
lower: 0.5641845703125 upper: 0.564208984375
lower: 0.5641845703125 upper: 0.56419677734375
lower: 0.5641845703125 upper: 0.564190673828125
lower: 0.5641876220703126 upper: 0.564190673828125
lower: 0.5641891479492188 upper: 0.564190673828125
0.5和0.6之间圆面积为1的那个圆的半径是: 0.5641895294189454

当然,一个函数可以在其内部调用自身,这种函数称为递归函数。下面求一个正整数n的阶乘的函数,当n=1时,直接返回1,否则将 n!转化为n*(n-1)!的问题。

def fact(n):
    if n==1:             #如果n等于1,就直接返回值1
        return 1
    return n * fact(n - 1)  #如果n大于1,就是n和fact(n-1)的乘积
fact(4)             # 输出: 24
24

作为练习,读者可以尝试将上面的求方程f(x)=y根的函数写成递归函数的形式。

类(class)是对一个抽象概念的描述,它描述了属于同一个概念的所有对象的共同属性,这些属性有:数据属性和方法属性。数据属性描述了该类对象的状态,而方法属性描述了该类对象具有哪些功能。一个类就是一个数据类型,它刻画了这种类型的所有可能值的的共同属性,如int类型刻画了所有整数的特性。

前面的str、list等都是类。一般的,可以通过类名创建一个类对象,类对象是一个具体的对象。如:

s = str("http://hwdong.net")
location = s.find("hwdong")     #通过str的find()方法查询是否存在一个子串,返回子串的位置
print(location)
alist = list(range(6))
blist = alist.copy()
blist[2] = 20
print(alist)
print(blist)
7
[0, 1, 2, 3, 4, 5]
[0, 1, 20, 3, 4, 5]

可以看到,可以通过一个类对象用“成员访问运算符.”访问类的方法,对这个对象执行某种操作(访问某些信息或修改该对象或创建新对象)。例如,s.find()在s中查询是否存在一个子串,返回子串的位置。而alist.copy()复制创建了一个和alist一样内容的list对象并使blist引用这个新创建的list对象。

Python中用关键字class定义一个类。为了刻画所有学生的共同属性,可以定义一个Student类。

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score
        
    def print(self):
        print(self.name,",",self.score)

类中的函数称为方法,通过一个类对象调用一个类的方法,就可以对这个类对象进行各种操作,因为一个类的对象可以右很多个,类的方法一般只对一个具体对象进行操作,因此,一般的方法的第一个参数都是self,表示调用这个类方法的是哪个对象。

下面代码定义了Student类的2个对象s1和s2:并通过它们调用了类Student的print()方法。Student的print()方法又调用了内置的函数print()输出self指向对象的姓名和分数。

s1 = Student("LiPing",67)
s2 = Student("WangQiang",83)
s1.print()
s2.print()
LiPing , 67
WangQiang , 83

类的中__init__()是一个特殊方法,称为构造函数,在定义类的对象时,会自动调用这个构造函数,对self指向的类对象进行初始化。如定义了2个类对象属性name和score并用构造函数的参数对它们进行初始化。

每个对象都有自己单独的实例属性,改变一个对象的实例属性不会影响其他对象的实例属性。除了实例属性外,还可以给一个类定义类属性,类属性是类的所有对象都共享的属性。类属性是定义在类的方法外面的属性。

如修改的Student类添加了一个类属性count,表示从这个类创建了多少具体的类对象,其初始值为0,每当创建一个类对象时,就增加其计数。

class Student:
    count=0
    def __init__(self, name, score):
        self.name = name
        self.score = score
        Student.count +=1
        
    def print(self):
        print(self.name,",",self.score)

一般的都是通过“类名.类属性”来查询或修改类属性,如“Student.count”,也可通过“实例名.类属性”(包括self.类属性)来查询实例属性。如下面的s1.count。

print(Student.count)
s1 = Student("LiPing",67)
print(s1.count)
s2 = Student("WangQiang",83)
print(Student.count)
0
1
2

Matplotlib

Matplotlib是一个Python语言的2D绘图库,windows系统下以管理员权限打开命令行窗口,然后执行下列命令安装它。

pip install matplotlib

Linux或Mac可以需要管理员权限,即执行:

sudo pip install matplotlib

matplotlib的pyplot模块提供了简单的绘图函数,可以用下面的代码导入matplotlib.pyplot模块并命名为plt,可避免在代码中写一长串的matplotlib.pyplot。

import matplotlib.pyplot as plt

pyplot模块的plot()函数可以直接绘制2D数据,如:

y = [i for i in range(10)]
print(y)
plt.plot(y)           #  绘制y作为纵轴坐标点构成的图形
plt.show()            #  调用plt.show()显示图形
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]    

尽管只给了纵轴坐标的数组y,plot()函数默认会自动生成从0开始的横轴坐标。当然,可以分别传递2个数组表示x和y坐标,如:

x = [i*0.1 for i in range(10)]
y = [xi**2 for xi in x]
print(["{0:0.2f}".format(i) for i in x])
print(["{0:0.2f}".format(i) for i in y])
plt.plot(x, y)        #  绘制(x,y)坐标点构成的图形
plt.show()            #  调用plt.show()显示图形
['0.00', '0.10', '0.20', '0.30', '0.40', '0.50', '0.60', '0.70', '0.80', '0.90']
['0.00', '0.01', '0.04', '0.09', '0.16', '0.25', '0.36', '0.49', '0.64', '0.81']

可以同时绘制几个曲线。

x = [i*0.2 for i in range(10)]
y = [xi**2 for xi in x]
y2 = [3*xi-1 for xi in x]

plt.plot(x, y)        #  绘制(x,y)坐标点构成的图形
plt.plot(x, y2)  
plt.ylim(0,5)
plt.xlabel('x axis label')
plt.ylabel('y axis label')
plt.title('y=x^2 and y=3x-1')
plt.legend(['y=x^2', 'y=3x-1'])
plt.show()            #  调用plt.show()显示图形

其中pyplot模块的函数title()用于给图起一个标题,而legend()则给每个绘制的曲线一个名字,xlim()和ylim()用于限定x和y坐标的范围,xlabel()和ylabel()用于给x轴和y轴一个标签。可以看到不同的图形将自动用不同的颜色显示。

plot()函数还可以接受一些参数,用于定制绘制的图形的样式,如:

import math
x = [i*0.2 for i in range(50)]
y = [math.sin(xi) for xi in x]
y2 = [math.cos(xi) for xi in x]
y3 = [0.2*xi for xi in x]
plt.plot(x, y,'r-')        
plt.plot(x, y2,'bo')  
plt.plot(x, y3,'g:')  
plt.legend(['sin(x)', 'cos(x)','0.2x'])
plt.show()           

其中’r-‘的r表示红色(red)、-表示短线,’bo’的b表示蓝色(blue)、o表示以圆点,’g:’的g表示绿色(green)、:表示虚线。

pyplot模块除了plot()函数可以绘图外,还有其他的一些函数用于绘制其他类型的图,如 scatter()用于绘制散乱点图。如:

import math
x = [i*0.2 for i in range(50)]
y = [math.sin(xi) for xi in x]
y2 = [math.cos(xi) for xi in x]
y3 = [0.2*xi for xi in x]
plt.scatter(x, y, c='r', s=6, alpha=0.2)        
plt.scatter(x, y2,c='g', s=18, alpha=0.9)  
plt.scatter(x, y3,c='b', s=30, alpha=0.4)  
plt.legend(['sin(x)', 'cos(x)','0.2x'])
plt.show() 

其中参数c表示颜色,其值’r’、’g’、’b’分别表示红、绿、蓝,s参数表示点的大小,alpha表示图的透明性。

bar()函数用来绘制条形图。条形图常常用来描述一组数据的对比情况。如下面代码用bar()函数计科6个班级的平均分数:

classes=['CS1901','CS1902','CS1903','CS1904','CS1905','CS1906']
scores = [76.5, 60.5, 85.0,45.5,79.3,91]
plt.bar(classes, scores, color='green')   #color参数表示颜色,'green'表示绿色
plt.xlabel('班级名')
plt.ylabel('平均分')
plt.show() 

pie()函数用来绘制饼状图。饼状图通常用来表达集合中各个部分的百分比。下面代码将上述的scores以百分比的饼状图形式显示,其中的labels是这些百分比对应的标签。legend()函数用参数loc指定在右上角’upper right’显示这些标签。

classes=['CS1901','CS1902','CS1903','CS1904','CS1905','CS1906']
scores = [76.5, 60.5, 85.0,45.5,79.3,91]
plt.pie(scores,labels = classes, autopct='%1.1f%%')
plt.legend(loc='upper right')
plt.show() 

hist()函数用来绘制直方图。直方图看起来是条形图有些类似。但它们的含义是不一样的,直方图描述了数据中某个范围内数据出现的频度。

import random
data=[random.normalvariate(2, 3) for i in range(500)]
bins = [-8, -6, -4,-2,0,2,4,6,8,10]
plt.hist(data, bins=bins)
plt.show()

可以看到在bins数组表示的不同范围里的数据点个数是不一样的,[-8,-6]个数很少,而[0,2][2,4]范围的数据点个数很多。直方图以条形图形式直观显示了每个区间的数据点个数。

显示图形的窗口figure对象除了可以显示多个图形外,

还可以用多个子区域来显示不同的图形。可以用subplot()函数指定子图绘制在那个子图窗口中。

subplot(numRows, numCols, plotNum)

其参数numRows, numCols, plotNum分别指定行数、列数和子图的序号。在绘制子图中的图形前,先调用subplot()指明在那个位置的子图上绘制图形,并可以用title()函数设置子图的标题。如:

import math
x = [i*0.2 for i in range(50)]
y = [math.sin(xi) for xi in x]
y2 = [math.cos(xi) for xi in x]
y3 = [0.2*xi for xi in x]

fig = plt.gcf()
fig.set_size_inches(12, 4, forward=True)

plt.subplot(1, 2, 1)
plt.plot(x, y,'r-') 
plt.plot(x, y2,'bo')  
plt.title('sin(x) and cos(x)')
plt.legend(['sin(x)', 'cos(x)'])

plt.subplot(1, 2, 2)
plt.plot(x, y3,'g:')  
plt.title('0.2x') 


plt.show()    

上述代码,先通过fig = plt.gcf()得到当前绘图窗口的figure对象并赋值给遍历fig,然后通过调用figure的set_size_inches()函数修改默认的figure对象的宽高,forward=True表示立即更新当前窗口的figure对象大小。

可以用imshow()显示一幅图像,在这之前可以用skimage库的io模型的imread()函数读取图像。读取的图像放在一个多维数组库numpy的多维数组ndarray对象中。numpy模型可以有很多方便的函数处理多维数组,如uint8()函数可以将其他数据元素类型的numpy数组转化为uint8类型即无符号整数类型(取值范围是[0,255]),也可用运算符*进行逐元素的乘积。

import numpy as np
import skimage 
import matplotlib.pyplot as plt

img = skimage.io.imread('imgs/lenna.png')    #原图
img_tinted = img * [1, 0.95, 0.9]    #3个颜色通道值乘以不同的系数

plt.subplot(1, 2, 1)
plt.imshow(img)

plt.subplot(1, 2, 2)
plt.imshow(np.uint8(img_tinted))  #将实数值的img_tinted图像转换为unit8无符号整型
plt.show()

觉得文章对您有用,帮忙点击博客上面的广告哦!谢谢!

关注:

jupyter notebook请访问这个网址(Please visit this link)

https://github.com/hwdong-net/python


支付宝打赏 微信打赏

您的打赏是对我最大的鼓励!