Python入门

本文最后更新于:2020年5月17日 晚上

概览:本文是Python3.x的简易学习笔记。

基本数据类型

整数:int 8

浮点数: float 8.8

字符串: str “8个人部分股”

布尔值:bool True False

查看数据类型

1
2
type(8) 可以返回变量的基本类型
id(8) 可以返回变量所指的内存地址

类型转换

1
2
3
str --> intint('8')
int --> str : str(123)
int --> boolbool(123) = True

序列

字符串、列表、元组三种类型都属于序列。

1
2
3
字符串: "abcd"
列表: [0, 'abcd']
元组: ("abc", "def")

列表存储的内容可变更

但是元组存储的内容不可变更

序列的基本操作

切片操作 – [0:整数]

1
2
3
chineseZodiac = "鼠牛虎兔龙蛇马羊猴鸡狗猪"

print(chineseZodiac[0:4]) # 鼠牛虎兔 [0,4) 左闭右开
1
2
3
4
5
6
7
# 切片语法
sname[start : end : step]

#sname:序列的名称
#start:切片开始的位置,包括该位置
#end: 切片截至的位置,但不包括该位置
#step: 切片的步长,如果省略,默认为1

成员关系 – in、not in

1
2
3
print('狗' in chineseZodiac)  # True

print('狗' not in chineseZodiac) # False

连接操作 – 序列+序列

1
print(chineseZodiac + 'abcd')

重复操作 – 序列 * 整数

1
2
3
chineseZodiac = "猴鸡狗猪鼠牛虎兔龙蛇马羊"

print(chineseZodiac * 3) #猴鸡狗猪鼠牛虎兔龙蛇马羊猴鸡狗猪鼠牛虎兔龙蛇马羊猴鸡狗猪鼠牛虎兔龙蛇马羊

序列长度

1
len() #计算列表的长度

字符串、元组、列表

1
2
3
4
5
6
chineseZodiac = "鼠牛虎兔龙蛇马羊猴鸡狗猪" # <class 'str'>

zodiac_name = (u'摩羯座',u'水瓶座',u'双鱼座',u'白羊座',u'金牛座',u'双子座',
u'巨蟹座',u'狮子座',u'处女座',u'天秤座',u'天蝎座',u'射手座') #<class 'tuple'>

alist = ['abc', 'xyz'] #<class 'list'>

列表推导式

1
2
3
4
5
6
7
8
9
10
11
#普通方式的列表
alist = []
for i in range(1,11):
if(i%2 == 0):
alist.append(i*i)

print(alist) # [4, 16, 36, 64, 100]

#列表推导式
blist = [i*i for i in range(1,11) if(i%2 == 0)]
print(blist) # [4, 16, 36, 64, 100]

字符串的一些操作

1
2
3
split('|') -- 将字符串按照符号“|”来进行分割成为一个列表
strip('\n') -- 将字符串里的换行符剔除
replace('a','b') -- 将字符串里的字母'a'全都替换成为字母'b'

字典

字典是无序的可变序列。保存的内容是以“键值对”的形式存放的。

类似于C++中的map。

特征:

字典中的键值必须唯一,且不能够改变。所以列表不能作为字典的键。

字典是通过键值来读取的,字典也称为散列表(hash)。不能向序列那样通过索引获取值。

字典是无序集合,各项随机排列,这样能够提高查找的效率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
dict1 = {'x':1, "y":2}

print(type(dict1)) #<class 'dict'>
print(dict1) #{'x': 1, 'y': 2}

dict1['z'] = 3
print(dict1) #{'x': 1, 'y': 2, 'z': 3}

# 通过键值去遍历字典
for each_key in dict1.keys():
print(each_key + ":" + str(dict1[each_key]))
# x: 1
# y: 2
# z: 3

#遍历键值对列表
for item in dict1.items():
print(item)
# ('x', 1)
# ('y', 2)
# ('z', 3)

dict1.clear()
print(dict1) #{}

字典推导式

1
2
3
4
5
6
7
8
# 普通方式
dict1 = {'x':1, 'y':1, 'z':1}
print(dict1) #{'x': 1, 'y': 1, 'z': 1}

# 字典推导式
str1 = 'xyz'
dict2 = {i:1 for i in str1}
print(dict2) #{'x': 1, 'y': 1, 'z': 1}

流程控制

条件语句

1
2
3
4
5
6
7
8
9
10
chineseZodiac = "猴鸡狗猪鼠牛虎兔龙蛇马羊"

year = int(input('请用户输入年份:'))

if chineseZodiac[year%12] == '狗':
print("狗年发大财")
elif chineseZodiac[year%12] == '猪':
print("猪年快乐")
else:
print("笑口常开")

for循环

1
2
3
4
5
6
7
8
9
10
chineseZodiac = "猴鸡狗猪鼠牛虎兔龙蛇马羊"

for i in chineseZodiac:
print(i)

for i in range(13):
print(i) #0-12

for year in range(2000,2020):
print("%s 年的生肖是 %s" %(year,chineseZodiac[year%12]))

while循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
while True:
print('a')
break

###############

num = 5
while True:
print(num)
num += 1
if num > 10:
break


##########
num = 5
while True:
num += 1
if num == 10:
continue
print(num)
if num > 15:
break;

👍元组中的filter

1
2
3
4
5
6
7
8
zodiac_name = (u'摩羯座',u'水瓶座',u'双鱼座',u'白羊座',u'金牛座',u'双子座',
u'巨蟹座',u'狮子座',u'处女座',u'天秤座',u'天蝎座',u'射手座')
zodiac_day = ((1,20),(2,19),(3,21),(4,21),(5,23),(6,22),
(7,23),(8,23),(9,23),(10,23),(11,23),(12,23))
(month,day) = (2,11)
zodiac = filter(lambda x: x<=(month,day), zodiac_day)
zodiac_len = len( list(zodiac) ) # 取出长度
print(zodiac_name[zodiac_len%12]) #水瓶座
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
zodiac_name = (u'摩羯座',u'水瓶座',u'双鱼座',u'白羊座',u'金牛座',u'双子座',
u'巨蟹座',u'狮子座',u'处女座',u'天秤座',u'天蝎座',u'射手座')
zodiac_day = ((1,20),(2,19),(3,21),(4,21),(5,23),(6,22),
(7,23),(8,23),(9,23),(10,23),(11,23),(12,23))
# 用户输入月份与日期
month = int(input("请输入月份:"))
day = int(input("请输入日期:"))

for zo in range(len(zodiac_day)):
if (month,day) <= zodiac_day[zo]:
print("出生于%s月%s日的星座是%s" %(month,day,zodiac_name[zo]))
break
elif month == 12 and day > 23:
print("出生于%s月%s日的星座是摩羯座" % (month, day))
break

文件读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# ‘w':文件不存在会新建、文件存在会覆盖
file1 = open('name.txt','w')
file1.write("hello,Python")
file1.close()

# 文件读取也叫做输入,文件写入也叫做输出

# 'r':文件不存在就报错
file2 = open("name.txt",'r')
str = file2.readline()#读取一行
print(str)
file2.close()

# 'a':append追加,文件不存在就新建,文件存在就将内容添加到末尾
file3 = open("name.txt","a")
file3.write("你好/n哈哈")
file3.close()

# readlines()读取多行,返回值是list
file4 = open("name.txt", 'r')
for line in file4.readlines():
print(line)
print("===")

# 文件指针,使用tell()获得文件指针
file5 = open("name.txt",'r')
print(file5.tell()) #指针位置为0
print(file5.read(1)) #打印第一个字符
print(file5.tell()) #现在的指针位置为1

file5.seek(0) #文件指针回到0
print(file5.tell()) #指针位置为0

file6 = open("name.txt",'r')
print(file6.tell())#0
file6.seek(5,0)
print(file6.tell())#5

#seek()函数有两个参数时,第一个参数代表偏移量,第二个参数代表从什么位置开始计算
# 对于第二个参数:0 表示从文件头开始计算, 1 表示从当前位置开始计算,2 表示从文件尾开始计算
#注意!如果在打开文件时,没有使用b模式,那么只允许从文件头开始计算相对偏移量

文件打开的三个参数

1
file = open("test.txt",'r',encoding='utf-8')

打开文件使用with语句–上下文管理器

1
2
3
with open("name.txt",'r') as file:
for line in file.readlines():
print(line)

Python打开文件要及时关闭,忘记关闭可能会带来问题,另外如果在打开文件是出现了异常,那么将导致文件不能及时被关闭,为了避免此类问题,可以使用上述的with语句进行操作。

这样在处理文件时,无论是否抛出了异常,都能保证with语句执行完毕后关闭已经打开的文件

异常

常见异常

简单的异常处理语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
try:
year = int(input("请输入年份:"))
except ValueError:
print("年份应该输入数字")

a = 123
try:
a.append('a')
except AttributeError:
print('数字没有append方法')

try:
print(1/0)
except ZeroDivisionError as e:
print('0不能作为除数:',e) #0不能作为除数: division by zero

#捕获未知类型的异常
try:
print(1/'a')
except Exception as e:
print(e)

#try...except...else语句
try:
print(1/1)
except Exception as e:
print(e)
else:
print("正常执行")

try…except…finally语句

finally语句用来放置无论是否发生异常都会被执行的代码。例如:打开文件是使用此语句,释放资源的代码放在finally语句之中。

使用raise语句抛出异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def div():
num1 = int(input('请输入被除数:'))
num2 = int(input('请输入除数:'))
if num2 == 0:
raise ValueError("除数不能为0.")
result = num1 / num2
print(result)

if __name__ == "__main__":
try:
div()
except ZeroDivisionError:
print("\nerror!除数不能为0")
except ValueError as e:
print("输入错误:",e)

如果某个函数或者方法可能会产生异常,但不想在当前函数或方法中处理这个异常,则可以使用raise语句在函数或者方法中抛出异常。

assert断言语句

1
2
3
4
5
6
7
8
9
10
11
12
def div():
num1 = int(input('请输入被除数:'))
num2 = int(input('请输入除数:'))
assert num2 != 0, "除数不能为0"
result = num1 / num2
print(result)

if __name__ == "__main__":
try:
div()
except AssertionError as e:
print("\nerror!",e)

断言语句的基本格式为

1
2
3
4
assert expression , reason

expression:是条件表达式,表达式为True时什么都不做,为False时抛出AssertionError异常。
reason:描述异常信息,可写可不写

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#统计单词出现次数

import re #一个模块

def find_word(word):
with open('Stone.txt',encoding='GBK') as f:
data = f.read().replace('\n','')
words = re.findall(word, data) #函数的返回值时list
return len(words)


#读取人物信息
with open("name.txt") as f:
words = f.read().split('|')
for w in words:
print("'",w,"'",'出现了:',find_word(w))
# ' 密苏里 ' 出现了: 3
# ' 他 ' 出现了: 17
# ' 斯通纳 ' 出现了: 6
# ' 的 ' 出现了: 52

定义函数

1
2
def function(形参列表):
函数体

如上所示,使用def来定义一个函数,如果函数有返回值的时候可以通过return语句返回。如若想定义一个空函数的画,可以使用pass作为占位符。

当函数中没有return语句时,或者省略了return语句后面的内容,将会返回None,即返回空值

参数传递

Python参数传递分为值传递和引用传递两种。

  • 当实参是不可变对象时,进行的是值传递
  • 当实参为可变对象是,进行的是引用传递

区别在于:

值传递在函数内改变了形参的值,实参的值也不变

引用传递后,改变形参的值,实参的值也会一同改变

字符串就是不可变对象,而列表就是可变对象。

参数种类

  • 位置参数,也叫必备参数。即使用函数时要按照形参列表的正确顺序与数量进行使用。
  • 关键字参数。使用形参的名字来确定输入的参数值。打开文件时指定编码就是使用关键字参数:open('test.txt',encoding='GBK')
  • 有默认值的参数。在定义函数时直接指定形参的默认值。这样没有参数传递时就会直接使用默认值。
    • 例如定义函数 def func(filename, lenth = 5)
    • 定义函数时指定的默认参数要写在所有形参的最后面
    • 可以使用 函数名.__defaults__ 的形式查看函数的默认值参数,结果是元组。
    • 此外当使用可变参数作为函数参数默认值时,多次调用可能会导致意外,所以最好将可变参数的默认值设置为None默认参数必须要指向不可变对象
  • 可变参数。即不定长参数,可以传递的值是0个或者任意个。
    • 第一种形式:***parameter**。接受任意多的参数并放到一个元组之中。如果若要把一个存在的列表作为参数传递进去,可以使用 *列表名称 作为参数传递。
    • 第二种形式:**parameter。接受任意多个显式赋值的实际参数,并将其放到字典中。如果若要把一个存在的字典作为参数传递进去,可以使用 **字典名称 作为参数传递。

变量作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 全局变量在函数内外都可以访问的到
sum = 123

def func():
print(sum)

func() #123
print(sum) #123

# 局部变量与全局变量重名时
sum = 123

def func():
sum = 456
print(sum)

func() #456
print(sum) #123

# 可以在函数体内声明一个全局变量
sum = 123

def func():
global sum
sum = 456
print(sum)

func() #456
print(sum) #456

👍迭代器、生成器与iter函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
list1 = [1,2,3]
it = iter(list1)
print(next(it))
print(next(it))
print(next(it))
# print(next(it)) #error

def frange(start,stop,step):
x = start
while x < stop:
yield x
x += step

for i in frange(10,20,0.5):
print(i)

Python:迭代器、生成器(yield)、iter函数

只要函数里有 __iter__ 以及 __next__ 的这种方法就可以使用 for...in... 的形式以及 next 形式去取迭代值。

匿名函数–lambda表达式

1
2
3
4
5
6
7
8
9
10
11
def true():
return True

#对应的lambda表达式
lambda : True

def add(x,y):
return x+y

#对应的lambda表达式
lambda x,y : x+y

: 之前写函数的参数,冒号之后写实现具体功能的表达式。此外一定要有一个变量去接受或者去调用这个lambda表达式。

常用的Python内置函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
a = [1,2,3,4,5,6,7]
list1 = list(filter(lambda x:x>2, a))
print(list1) #[3, 4, 5, 6, 7]

a = [1,2,3,4,5,6,7]
list2 = list(map(lambda x:x+1, a))
print(list2) #[2, 3, 4, 5, 6, 7, 8]

b = [7,7,7,7,7,7,7]
list3 = list(map(lambda x,y:x+y, a,b))
print(list3) #[8, 9, 10, 11, 12, 13, 14]

#reduce 对参数序列中元素进行累积。
from functools import reduce
print(reduce(lambda x,y:x+y,[1,2,3,4])) #10


a = (1,2,3)
b = (4,5,6)
for i in zip(a,b):
print(i)

# (1, 4)
# (2, 5)
# (3, 6)

#使用zip将字典的键值进行对调
dict1 = {'a':22, 'b':33}
dict2 = dict(zip(dict1.values(), dict1.keys()))
print(dict2) #{22: 'a', 33: 'b'}

闭包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#定义一个函数,内部还有一个函数,外部函数的返回值是内部函数的名字
def func():
def printa():
print("start")

return printa


func() #不会执行,无结果
print(func()) #<function func.<locals>.printa at 0x0000014DA9557D90>
print(type(func())) #<class 'function'>

a = func()
a() #执行函数内容:start

闭包是由函数及其相关的引用环境组合而成的实体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def ExFunc(n):
sum = n
def InsFunc():
return sum+1

return addFun

myFun1 = ExFunc(10)
sums = myFun1()
print(sums) #11

myFun2 = ExFunc(100)
sumss = myFun2()
print(sumss) #101

当调用函数分别传入不同的参数的时候,得到的结果myFun1myFun2这两个是隔离的,也就是说每次调用ExFunc()函数后都将生成并且保存一个新的局部变量sum。

按照命令式语言的规则,ExFunc函数只是返回了内嵌函数InsFunc的地址,在执行InsFunc函数时将会由于在其作用域内找不到sum变量而出 错。而在函数式语言中,当内嵌函数体内引用到体外的变量时,将会把定义时涉及到的引用环境和函数体打包成一个整体(闭包)返回。现在给出引用环境的定义就 容易理解了:引用环境是指在程序执行中的某个点所有处于活跃状态的约束(一个变量的名字和其所代表的对象之间的联系)所组成的集合。闭包的使用和正常的函 数调用没有区别。

由于闭包把函数和运行时的引用环境打包成为一个新的整体,所以就解决了函数编程中的嵌套所引发的问题。如上述代码段中,当每次调用ExFunc函数 时都将返回一个新的闭包实例,这些实例之间是隔离的,分别包含调用时不同的引用环境现场。不同于函数,闭包在运行时可以有多个实例,不同的引用环境和相同 的函数组合可以产生不同的实例。

闭包=函数块+定义函数时的环境

引用自博客:Python-闭包详解

并且一个常见的闭包错误以及python对应的解决方式:python nonloacal

闭包的实际小案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#计数器
def counter():
cnt = [0]
def add_one():
cnt[0] += 1
return cnt[0]
return add_one

num1 = counter()

#每执行一次函数 计数器+1
print(num1()) #1
print(num1()) #2
print(num1()) #3
print(num1()) #4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#计算 y = a*x+b

#普通函数的写法
def yyy(a,b,x):
return a*x+b

y = yyy(1,2,5)
print(y)

y = yyy(1,2,6)
print(y)

#闭包的写法
def yyy(a,b):
def argy(x):
return a*x + b
return argy

y1 = yyy(1,2)
ends = y1(5)
print(ends)

end2 = y1(6)
print(end2)

如上所示,对于计算一阶函数时,想要固定a,b的值而只改变x的值的时候就可以采用这种方式,简化代码。

装饰器

1
2
3
4
5
6
7
8
9
10
11
12
import time

def iSleep():
time.sleep(2)

start_time = time.time()

iSleep()

end_time = time.time()

print('使用时间:',end_time-start_time)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import time

def timmer(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('使用时间:', end_time - start_time)
return wrapper

@timmer
def iSleep():
time.sleep(2)


#执行
iSleep()

我们注意到装饰器可以使用def来定义,装饰器接收一个函数对象作为参数,并返回一个新的函数对象。装饰器通过名称绑定,让同一个变量名指向一个新返回的函数对象,这样就达到修改函数对象的目的。在使用装饰器时,我们通常会在新函数内部调用旧函数,以保留旧函数的功能,这正是“装饰”一词的由来。在定义好装饰器以后,就可以使用@语法了,其实际意义时,将被修饰对象作为参数传递给装饰器函数,然后将装饰器函数返回的函数对象赋给原来的被修饰对象。装饰器可以实现代码的可复用性,即我们可以用同一个装饰器修饰多个函数,以便实现相同的附加功能。

参看链接:深入浅出理解Python装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def tips(func):
def nei(a,b):
print('start')
func(a,b)
print('end')

return nei

@tips
def add(a,b):
print(a+b)

@tips
def sub(a,b):
print(a-b)

add(1,2)
sub(5,3)

##################

def new_tips(argv):
def tips(func):
def nei(a,b):
print('start:',argv)
func(a,b)
print('end:',argv)

return nei
return tips

@new_tips('add')
def add(a,b):
print(a+b)

@new_tips('sub')
def sub(a,b):
print(a-b)

add(1,2)
sub(5,3)

类与对象

Python中一切都是对象,甚至字符串、函数等都是对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#定义一个类
class Player:
def __init__(self, name, hp):
self.name = name
self.hp = hp
#定义一个方法
def print_role(self):
print(self.name, ':', self.hp)

#类的实例化
user1 = Player('tom', 100)
user2 = Player('Bob', 200)

user1.print_role();
user2.print_role();

__init__()方法与self参数

__init__方法是构造方法,每当创建一个类的实例的时候Python就会自动执行他。

这种函数名写法用于区分Python的默认方法和普通方法。

self参数是指向实例本身的引用,用于访问类中的属性和方法,在方法调用的时候就会自动传递参数self。(类似于C++类中的this)

类中方法的第一个参数一定要是self。(self只是约定的名字,其他名字也行)

类的成员

类的成员由实例方法数据成员组成。

数据成员是指类中定义的变量,即类的属性。

而类的属性根据其所在位置的不同又分为类属性实例属性

  • 类属性:定义在类中,定义在类的实例方法之外的属性。
    • 类属性在类的所有实例之间共享,即所有实例化对象共用此属性。
    • 类属性可以通过类名调用,或者通过实例名进行访问
    • 类似于C++类中的static变量
  • 实例属性:定义在类的方法中的属性。
    • 实例属性只能通过实例名进行访问。
    • 不同实例的实例属性之间互不影响。

访问权限

Python中通过给属性或者方法的名字前面添加单下划线双下划线首尾双下划线的方式来限制类中属性和方法的访问权限。

  • 首尾双下划线:表示定义特殊方法,一般是系统定义名字。比如:__init__()方法
  • 单下划线开头:表示protected(保护)类型的成员,只允许类本身和子类访问,但不能使用”from modules import *”这种语句导入。比如:自定义属性 _foo
  • 双下划线开头:表示private(私有)成员。只允许定义该方法的类本身进行访问,不能直接通过类的实例进行访问,但是可以通过”类的实例名._类名_xxx”的方式访问。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Swan:
#定义保护成员
_neckSwan = '天鹅的脖子很长'
def __init__(self):
print("__init__()",self._neckSwan)

swan = Swan()
print('直接访问',swan._neckSwan)

##########

class Swan:
#定义私有成员
__neckSwan = '天鹅的脖子很长'
def __init__(self):
print("__init__()",self.__neckSwan)

swan = Swan()
print('直接访问',swan._Swan__neckSwan)

类的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Fruit:
def __init__(self, color):
self.color = color
print('我是水果')
def havest(self):
print('水果是', self.color, '色的')


#类Orange,子类,继承于Fruit类
class Orange(Fruit):
def __init__(self):
# super(Orange, self).__init__()
# 调用基类的初始化方法
super().__init__('橙')
print('我是Orange')

#重写方法
def havest(self):
print('橙子是', self.color, '色的')

orange = Orange()
orange.havest()

####输出
#我是水果
#我是Orange
#橙子是 橙 色的
  • 当要继承多个父类的时候,在小括号内类名用逗号分隔开
  • 如果不指定时,默认继承于所有Python对象的基类Object

判断实例与类的关系

1
2
3
print(type(orange))               #<class '__main__.Orange'>
print(isinstance(orange, Orange)) #True
print(isinstance(orange, Fruit)) #True

@property(装饰器)

在Python中可以通过 @property(装饰器) 将一个方法转换为属性,从而实现用于计算的属性。

将方法转换为属性之后,可以直接通过方法名来访问方法,不再需要小括号()

  • 通过 @property 转换的属性不能够直接赋值,否则会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
class Rect:
def __init__(self, width, heigh):
self.width = width
self.heigh = heigh

@property
def area(self):
return self.width * self.heigh

rect = Rect(640, 480)
print('面积为:', rect.area)
#print('面积为:', rect.area()) # 执行错误
# TypeError: 'int' object is not callable

@property(装饰器)创建只读但不能修改的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
class TVshow:
def __init__(self, show):
self.__show = show

@property
def show(self):
return self.__show

tvshow = TVshow('哪吒传奇之魔童降世')

# print(tvshow.__show) 错误
# print(tvshow.show()) 错误
print(tvshow.show)

自定义with语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Testwith:
def __enter__(self):
print('开始')
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_tb is None:
print('正常结束')
else:
print('出现异常 %s' %(exc_tb))

with Testwith():
print('测试自定义with语句')
raise Exception('手动出现异常')

##### 结果
# 开始
# Traceback (most recent call last):
# 测试自定义with语句
# 出现异常 <traceback object at 0x000002618D1AC188>
# File "E:/Code/Python/test/mywith.py", line 12, in <module>
# raise Exception('手动出现异常')
# Exception: 手动出现异常

模块

1
2
3
4
5
6
7
8
9
10
11
12
#import 模块名称
import time

#import 模块名称 as 重命名
import matplotlib as m

#from 模块名称 import 方法名
import time import sleep

#导入自定义模块:
#将自定义的变量和函数编写在一个单独的文件之中,创建成模块名+.py的形式
# 然后参照上面的语法导入

Python日常应用比较广泛的模块

  1. 文字的处理:re
  2. 日期类型:time、datetime
  3. 数字和数学类型:math、random
  4. 文件和目录的访问:pathlib、os.path
  5. 数据压缩和归档:tarfile
  6. 通用操作系统:os、logging、argparse
  7. 多线程:threading、queue
  8. Internet数据处理:base64、json、urllib
  9. 结构化标记处理工具:html、xml
  10. 开发工具:unitest
  11. 调试工具:timeit
  12. 软件包的发布:venv
  13. 运行服务的 __main__

正则表达式 - re

正则表达式可以用来处理符合某些规则的字符串。

函数

1
2
3
4
5
6
7
compile(pattern[, flags]) #根据包含正则表达式的字符串创建模式对象
search(pattern, string[, flags]) #在字符串中查找模式
match(pattern, string[, flags]) #在字符串开头匹配模式
split(pattern, string[, maxsplit=0]) #根据模式来分割字符串
findall(pattern, string)#返回一个列表,其中包含字符串中所有与模式匹配的子串
sub(pat, repl, string[, count=0])#将字符串中与模式pat匹配的子串都替换为repl
escape(string) #对字符串中所有的正则表达式特殊字符都进行转义

字符

↑常用元字符
![](Python/xiandingfu.png)
↑常用限定符
### 实例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import re

#定义要匹配的字符串hell
# p = re.compile('hell')
# print(p.match('hello')) #<re.Match object; span=(0, 4), match='hell'>

# 一个点 . -->一个点可以匹配任意一个字符
p = re.compile('.')
print(p.match('a')) #<re.Match object; span=(0, 1), match='a'>

p1 = re.compile('..')
print(p1.match('baa')) #<re.Match object; span=(0, 2), match='ba'>

p2 = re.compile('.{3}')
print(p2.match('a12a')) #<re.Match object; span=(0, 3), match='a12'>

# ^ 从开头向后搜索 p = re.compile('^')
# $ 从结尾向前扩展 p = re.compile('jpg$') 匹配到以jpg结尾的图片

# * --> 匹配*前面的字符 0次或多次
p = re.compile('ca*t')
print(p.match('caaaaaat')) #<re.Match object; span=(0, 8), match='caaaaaat'>

# + --> 匹配+前面的字符 1次或多次
p = re.compile('ca+t')
print(p.match('caaaaaat')) #<re.Match object; span=(0, 8), match='caaaaaat'>
print(p.match('ct')) #None

# ? --> 匹配?前面的字符 0次或1次
p = re.compile('c?t')
print(p.match('caat')) #None
print(p.match('ctt')) #<re.Match object; span=(0, 2), match='ct'>

# {n} --> 匹配前面的字符出现n次
p = re.compile('ca{4}t')
print(p.match('caaaat')) #<re.Match object; span=(0, 6), match='caaaat'>
print(p.match('caaaaaat')) #None

# {m,n} --> 匹配前面的字符出现m~n次之间
p = re.compile('ca{4,6}t')
print(p.match('caaaat')) #<re.Match object; span=(0, 6), match='caaaat'>
print(p.match('caaaaaat')) #<re.Match object; span=(0, 8), match='caaaaaat'>

# []
p = re.compile('c[abc]t')
print(p.match('cat')) #<re.Match object; span=(0, 3), match='cat'>
print(p.match('cct')) #<re.Match object; span=(0, 3), match='cct'>
print(p.match('cdt')) #None

# \d -->表示匹配的字符是一串数字
# \D --> 表示匹配不包括这一串数字
# \s --> 表示匹配一串字符串
# () --> 正则分组
# | --> 表示或者
# ^$ --> 组合在一起,表示这一段是空行
# .*? --> 不使用贪婪模式


# 正则分组
p = re.compile(r'\d-\d-\d')
print(p.match('2019-08-24')) #None

p1 = re.compile(r'(\d+)-(\d+)-(\d+)')
print(p1.match('2019-08-24')) #<re.Match object; span=(0, 10), match='2019-08-24'>
print(p1.match('2019-08-24').group()) #2019-08-24
print(p1.match('2019-08-24').group(2)) #08

year, month, day = p1.match('2019-08-24').groups()
print(year) #2019

# 搜索指定的字符串
p1 = re.compile(r'(\d+)-(\d+)-(\d+)')
print(p1.match('aa2019-08-24nn')) #None
print(p1.search('aa2019-08-24nn')) #<re.Match object; span=(2, 12), match='2019-08-24'>

# 字符串替换
phone = '123-456-789 # 这是一串字符串'
p2 = re.sub(r'#.*$', '', phone)
print(p2) #123-456-789

p3 = re.sub(r'\D', '', p2)
print(p3) #123456789

参考链接

python基础(re模块(正则表达式))

python正则表达式详解

时间相关的库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import time

print(time.time()) #输出现在与1970年1月1日相差的秒数
print(time.localtime()) #time.struct_time(tm_year=2019, tm_mon=8, tm_mday=25, tm_hour=9, tm_min=45, tm_sec=9, tm_wday=6, tm_yday=237, tm_isdst=0)
print(time.strftime('%Y-%m-%d %H-%M-%S'))#格式化输出:2019-08-25 09-45-09

import datetime
print(datetime.datetime.now()) #22019-08-25 09:48:03.377347
newTime = datetime.timedelta(minutes=10)
print(datetime.datetime.now() + newTime) #2019-08-25 09:58:03.377347

one_day = datetime.datetime(2008, 10, 1)
newDate = datetime.timedelta(days=10)
print((one_day + newDate)) #2008-10-11 00:00:00

参考链接:Python中处理日期时间库的使用方法(转载)

random库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import random
import string

# 随机整数:
print (random.randint(1,50))

# 随机选取0到100间的偶数:
print (random.randrange(0, 101, 2))

# 随机浮点数:
print (random.random())
print (random.uniform(1, 10))

# 随机字符:
print (random.choice('abcdefghijklmnopqrstuvwxyz!@#$%^&*()'))

# 多个字符中生成指定数量的随机字符:
print (random.sample('zyxwvutsrqponmlkjihgfedcba',5))

# 从a-zA-Z0-9生成指定数量的随机字符:
ran_str = ''.join(random.sample(string.ascii_letters + string.digits, 8))
print (ran_str)

# 多个字符中选取指定数量的字符组成新字符串:
print (''.join(random.sample(['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'], 5)))

# 随机选取字符串:
print (random.choice(['剪刀', '石头', '布']))

# 打乱排序
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print (random.shuffle(items))

文件目录操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os

print(os.path.abspath('.')) #获取当前的绝对路径 E:\Code\Python\test
print(os.path.exists(r'E:\Code\Python\test')) #判断文件或者目录是否存在
print(os.path.isfile(r'E:\Code\Python\test')) #判断是否是文件
print(os.path.isdir(r'E:\Code\Python\test')) #判断是否是目录
print(os.path.join('/tmp/a',r'Python\test')) #连接路径 /tmp/a\Python\test

from pathlib import Path
p = Path('.')
print(p.resolve()) #E:\Code\Python\test

q = Path(r'E:\Code\Python\test\a')
Path.mkdir(q, parents=True) #创建目录

机器学习库

numpy库

Numpy用于高性能科学计算和数据分析,是常用的高级数据分析的基础包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import numpy as np

arr1 = np.array([2,3,4])
print(arr1) #[2 3 4]
print(type(arr1)) #<class 'numpy.ndarray'>
print(arr1.dtype) #int32

arr2 = np.array([1.2,2.3,3.8])
print(arr2)
print(arr2.dtype) #float64

#Numpy的算数运算:两个数组可以可以做算数运算

print(arr1+arr2) #[3.2 5.3 7.8]
print(arr2 * 10) #[12. 23. 38.]

# N维数组
data = [[1,2,3],[4,5,6]]
arr3 = np.array(data) #转化为一个二维矩阵
print(arr3)
print(arr3.shape) #(2, 3)
print(arr3.dtype) #int32

#生成特殊的值
print(np.zeros(10)) #[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
print(np.zeros((3,5))) #三行五列的矩阵值全为0
print(np.ones((3,5))) #三行五列的矩阵值全为1
print( np.empty((2,3,2)) )#设置为空,会随机填充

#通过下标访问,arange()函数,切片操作
arr = np.arange(10)
print(arr)
print(arr[1]) # 1
print(type(np.arange(10))) #<class 'numpy.ndarray'>

arr4 = np.arange(10)
print(arr4[5:8]) #[5 6 7]

#复制操作
arr_slie = arr4[3:9].copy()
print(arr_slie) #[3 4 5 6 7 8]
arr_slie[1:4] = 0
print(arr_slie) #[3 0 0 0 7 8]

arrs = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(arrs.shape) #(3, 3)

#将多维数组转换为一维数组
arrs2 = arrs.flatten()
print(arrs2) #[1 2 3 4 5 6 7 8 9]
print(type(arrs2)) #<class 'numpy.ndarray'>

参考链接:

Python入门:Anaconda和Pycharm的安装和配置

pycharm如何使用anaconda中的各种包

pycharm使用Anaconda的配置环境

pandas

Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗功能.

Series:它是一种类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据也可产生简单的Series对象。

DataFrame是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。

pandas的Series

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from pandas import Series,DataFrame
import pandas as pd

obj = Series([4,5,6,-7])
print(obj)
# 会自动添加索引,但是索引可以重复
# 0 4
# 1 5
# 2 6
# 3 -7
# dtype: int64
print(obj.index) #RangeIndex(start=0, stop=4, step=1)
print(obj.values) #[ 4 5 6 -7]

# 生成时同时指定索引
obj2 = Series([4,5,6,7],index=['d','b','c','a'])
print(obj2)
# d 4
# b 5
# c 6
# a 7
# dtype: int64
print(type(obj2)) #<class 'pandas.core.series.Series'>

#通过索引来改变值
obj2['c'] = 2
print(obj2)

#使用 in 操作符判断索引是否在obj2中,但是无法识别value
print('a' in obj2)

#将字典转化成
stata = {'aa':1,'bb':2,'cc':3}
obj3 = Series(stata)
print(obj3)

#重新进行索引排序
obj4 = Series([4.5,5.3,1.2,-3.6], index= ['b','c','d','a'])

# fill_value=使用这个值进行填充索引存在但值不存在的那些。
obj5 = obj4.reindex(['a','b','c','d','e'], fill_value=0)
print(obj5)

obj6 = Series(['blue','black','white'], index=[0,2,4])

# method='ffill'是以上面的值作为填充
print(obj6.reindex(range(6) , method='ffill'))
# method='bfill'是以下面的值作为填充
print(obj6.reindex(range(6) , method='bfill'))

from numpy import nan as NA
obj7 = Series([1,NA,3])
print(obj7)
#删除NaN这个值
print(obj7.dropna())

import numpy as np

#层次化索引
fram5 = Series(np.random.randn(10),
index=[['a','a','a','b','b','b','c','c','d','d'],
[1,2,3,1,2,3,1,2,2,3]])
print(fram5)

print(fram5['b'])
print(fram5['b':'c'])

#将一维的数据转换为二维数据
print(fram5.unstack())
#将二维的数据转换为一维数据
print(fram5.unstack().stack())

pandas的DataFram

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#字典
data = {'city':['shanghai','guangdong','shenzhen','beijing'],
'year':[2013,2015,2017,2019],
'pop':[1.1,1.3,1.5,1.7]}

fram = DataFrame(data)

print(fram)
# city year pop
# 0 shanghai 2013 1.1
# 1 guangdong 2015 1.3
# 2 shenzhen 2017 1.5
# 3 beijing 2019 1.7
print(type(fram)) #<class 'pandas.core.frame.DataFrame'>

#指定表格的排序规则
fram2 = DataFrame(data, columns=['year','city','pop'])
print(fram2)

#提取数据
print(fram['city'])
print(fram.year)

#增加新的列
fram2['new'] = 100
print(fram2)

#根据其他列来产生新的列
fram2['cap'] = (fram2.city == 'beijing')
print(fram2)

#将字典转化为DataFram
pop = {'beijing':{2008:1.5,2009:2.0},
'shanghai':{2008:2.0,2009:3.6}}

fram3 = DataFrame(pop)
print(fram3)
# beijing shanghai
# 2008 1.5 2.0
# 2009 2.0 3.6

#行列互换:行列式转换
print(fram3.T)

from numpy import nan as NA

fram4 = DataFrame([[1,6,5],[1,NA,NA],[NA,NA,NA]])
print(fram4)
# 0 1 2
# 0 1.0 6.0 5.0
# 1 1.0 NaN NaN
# 2 NaN NaN NaN

#删除含有na的行
print(fram4.dropna())
# 0 1 2
# 0 1.0 6.0 5.0

#删除行的值全部都是na的行
print(fram4.dropna(how='all'))
# 0 1 2
# 0 1.0 6.0 5.0
# 1 1.0 NaN NaN

# 使第四列的值全为na
# fram4[4] = NA
# print(fram4)
#删除一列全是na的列
print(fram4.dropna(axis=1, how='all'))

#将na填充为数字,默认修改时不会改变本身的,但是添加inplace这个参数就可以改变本身
print(fram4.fillna(0, inplace=True))
print(fram4)

matplotlib绘图

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt

#当产生警告时忽略
import warnings
warnings.filterwarnings('ignore')

#绘制简单的曲线
plt.plot([1,3,5],[4,8,10])
plt.show()

1567172852560

1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt


#当产生警告时忽略
import warnings
warnings.filterwarnings('ignore')

x = np.linspace(-np.pi,np.pi,100)# x轴的定义域为 -3.14到3.14 中间间隔100个元素
plt.plot(x, np.sin(x))
plt.show()

1567173015230

1
2
3
4
5
6
7
8
9
10
11
12
import matplotlib.pyplot as plt
import numpy as np

#当产生警告时忽略
import warnings
warnings.filterwarnings('ignore')

x = np.linspace(-np.pi * 2, np.pi * 2, 100)# x轴的定义域为 -3.14到3.14 中间间隔100个元素
plt.figure(1, dpi=50)#创建图表1,dpi为精度
for i in range(1,5):
plt.plot(x, np.sin(x/i))
plt.show()

1567173105787

1
2
3
4
5
6
7
8
9
10
11
import matplotlib.pyplot as plt

#当产生警告时忽略
import warnings
warnings.filterwarnings('ignore')

#绘制直方图
plt.figure(1, dpi=50) #创建图表1,dpi表示图片精度
data = [1, 2, 1, 2, 3, 5, 1, 3, 6]
plt.hist(data) #只要传入数据,直方图就会统计数据出现的次数
plt.show()

1567173208283

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt
import numpy as np

#当产生警告时忽略
import warnings
warnings.filterwarnings('ignore')

# 绘制散点图
x = np.arange(1, 10)
y = x
fig = plt.figure()
plt.scatter(x, y, c='r', marker='o') #c = 'r'表示散点的颜色为红色,marker表示指定散点的形状为原型
plt.show()

1567173326484

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

#当产生警告时忽略
import warnings
warnings.filterwarnings('ignore')

#读取csv格式文件,绘制散点图
iris = pd.read_csv('04.CSV')
print(iris.head()) #打印前五行数据
#绘制散点图
iris.plot(kind='scatter', x='132', y='2840')
plt.show()

############
# 采用新的库seaborn绘制
iris = pd.read_csv('04.CSV')
#设置样式
sns.set(style='white', color_codes=True)
#设置绘图格式为散点图
sns.jointplot(x='132', y='2840', data=iris, size=5)
#displot绘制曲线
sns.distplot(iris['132'])
plt.show()
## 下图是库seaborn绘制的

1567173639044

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

#当产生警告时忽略
import warnings
warnings.filterwarnings('ignore')

iris = pd.read_csv('04.CSV')
#设置样式
sns.set(style='white', color_codes=True)
# #FacetGrid 是一般的绘图函数
# #hue 彩色显示分类0/1/2
# #plt.scatter 绘制散点图
# #add_legend 显示分类的描述信息
# #map用来指定行列
sns.FacetGrid(iris, hue='11', size=5).map(plt.scatter, '132', '2840').add_legend()
plt.show()

1567173541444


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!