2019-04-26  2024-09-18    7556 字  16 分钟

Python手册

基本数据类型

整数

  • Python可以处理"任意"大小的整数,包括负数
  • 支持二进制,八进制,十进制,十六进制
前缀 例子 进制
0b或者0B a = 0b1010 2
0o或者0O a = 0o12 8
a = 10 10
0x或者0X a = 0xa 16

浮点数

  • 定义

    • a = 1.2
    • b = .4
    • c = 1.2e-4
  • 计算时可能会丢失精度

字符串

  • 定义
    • a = ’test'
    • a = “test”
    • a = ‘‘’test’’’
      • 可以直接使用单/双引号
1a = "test"
2len(a)

切割字符串

 1x = 'hello world'
 2# 分割字符串
 3a = x.split(' ')
 4# ['hello', 'world']
 5
 6# 合并为字符串
 7' '.join(a)
 8# 'hello world'
 9
10
11# 切片
12s = '12 34'
13s[2:4]
14# ' 3'

格式化字符串

 1name = "Akvicor"
 2age = 19
 3
 4# print I'm Akvicor
 5new_str = "I'm " + name + ", " + str(age) + " years old"
 6print("Case0: " + new_str)
 7
 8# in python2
 9new_str1 = "I'm %s, %d years old" % (name, age)
10print("Case1: " + new_str1)
11
12# in python3
13new_str2 = "I'm {}, {} years old".format(name, age)
14print("Case2: " + new_str2)
15new_str3 = "I'm {names}, {ages} years old".format(
16    names='Akvicor', ages=age
17)
18print("Case3: " + new_str3)
19new_str4 = f"I'm {name}, {age} years old"
20print("Case4: " + new_str4)
21
22# Case0: I'm Akvicor, 19 years old
23# Case1: I'm Akvicor, 19 years old
24# Case2: I'm Akvicor, 19 years old
25# Case3: I'm Akvicor, 19 years old
26# Case4: I'm Akvicor, 19 years old

运算符

+:两个字符串拼接

*****:将字符串重复

布尔型

  • True
  • False

NONE空值

  • 空值就是没有值
  • a = ’’ 不叫空
  • a = 0 也不叫空
  • a = None 叫空
1a = None
2a is None
3# True
4
5a = ''
6a is None
7# False

turtle

  1. 设置画笔大小 pensize(4)
  2. 隐藏海龟 hideturtle()
  3. 切换RGB色彩模式 colormode(255)
  4. 颜色 color((255, 155, 192), "pink")
  5. 设置画布宽和高 setup(840, 500)
  6. 设置画笔速度 speed(10)
turtle peppa pig source code
  1"""
  2绘制小猪佩奇
  3"""
  4from turtle import *
  5
  6
  7def nose(x, y):
  8    """画鼻子"""
  9    # 将海龟移动到指定的坐标
 10    goto(x, y)
 11    pendown()
 12    # 设置海龟的方向(0-东、90-北、180-西、270-南)
 13    setheading(-30)
 14    begin_fill()
 15    a = 0.4
 16    for i in range(120):
 17        if 0 <= i < 30 or 60 <= i < 90:
 18            a = a + 0.08
 19            # 向左转3度
 20            left(3)
 21            # 向前走
 22            forward(a)
 23        else:
 24            a = a - 0.08
 25            left(3)
 26            forward(a)
 27    end_fill()
 28    penup()
 29    setheading(90)
 30    forward(25)
 31    setheading(0)
 32    forward(10)
 33    pendown()
 34    # 设置画笔的颜色(红, 绿, 蓝)
 35    pencolor(255, 155, 192)
 36    setheading(10)
 37    begin_fill()
 38    circle(5)
 39    color(160, 82, 45)
 40    end_fill()
 41    penup()
 42    setheading(0)
 43    forward(20)
 44    pendown()
 45    pencolor(255, 155, 192)
 46    setheading(10)
 47    begin_fill()
 48    circle(5)
 49    color(160, 82, 45)
 50    end_fill()
 51
 52
 53def head(x, y):
 54    """画头"""
 55    color((255, 155, 192), "pink")
 56    penup()
 57    goto(x, y)
 58    setheading(0)
 59    pendown()
 60    begin_fill()
 61    setheading(180)
 62    circle(300, -30)
 63    circle(100, -60)
 64    circle(80, -100)
 65    circle(150, -20)
 66    circle(60, -95)
 67    setheading(161)
 68    circle(-300, 15)
 69    penup()
 70    goto(-100, 100)
 71    pendown()
 72    setheading(-30)
 73    a = 0.4
 74    for i in range(60):
 75        if 0 <= i < 30 or 60 <= i < 90:
 76            a = a + 0.08
 77            lt(3)  # 向左转3度
 78            fd(a)  # 向前走a的步长
 79        else:
 80            a = a - 0.08
 81            lt(3)
 82            fd(a)
 83    end_fill()
 84
 85
 86def ears(x, y):
 87    """画耳朵"""
 88    color((255, 155, 192), "pink")
 89    penup()
 90    goto(x, y)
 91    pendown()
 92    begin_fill()
 93    setheading(100)
 94    circle(-50, 50)
 95    circle(-10, 120)
 96    circle(-50, 54)
 97    end_fill()
 98    penup()
 99    setheading(90)
100    forward(-12)
101    setheading(0)
102    forward(30)
103    pendown()
104    begin_fill()
105    setheading(100)
106    circle(-50, 50)
107    circle(-10, 120)
108    circle(-50, 56)
109    end_fill()
110
111
112def eyes(x, y):
113    """画眼睛"""
114    color((255, 155, 192), "white")
115    penup()
116    setheading(90)
117    forward(-20)
118    setheading(0)
119    forward(-95)
120    pendown()
121    begin_fill()
122    circle(15)
123    end_fill()
124    color("black")
125    penup()
126    setheading(90)
127    forward(12)
128    setheading(0)
129    forward(-3)
130    pendown()
131    begin_fill()
132    circle(3)
133    end_fill()
134    color((255, 155, 192), "white")
135    penup()
136    seth(90)
137    forward(-25)
138    seth(0)
139    forward(40)
140    pendown()
141    begin_fill()
142    circle(15)
143    end_fill()
144    color("black")
145    penup()
146    setheading(90)
147    forward(12)
148    setheading(0)
149    forward(-3)
150    pendown()
151    begin_fill()
152    circle(3)
153    end_fill()
154
155
156def cheek(x, y):
157    """画脸颊"""
158    color((255, 155, 192))
159    penup()
160    goto(x, y)
161    pendown()
162    setheading(0)
163    begin_fill()
164    circle(30)
165    end_fill()
166
167
168def mouth(x, y):
169    """画嘴巴"""
170    color(239, 69, 19)
171    penup()
172    goto(x, y)
173    pendown()
174    setheading(-80)
175    circle(30, 40)
176    circle(40, 80)
177
178
179def setting():
180    """设置参数"""
181    pensize(4)
182    # 隐藏海龟
183    hideturtle()
184    colormode(255)
185    color((255, 155, 192), "pink")
186    setup(840, 500)
187    speed(10)
188
189
190def main():
191    """主函数"""
192    setting()
193    nose(-100, 100)
194    head(-69, 167)
195    ears(0, 160)
196    eyes(0, 140)
197    cheek(80, 10)
198    mouth(-20, 30)
199    done()
200
201
202if __name__ == '__main__':
203    main()

列表和元组

  • 元组是不可变的(Immutable)Python对象,储存在固定的一块内存里
  • 列表是可变的(mutable)Python对象,需要两块存储空间,一块固定用来存储实际的列表数据,一块可变的空间用于扩展。
  • 结论就是:元组创建和访问要比列表块,但是不如列表灵活

list basic

 1a = [1, 2, 3]
 2
 3b = [1, 'abc', 2.0, ['a', 'b', 'c']]
 4
 5print(a)
 6# [1, 2, 3]
 7print(b)
 8# [1, 'abc', 2.0, ['a', 'b', 'c']]
 9print(a[0])
10# 1
11print(a[0], a[1])
12# 1 2
13# 默认两个之间加入空格
14# 默认分隔符为空格,结尾为换行。但可以修改
15print(a[0], a[1], a[2], sep='*', end='-')
161*2*3-
17
18c = b[1:3]
19print(c)
20# ['abc', 2.0]
21s = 'abcdefghijklmn'
22print(s[3:7], s[-5:-2])
23# defg jkl

list method

 1# 获取列表的一些基本信息
 2list1 = [9, 1, -4, 3, 7, 11, 3]
 3
 4print('list1的长度 = ', len(list1))
 5
 6print('list1里的最大值 = ', max(list1))
 7
 8print('list1里的最小值 = ', min(list1))
 9
10print('list1里3这个元素一共出现了{}次'.format(list1.count(3)))
11
12# 列表复制
13list_copy = list1[:]
14# 不能使用 list_copy = list1 这种方法
15# 这只会让list_copy和list1指向同一个列表
16
17# 列表的改变
18list2 = ['a', 'c', 'd']
19print('list2 = ', list2)
20
21# 给list2结尾添加一个元素'e'
22list2.append('e')
23print('list2 = ', list2)
24
25# 在list2的'a'和'b'之间插入一个'b'
26list2.insert(1, 'b')
27print('list2 = ', list2)
28
29# 删除list2里的 'b'  根据值删除元素
30list2.remove('b')
31print('list2 = ', list2)
32
33# 列表反转
34list3 = [1, 2, 3]
35print('list3 = ', list3)
36list3.reverse()
37print('list3 = ', list3)
38
39# 列表排序
40list4 = [9, 1, -4, 3, 7, 11, 3]
41
42# 永久排序
43list4.sort()
44print('list4 = ', list4)
45list4.sort(reverse=True)
46print('list4 = ', list4)
47# 临时排序
48list4Temp = sorted(list4)
49list4Temp = sorted(list4, reverse=True)
50
51# 删除列表元素  根据位置
52list4 = [9, 1, -4, 3, 7, 11, 3]
53# 是用del删除 
54del list4[6]  # -> [9, 1, -4, 3, 7, 11]
55# 是用pop()删除  默认是最后一个元素,也可以是指定元素
56p = list4.pop()  # -> [9, 1, -4, 3, 7, 11]
57# p = 3
58p = list4.pop(0)  # -> [1, -4, 3, 7, 11, 3]
59# p = 9
60
61# ETC
62list5 = [1, 2, 3, 4]
63print(list5 * 2 + [4, 5, 6])
64# [1, 2, 3, 4, 1, 2, 3, 4, 4, 5, 6]
 1list1的长度 =  7
 2list1里的最大值 =  11
 3list1里的最小值 =  -4
 4list1里3这个元素一共出现了2次
 5list2 =  ['a', 'c', 'd']
 6list2 =  ['a', 'c', 'd', 'e']
 7list2 =  ['a', 'b', 'c', 'd', 'e']
 8list2 =  ['a', 'c', 'd', 'e']
 9list3 =  [1, 2, 3]
10list3 =  [3, 2, 1]
11list4 =  [-4, 1, 3, 3, 7, 9, 11]
12list4 =  [11, 9, 7, 3, 3, 1, -4]
13[1, 2, 3, 4, 1, 2, 3, 4, 4, 5, 6]

tuple basic

 1# 元组的创建
 2
 3a = (1, 2, 3)
 4b = 1,
 5print(a, type(a))
 6print(b, type(b))
 7
 8# 元组的访问
 9
10print(a)
11print(a[1])
12print(a[-1])
13print(a[1:3])
14print(a[1:])
15print(a[:2])

tuple methods

元组里面的值与字符串类似,不可以改变

 1# 获取元组的一些基本信息
 2tuple1 = (9, 1, -4, 3, 7, 11, 3)
 3
 4print('tuple1的长度 = ', len(tuple1))
 5
 6print('tuple1里的最大值 = ', max(tuple1))
 7
 8print('tuple1里的最小值 = ', min(tuple1))
 9
10print('tuple1里3这个元素一共出现了{}次'.format(tuple1.count(3)))
11
12tuple5 = (1, 2, 3, 4)
13print(tuple5 * 2 + (4, 5, 6))
1tuple1的长度 =  7
2tuple1里的最大值 =  11
3tuple1里的最小值 =  -4
4tuple1里3这个元素一共出现了2次
5(1, 2, 3, 4, 1, 2, 3, 4, 4, 5, 6)

dict basic

 1# 字典创建
 2
 3a = {
 4    1: 'a',
 5    2: 'b',
 6    '3': 'c'
 7}
 8
 9
10# 不可改变的数据类型
11
12l1 = [1, 2, 3]
13# 因为list是可以改变的,所以下面这种是错误的
14# b = {
15#     l1: 1
16# }
17
18t1 = (1, 2, 3)
19# 这是可以的,因为tuple不可改变
20c = {
21    t1: l1
22}
23print(c)
24
25
26d = dict()
27print(d)
28
29e = dict(a=1, b=2, d='a')
30print(e)
31
32# 字典的访问
33print(e['d'])
34
35e['c'] = 123
36print(e)
37
38e['c'] = 3
39print(e)
1{(1, 2, 3): [1, 2, 3]}
2{}
3{'a': 1, 'b': 2, 'd': 'a'}
4a
5{'a': 1, 'b': 2, 'd': 'a', 'c': 123}
6{'a': 1, 'b': 2, 'd': 'a', 'c': 3}

dict methods

 1d = {
 2    'Name': 'Jack',
 3    'Age': 9,
 4    'Grade': 5
 5}
 6
 7#  不安全,在没有Name时会报错
 8print(d['Name'])
 9# 在没有Name时输出None
10print(d.get('Name'))
11
12print(d.keys())
13
14print(d.values())
15
16print(d.items())
17
18c = d.pop('Name')
19print(c, d)
20
21d.clear()
22print(d)
23
24
25# 字典的更新
26
27c = {
28    1: 1,
29    2: 2
30}
31print(c)
32c[3] = 3
33c[4] = 4
34
35d = {
36    5: 5,
37    6: 6
38}
39
40# 字典删除  按照键删除
41
42del c[3]
43
44# c.update(d)
45# print(c)
46# 或
47e = {**c, **d}
48print(e)
1Jack
2Jack
3dict_keys(['Name', 'Age', 'Grade'])
4dict_values(['Jack', 9, 5])
5dict_items([('Name', 'Jack'), ('Age', 9), ('Grade', 5)])
6Jack {'Age': 9, 'Grade': 5}
7{}
8{1: 1, 2: 2}
9{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6}

set basic

 1a = {'f', 'a', 'b', 'c'}
 2
 3print(a)
 4
 5print('c' in a)
 6print('d' in a)
 7
 8li = [1, 2, 3, 2, 4, 5, 2]
 9
10s1 = set(li)
11print(s1, type(s1), list(s1))
1{'a', 'b', 'f', 'c'}
2True
3False
4{1, 2, 3, 4, 5} <class 'set'> [1, 2, 3, 4, 5]

set methods

 1s = {1, 2, 3, 4}
 2
 3s.add(5)
 4print(s)
 5
 6# 如果元素不存在会报错
 7s.remove(5)
 8# s.remove(5)
 9print(s)
10
11a = '123452'
12s1 = set(a)
13print(s1)
14
15
16s1 = {1, 2, 3, 4}
17s2 = {3, 4, 5, 6}
18
19print(s1 & s2)
20print(s1 | s2)
21print(s1 ^ s2)
22print(s1 - s2)
23print(s2 - s1)
1{1, 2, 3, 4, 5}
2{1, 2, 3, 4}
3{'2', '4', '3', '5', '1'}
4{3, 4}
5{1, 2, 3, 4, 5, 6}
6{1, 2, 5, 6}
7{1, 2}

条件语句和循环语句

if elif else

1a = eval(input('Please input a integer: '))
2print('Information: ', a, type(a))
3
4if a > 0:
5    print('This integer is large than 0')
6elif a == 0:
7    print('This integer is equal 0')
8else:
9    print('This integer is smaller than 0')

while

1a = 10
2
3while a > 0:
4    print(a)
5    a -= 1

for

 1a = '12345'
 2b = [1, 2, 3, 4]
 3c = ('a', 'b', 'c', 'd')
 4d = {
 5    1: 'a',
 6    2: 'b',
 7    3: 'c'
 8}
 9e = {1, 2, 3, 4, 9}
10
11for item in a:
12    print(item)
13
14print('\ndict')
15for item in d:
16    print(item)
17for a, b in d.items():
18    print(f'{a}={b}')
19
20print('\nrange')
21for i in range(1, 20, 3):  # 默认步长等于1,也可以指定步长,例如三
22    # 等价于 C++ 中的 for(int i = 1; i < 20; i+=3)
23    print(i)

break continue

 1for i in range(10):
 2    print(i)
 3    if i == 3:
 4        break
 5print('#2')
 6for i in range(10):
 7    if i % 2 == 0:
 8        print(i)
 9print('#3')
10for i in range(10):
11    if i % 2 == 0:
12        continue
13    print(i)
 10
 21
 32
 43
 5#2
 60
 72
 84
 96
108
11#3
121
133
145
157
169

Game: guss number

 1import random
 2
 3a = random.randint(0, 100)
 4
 5while True:
 6    num = int(input("Please input your choice: "))
 7    if num == a:
 8        print('\nCongratulation!')
 9        break
10    elif num > a:
11        print('To large')
12    else:
13        print('To small')
14print(f'The number is {a}')

函数

函数的定义和调用

 1
 2def demo():
 3    print('Hello World')
 4    print('demo')
 5
 6
 7demo()
 8
 9
10def demo1(a, b):
11    print(a, b)
12    print('demo1')
13
14
15demo1(a=[1, 2, 3], b={1: 1, 2: 3})
16
17
18def my_sum(a: int, b: int):
19    return a + b
20
21
22print(my_sum(2, 3))
23
24
25def my_max(a):
26    if not a:
27        return None
28    max_value = 0
29    for i in a:
30        if i > max_value:
31            max_value = i
32    return max_value
33
34
35a = [1, 4, 5, 2, 3, 8, 10]
36print(my_max(a))
1Hello World
2demo
3[1, 2, 3] {1: 1, 2: 3}
4demo1
55
610

命名空间和范围

 1x = 1
 2
 3x += 1
 4
 5print(x)
 6
 7
 8def demo():
 9    x = 10
10    print(x)
11
12
13demo()
14
15print(x)
16
17
18def demo1(a):
19    a = a + 10
20    print(a)
21
22
23demo1(a=x)
24
25print(x)
26
27print("Next")
28y = [1, 2, 3]
29print('This is y', y)
30
31
32def demo2(a):
33    a.append(4)
34    print('demo2', a)
35
36
37def demo22(a):
38    a = a + [4]
39    print('demo22', a)
40
41
42demo22(a=y)
43print('After demo22', y)
44demo2(a=y)
45print('After demo2', y)
46print('可以发现这两种方法中 .append() 会影响原数组,而 + 不会影响')
47
48
49
50z = 1
51print('This is z', z)
52
53
54def demo3(a):
55    global z
56    z = z + a
57    print('In function', z)
58
59
60demo3(a=10)
61print('After Function', z)
 12
 210
 32
 412
 52
 6Next
 7This is y [1, 2, 3]
 8demo22 [1, 2, 3, 4]
 9After demo22 [1, 2, 3]
10demo2 [1, 2, 3, 4]
11After demo2 [1, 2, 3, 4]
12可以发现这两种方法中 .append() 会影响原数组,而 + 不会影响
13This is z 1
14In function 11
15After Function 11

可变参数*arge

 1def add(a, b):
 2    return a + b
 3
 4
 5print(add(1, 2))
 6
 7
 8def add1(a, b, c):
 9    return a + b + c
10
11
12print(add1(1, 2, 3))
13
14
15def add2(*args):
16    print(args)
17    result = 0
18    for i in args:
19        result += i
20    return result
21
22
23print(add2(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
13
26
3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
455

可变参数**wargs

 1def add(**kwargs):
 2    print(kwargs)
 3
 4
 5print(add(a=1, b=2))
 6
 7
 8def test(a, b, c):
 9    print(a + b + c)
10
11
12def add(x, **kwargs):
13    if x == 2:
14        test(**kwargs)
15
16
17add(x=2, a=1, b=2, c=2)
1{'a': 1, 'b': 2}
2None
35

参数默认值

1def test(a, b=False):
2    if b:
3        return a
4    else:
5        return a * a
6
7
8print(test(3))
9print(test(3, True))
19
23

递归的实现

 1def demo(n):
 2    result = 1
 3    for i in range(1, n+1):
 4        result *= i
 5    return result
 6
 7
 8def rec(n):
 9    if n <= 1:
10        return 1
11    return n * rec(n-1)
12
13
14print(rec(5))
15print(demo(5))
16# 120
17# 120

 面向对象

类和对象的基本概念

 1class MyClass:
 2    pass
 3
 4
 5# __init__() method 方法 function(函数)
 6# attribute 属性
 7# method 方法
 8
 9
10class People:
11    def __init__(self, name, age):
12        self.name = name
13        self.age = age
14
15    def say_hi(self):
16        print("Hi, my name is {}, and I'm {}".format(self.name, self.age))
17
18
19someone = People('Jack', 20)
20print(someone.name, someone.age)
21someone.say_hi()

私有属性和受保护属性

保护的属性为变量名前有一个_,私有属性为变量名前有两个__

保护属性可以在类外更改,但IDE会警告

私有属性不可以在类外更改

但是通过某种方法也可以更改私有属性,但并不推荐在类外对这两种属性进行更改

 1class People:
 2    def __init__(self, name, age):
 3        self.name = name
 4        self.age = age
 5        self._protect_var = 10  # can be replace
 6        self.__private_var = 10  # can not be replace
 7
 8    def say_hi(self):
 9        print("Hi, my name is {}, and I'm {}".format(self.name, self.age))
10
11    def get_var(self):
12        return self.__private_var
13
14    def set_var(self, var):
15        self.__private_var = var
16
17
18someone = People('Jack', 20)
19someone.say_hi()
20someone.age = 21
21someone.say_hi()
22someone._protect_var = 30
23print(someone._protect_var)
24
25
26print(someone.get_var())
27someone.set_var(30)
28print(someone.get_var())
29
30# python 只是将私有变量改名,并没有阻止我们对他的访问和修改
31# 这只是变相的阻止我们对他的访问,但在实际项目中请不要这样做
32print(dir(someone))
33someone._People_protect_var = 31
34print(someone._People_protect_var)
35someone._People__private_var = 31
36print(someone.get_var())
1Hi, my name is Jack, and I'm 20
2Hi, my name is Jack, and I'm 21
330
410
530
6['_People__private_var', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_protect_var', 'age', 'get_var', 'name', 'say_hi', 'set_var']
731
831

类的proterty怎么用

@property使类中的私有变量直接以 类名.变量名的形式访问

@变量名.setter 使类中的私有变量直接以 类名.变量名的形式修改需要先设定变量的property

此方法可以使私有变量在访问和修改时按照指定的方法进行处理,防止存放进去非法数据

 1class People:
 2    def __init__(self, name, age, sex):
 3        self.__name = name
 4        self.__age = age
 5        self.__sex = sex
 6
 7    def say_hi(self):
 8        print("Hi, my name is {}, and I'm {}".format(self.__name, self.__age))
 9
10    # def get_name(self):
11    #     return self.__name
12
13    @property
14    def name(self):
15        return self.__name
16
17    def set_name(self, name):
18        self.__name = name
19
20    def get_age(self):
21        return self.__age
22
23    def set_age(self, age):
24        self.__age = age
25
26    # def get_sex(self):
27    #     return self.__sex
28
29    # def set_sex(self, sex):
30    #     self.__sex = sex
31
32    @property
33    def sex(self):
34        return self.__sex
35
36    # 必须设置此变量的property
37    @sex.setter
38    def sex(self, sex):
39        self.__sex = sex
40
41
42someone = People(name='Jack', age=20, sex='Male')
43print(someone.get_age())
44someone.set_age(21)
45print(someone.get_age())
46
47print(someone.name)
48
49someone.sex = 'Female'
50print(someone.sex)

继承和多态

 1class Animal:
 2
 3    def eat(self):
 4        print('Animal is eating')
 5
 6
 7class Bird(Animal):
 8    def sing(self):
 9        print('Bird is singing')
10
11    def eat(self):
12        print('Bird is eating')
13
14
15class Dog(Animal):
16    def eat(self):
17        print('Dog is eating')
18
19
20class Cat(Animal):
21    def eat(self):
22        print('Cat is eating')
23
24
25print('Animal')
26a = Animal()
27a.eat()
28print('Bird')
29b = Bird()
30b.eat()
31b.sing()
32print('Dog')
33d = Dog()
34d.eat()
35print('Cat')
36c = Cat()
37print('This is End\n')
38
39
40def demo_eat(a):
41    a.eat()
42
43
44for i in [a, b, c, d]:
45    demo_eat(i)
 1Animal
 2Animal is eating
 3Bird
 4Bird is eating
 5Bird is singing
 6Dog
 7Dog is eating
 8Cat
 9This is End
10
11Animal is eating
12Bird is eating
13Cat is eating
14Dog is eating

type和isinstance的使用

 1class A:
 2    pass
 3
 4
 5class B(A):
 6    pass
 7
 8
 9a = A()
10b = B()
11c = 1
12print('Type A', type(A))
13print('Type B', type(B))
14print('a->A', isinstance(a, A))
15print('c->int', isinstance(c, int))
16print('c->str', isinstance(c, str))
17print('b->B', isinstance(b, B))
18print('b->A', isinstance(b, A))  # 因为B继承自A

类属性和实例属性

类属性在在创建实例时会保留在实例中,修改实例中的属性不回影响到类的属性

但修改类中的属性会影响到后续通过此类实例化出来的实例。

 1class Student:
 2    count = 0
 3
 4    def __init__(self, name):
 5        Student.count += 1
 6        self.name = name
 7
 8
 9s1 = Student('A')
10s2 = Student('B')
11s3 = Student('C')
12print(Student.count)
13
14# print(Student.count)
15# # print(Student.name) 必须有实例才能访问
16# s1 = Student(name='A')
17# print(s1.name)
18# print(s1.count)
19#
20# s1.name = 'B'
21# s1.count = 1
22# print(s1.name)
23# print(s1.count)
24# print(Student.count)
25#
26# Student.count = 2
27# s2 = Student(name='C')
28# print('After change')
29# print(Student.count)
30# print(s1.count)
31# print(s2.count)
 10
 2A
 31
 4B
 51
 61
 7After change
 83
 91
103

类方法和实例方法

类中的普通方法只能先实例化之后,通过实例调用

类中的类方法可以直接调用,不用实例化。类方法因为有cls参数,所以可以调用类中的其他方法(例如静态方法和其他的类方法)

类中的静态方法可以直接调用,不用实例化。

 1class People:
 2    def __init__(self, name, age):
 3        self.name = name
 4        self.age = age
 5
 6    def sayhi(self):
 7        print(f"Hi, my name is {self.name}, and I'm {self.age}")
 8
 9    @classmethod
10    def test1(cls):
11        print('This is a class method')
12        cls.test2()  # 因为有cls参数,所以可以调用class方法
13
14    @staticmethod
15    def test2():
16        print('This is a static method')
17
18
19p1 = People(name='Jack', age=20)
20p1.sayhi()
21p1.test1()
22p1.test2()
23print('-------------')
24People.test1()
25People.test2()

模块和包

 1# ch8/demo/math.py
 2def my_sum(*args):
 3    result = 0
 4    for i in args:
 5        result += i
 6    return result
 7
 8
 9def my_max(*args):
10    print("max Value")
11
12
13def my_min(*args):
14    print("min Value")
15
16
17class People:
18    def __init__(self, name, age):
19        self.name = name
20        self.age = age
21
22
23MAX_NUM = 100
24
25
26# print(my_sum(1, 2, 3, 4))
 1# ch8/test.py
 2import sys
 3
 4if '/Users/akvicor/Documents/GitHub/Course/LearnCode/Python' not in sys.path:
 5    sys.path.append('/Users/akvicor/Documents/GitHub/Course/LearnCode/Python')
 6# print(sys.path)
 7
 8from ch8.demo.math import my_sum
 9
10# 只能在pycharm里才不会报错
11# 默认从系统根目录里寻找或从当前目录寻找,pycharm会自动添加ch8设为系统根目录
12print(my_sum(1, 2, 3, 4))

一般在使用import导入包时,最上面一组为系统自带的,中间一组为第三方的,最下面一组为自己的。

Terminal进入venv环境

进入项目目录然后 source venv/bin/activate

if __name__ == “__main__”

直接执行一个文件的时候,这个文件里面的 __name__ 就等于 __main__

否则 __name__等于文件所在位置

可以使用此语句可以防止此文件被别的文件引用时输出调试信息

pypi

pypi.org

查看包的一些信息

输入输出和文件

print和input本身就是条用了sys,所以我们可以直接使用sys来输入输出

1import sys
2print('Hello World', 'python', sep='%', end='.\n')
3sys.stdout.write('Hello world!\n')
4
5# a = input('ddd: ')
6# print(a, type(a))
7a = sys.stdin.readlines()  # command + D  to stop
8print(a, type(a))

写入文件,mode默认为r参数

 1f = open("test2.txt", mode='w', encoding='utf8')
 2
 3f.write("line 1\n")
 4f.writelines(['This is second line\n', "line 3\n"])
 5f.write("测试中文")
 6
 7f.close()
 8
 9"""
10参数列表:
11file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True
12
13    ========= ===============================================================
14    Character Meaning
15    --------- ---------------------------------------------------------------
16    'r'       open for reading (default)
17    'w'       open for writing, truncating the file first
18    'x'       create a new file and open it for writing
19    'a'       open for writing, appending to the end of the file if it exists
20    'b'       binary mode
21    't'       text mode (default)
22    '+'       open a disk file for updating (reading and writing)
23    'U'       universal newline mode (deprecated)
24    ========= ===============================================================
25"""

f为文件指针,当使用readline或readlines的时候指针会向后移动,再次调用时会从指针处继续读,只有用seek将指针改为文件开始处才可以重新从头读

 1f = open("test2.txt", encoding='utf-8')
 2
 3# a = f.read()  # while read all line from file, and is very slowly
 4# print(a, type(a))
 5
 6# for line in f:  # it will be quickly  # only one times for read
 7#     print(line)
 8
 9a = f.readline()  # while read all line from file, and is very slowly
10b = f.readlines()
11print(a, type(a))
12print(b, type(b))
13
14f.seek(0)  # back to first line
15
16
17f.close()

os

 1import os
 2
 3os.getcwd()  # 返回一个str,获取当前目录的完整路径
 4
 5os.listdir()  # 返回一个list,包含当前目录里的所有文件和文件夹
 6
 7os.mkdir('demo')  # 创建文件夹
 8
 9os.path.isdir('demo')  # 如果参数是文件夹,返回True
10
11os.chdir('demo')  # 进入一个目录
12
13os.path.exists('demo.txt')  # 当前目录下有没有这个文件夹或者文件,可以是根目录
14
15os.path.join('ch', 'demo.txt')  # 拼接目录,自动添加 '/'

使用pathlib进行文件相关操作

 1import os
 2from pathlib import Path
 3
 4# in_file = os.path.join(os.getcwd(), 'demo', 'test.txt')
 5#
 6# print(in_file)
 7#
 8# a = Path.cwd() / 'demo' / 'test.txt'
 9#
10# print(a)
11# print(type(a))
12#
13# print(a.is_file())
14# print(a.is_dir())
15# print(a.lstat())
16# print(a.parent)
17
18# b = Path.cwd() / 'demo'
19# b = b / 'test'
20# b.rmdir()
21
22p = Path.cwd()
23
24for file in p.glob('*'):
25    print(file)
26
27print('******************************************************************************')
28
29for file in p.rglob('*'):
30    print(file)

读写二进制文件

 1a = 'hello world'
 2b = b'hello world'
 3
 4type(a)  # <class 'str'>
 5type(b)  # <class 'bytes'>
 6
 7
 8f = open('test3.txt', 'wb')
 9f.write(b'Hello world!')
10f.close()
11
12ff = open('test3.txt', 'rb')
13print(ff.read())
14ff.close()

序列化对象

 1import pickle
 2
 3
 4class People:
 5    def __init__(self, name, age):
 6        self.name = name
 7        self.age = age
 8
 9    def sayhi(self):
10        print("Hi, my name is {}, and I'm {}".format(self.name, self.age))
11
12
13p1 = People(name='Akvicor', age=20)
14f = open('p1', 'wb')
15pickle.dump(p1, f)
16f.close()
17
18
19# 测试序列化对象的加载 (需要类的原型去映射)
20
21fp = open('p1', 'rb')
22p2 = pickle.load(fp)
23f.close()
24print(p2)

函数式编程

  • 高阶函数是至少满足下列一个条件的函数
    • 接受一个或多个函数作为输入
    • 输出一个函数
1print(sum([1,2,3]))
2b = sum
3print(b([1,2,3]))  # 因为sum是一个函数,所以b被赋值为sum后,b也是个函数,功能与sum相同
4def test(x, f):
5    return f(x)
6printf(test([1,2,3], sum)) # 因为传入的函数为sum, 所以功能为求和
7printf(test([1,2,3], max)) # 因为传入的函数为max, 所以功能为求最大值
8# test就是一个高阶函数

lambda 匿名函数

 1def test(x, y):
 2    return x + 2 * y
 3
 4
 5f = lambda x, y: x + 2 * y
 6
 7print(test(1, 2))
 8print(f(1, 2))
 9
10
11def demo(x, y, f):
12    return f(x, y)
13
14
15print(demo(1, 2, lambda x, y: x + 2 * y))
16
17
18def add_n(n):
19    return lambda x: n + x
20
21
22f = add_n(40)
23print(f(1))
24print(f(-10))

列表解析

1a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
2
3b = [item**2 for item in a if item % 2 == 0]
4
5print(b)
6
7# 列表解析
8
9# 字典解析

高阶函数map和reduce

 1from functools import reduce
 2
 3a = [1, 2, 3, 4]
 4
 5# def f(x, y):
 6#     return x + y
 7
 8
 9m = map(lambda x: x * x, a)
10
11for i in m:
12    print(i)
13
14
15r = reduce(lambda x, y: x + y, a)
16
17print("r ", r)

filter

 1a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
 2
 3f = filter(lambda x: x % 2 == 1, a)
 4print(f)
 5for i in f:
 6    print(i, end=' ')
 7
 8print("\nlist")
 9
10ff = [i for i in a if i % 2 == 1]
11print(ff)

decorator

 1def test1(x):
 2    # print(test1.__name__)
 3    return x * 2
 4
 5
 6def test2(x):
 7    # print(test2.__name__)
 8    return x**3
 9
10
11test1(1)
12test2(2)
13
14
15def demo(f):
16    def f_new(x):
17        print(f.__name__)
18        return f(x)
19    return f_new
20
21
22f = demo(test1)
23
24print(f(3))
25
26
27#  装饰器
28
29@demo
30def test3(x):
31    return x * 2 * x
32
33
34print("for the test3")
35a = test3(4)
36print(a)
37
38
39@demo
40def test3(x):
41    print('hello world')
42
43
44print('After @@')
45test3(1)

完善装饰器

主要是文档注释等函数属性问题

 1import functools
 2
 3
 4def demo(f):
 5    """
 6       This is f
 7       :param f:
 8       :return:
 9    """
10    @functools.wraps(f)  # 解决文档注释问题
11    def f_new(*args, **kwargs):
12        """
13        This is f-new
14        :param args:
15        :param kwargs:
16        :return:
17        """
18        print(f.__name__)
19        return f(*args, **kwargs)
20    # 解决文档注释问题, 或者使用functiontools解决
21    # f_new.__name__ = f.__name__
22    # f_new.__doc__ = f.__doc__
23    return f_new
24
25
26@demo
27def test1(x, y):
28    """
29    This is test 1
30    :param x: integer
31    :param y: integer
32    :return: str
33    """
34    print(f'x={x}, y{y}')
35
36
37test1(1, 2)
38
39print(test1.__name__)
40print(test1.__doc__)

异常和处理

 1a = [10, 4, 3, 7, 11, 6, 0, 9, 22, 'c']
 2try:
 3    b = [item for item in a if 100 % item == 0]
 4    print(b)
 5except ZeroDivisionError:
 6    print('Zero Error')
 7except TypeError:
 8    print('Type Error')
 9except Exception as e:
10    print('Other', e)
11
12print('Finished')

自定义异常

 1class MyException(Exception):
 2    pass
 3
 4
 5# raise MyException("This is user defined exception")
 6
 7try:
 8    raise MyException("This is user defined exception")
 9except MyException as e:
10    print(e)

assert

1def demo(x, y):
2    return x + y
3
4
5print(demo(1, 2))
6assert(demo(1, 2) != 3)

try-except-else

1try:
2    # 执行代码
3except:
4    # 如果有异常发生,执行此处代码
5else:
6    # 如果没有异常发生,执行此处代码

try-except-else-finally

1try:
2    # 执行代码
3except:
4    # 如果有异常发生,执行此处代码
5else:
6    # 如果没有异常发生,执行此处代码
7finally:
8    # 不管有没有异常都会执行此处代码

调试和测试

pdb 调试

1import pdb
2
3pdb.set_trace()

PyCharm Debug

doc test

适合小型的项目

 1def func_demo(a, b):
 2    """ doc test demo
 3    >>> func_demo(1, 2)
 4    3
 5    >>> func_demo('a', 'b')
 6    'ab'
 7    >>> func_demo([1, 2], [3, 4])
 8    [1, 2, 3, 4]
 9    >>> func_demo(1, '2')
10    Traceback (most recent call last):
11    TypeError: unsupported operand type(s) for +: 'int' and 'str'
12    >>>
13    """
14    return a + b
15
16
17if __name__ == "__main__":
18    import doctest
19    doctest.testmod()

单元测试

Python单元测试规范

  • 测试都是以class形式定义
  • 每一个测试类都必须是 unittest.TestCase 的子类
  • 每一个测试类里的测试方法都必须以 test_ 开头
  • 使用 assert 去检查预期结果和实际结果是否相符
  • 在测试方法运行之前需要使用 setUp() 方法预先定义一些测试规范和临时变量
  • 在测试方法执行完之后需要使用 tearDown() 方法清理和销毁临时变量等测试环境
  • 使用 python -m unittest -v test_module 执行测试

unittest

 1import unittest
 2
 3from demo.math import add
 4
 5
 6class TestAdd(unittest.TestCase):
 7    def test_add(self):
 8        self.assertEqual(add(1, 4), 5)
 9
10    def test_add2(self):
11        self.assertEqual(add(10, 20), 30)
12        self.assertNotEqual(add(10, 20), 31)
13
14    def test_add3(self):
15        self.assertRaises(ValueError, add, 1, 1.2)
16
17
18if __name__ == '__main__':
19    unittest.main()

pysnooper

pip install pysnooper

1import pysnooper
2
3@pysnooper.snoop()
4def f(a, b):
5    return a + b
6
7
8f(1, 2)

logging 模块

 1"""
 2low -> high
 3debug(), info(), warning(), error(), critical()
 4"""
 5import logging
 6
 7logging.basicConfig(level='INFO')
 8
 9logging.debug('This is debug')
10logging.info('This is info')
11logging.warning('This is warning')
12logging.error('This is error')
13logging.critical('This is critical')

文件写入

 1"""
 2low -> high
 3debug(), info(), warning(), error(), critical()
 4"""
 5import logging
 6
 7logging.basicConfig(level='INFO', filename='test.log', filemode='w')  # w 重新生成文件,默认在文件结尾添加内容
 8
 9logging.debug('This is debug')
10logging.info('This is info')
11logging.warning('This is warning')
12logging.error('This is error')
13logging.critical('This is critical')

logging format

 1"""
 2https://docs.python.org/3/library/logging.html#logrecord-attributes
 3"""
 4import logging
 5
 6format = '%(asctime)s-%(funcName)s-%(lineno)d-%(levelname)s %(name)s %(message)s'
 7
 8logging.basicConfig(level='INFO', format=format)
 9# logging.BASIC_FORMAT
10
11
12def main():
13    logging.debug('this is debug')
14    logging.info('this is info')
15    logging.warning('this is warning')
16    logging.error('this is erro')
17    logging.critical('this is critical')
18
19
20if __name__ == "__main__":
21    main()

创建新的logging对象

 1import logging
 2
 3logger = logging.getLogger(name='demo')
 4logger.setLevel(logging.DEBUG)
 5
 6# Create handlers
 7c_handler = logging.StreamHandler()
 8f_handler = logging.FileHandler('file.log')
 9c_handler.setLevel(logging.DEBUG)
10f_handler.setLevel(logging.INFO)
11
12# Create formatters and add it to handlers
13c_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
14f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
15c_handler.setFormatter(c_format)
16f_handler.setFormatter(f_format)
17
18# Add handlers to the logger
19logger.addHandler(c_handler)
20logger.addHandler(f_handler)
21
22
23def main():
24    logger.debug('this is debug')
25    logger.info('this is info')
26    logger.warning('this is warning')
27    logger.error('this is erro')
28    logger.critical('this is critical')
29
30
31if __name__ == '__main__':
32    main()

pypy提高python代码执行效率

链接

bin目录下为可执行文件

测试代码

 1import time
 2
 3
 4def test():
 5    for i in range(1, 10):
 6        n = pow(10, i)
 7        start_time = time.time()
 8        sum(x for x in range(1, n+1))
 9        end_time = time.time()
10        print(f'10^{i}:{end_time-start_time}')
11
12
13test()

Normal

110^1:3.0994415283203125e-06
210^2:8.106231689453125e-06
310^3:6.008148193359375e-05
410^4:0.0006120204925537109
510^5:0.006687164306640625
610^6:0.06196117401123047
710^7:0.49938416481018066
810^8:4.975664854049683
910^9:49.28339099884033

PyPy

110^1:1.811981201171875e-05
210^2:6.198883056640625e-05
310^3:0.0033159255981445312
410^4:0.00019216537475585938
510^5:0.001216888427734375
610^6:0.0063250064849853516
710^7:0.05159306526184082
810^8:0.5082838535308838
910^9:5.0509021282196045

除另有声明外本博客文章均采用 知识共享 (Creative Commons) 署名 4.0 国际许可协议 进行许可转载请注明原作者与文章出处