前言

宝剑锋从磨砺出,梅花香自苦寒来。

IDLE常用快捷键

快捷键 功能说明
Alt+N Alt+P 查看历史命令上一条、下一条
Ctrl+F6 重启 shell,以前定义的变量全部失效
F1 打开帮助文档
Alt+/ 自动补全前面曾经出现过的单词
Ctrl + [ Ctrl + ] 缩进代码和取消缩进
Alt+M 打开模块代码,先选中模块,然后按下此快捷键,会帮你 打开改模块的 py 源码供浏览
Alt+C 打开类浏览器,方便在源码文件中的各个方法体之间切换
F5 运行程序

利用海龟模块制作图形化设计

例子1:一些简单的绘制函数

import turtle #导入 turtle 模块
turtle.showturtle() #显示箭头
turtle.write("南海耗子哥") #写字符串
turtle.forward(300) #前进 300 像素
turtle.color("red") #画笔颜色改为 red
turtle.left(90) #箭头左转 90 度
turtle.forward(300)
turtle.goto(0,50) #去坐标(0,50)
turtle.goto(0,0)
turtle.penup() #抬笔。这样,路径就不会画出来
turtle.goto(0,300)
turtle.pendown() #下笔。这样,路径就会画出来
turtle.circle(100) #画圆

例子2:绘制4个矩形图案

import turtle
turtle.width(2)
turtle.color("red")
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.goto(100,0)
turtle.left(90)
turtle.penup()
turtle.forward(20)
turtle.pendown()
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.penup()
turtle.forward(20)
turtle.left(90)
turtle.pendown()
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.penup()
turtle.left(90)
turtle.forward(20)
turtle.pendown()
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.left(90)
turtle.forward(100)

\行连接符

一行程序长度是没有限制的,但是为了可读性更强,通常将一行比较长的程序分为多行。这 是,我们可以使用\行连接符,把它放在行结束的地方。Python 解释器仍然将它们解释为同 一行。

a=[10,20,30,40,\50,60,70]
print(a)
>>> a [10, 20, 30, 40, 50, 60, 70]

引用

在 Python 中,变量也成为:对象的引用。因为变量存储的就是对象的地址。 变量通过地址引用了“对象”。变量位于:栈内存。对象位于:堆内存。

使用 Python 帮助系统查看关键字

help()
help> keywords

Python 标识符命名规则

类型 规则 例子
模块和包名 全小写字母,尽量简单 math, os, sys
函数名 全小写字母,多个单词之间用下划线隔开 show,my_name
函数名 全小写字母,多个单词之间用下划线隔开 show,my_name
类名 首字母大写,采用驼峰原则。多个单词时,每个单词第一个字母大写,其余部分小写 My_Name
常量名 全大写字母,多个单词之间用下划线隔开 SPEED

进制

除 10 进制,还有其他三种进制:
·0b 或 0B,二进制 0 1
·0o 或 0O,八进制 0 1 2 3 4 5 6 7
·0x 或 0X,十六进制 0 1 2 3 4 5 6 7 8 9 a b c d e f
这三种进制可以非常方便的进行“位运算”操作。位运算知识后续将会介绍

变量赋值

链式赋值:

x=y=123

系列解包赋值

删除变量

a=123
del a

特殊运算符

运算符 说明 例子
/ 浮点数除法 8/2=4.0
// 整数除法 7//2=3
% 模(取余) 7%4=3
** 2**3=8

特殊运算函数

运算符函数 说明 例子
math.sqrt() 开方 math.sqrt(2**2)=2
divmod() 同时得到商和余数 divmod(10,3)=(3,1)
round(value) 返回四舍五入的值 round(4.6)=4.7
bin() 可以将数字转成二进制表示 bin(8)=04

时间的表示

计算机中时间的表示是从“1970 年 1 月 1 日 00:00:00”开始,以毫秒(1/1000 秒) 进行计算。我们也把 1970 年这个时刻成为“unix 时间点”。可以通过 time.time() 获得当前时刻,返回的值是以秒为单位,带微秒 (1/1000 毫秒)精度的浮点值。例如:1530167364.8566。

import time
b = int(time.time())
print(b)
totalMinutes = b/60
totalMinutes = b//60
totalHours = totalMinutes//60
totalDays = totalHours//24
totalYears = totalDays//365 

同一运算符

  1. is 用于判断两个变量引用对象是否为同一个,既比较对象的地址。
  2. is not 是判断两个标识符是不是引用不同对象 。
  3. == 用于判断引用变量引用对象的值是否相等,默认调用对象的 eq()方法。
    示例代码:
c = 10
d = 10
c is d
>>>True
id(c)
>>>1388831648
id(d)
>>>1388831648

位操作

a = 0b11001
b = 0b01000
c = a|b
bin(c) #bin()可以将数字转成二进制表示 '0b11001'
bin(c&b) '0b1000'
bin(c^b) '0b10001'
a = 3
a<<2 #左移 1 位相当于乘以 2.左移 2 位,相当于乘以 4 12
a = 8
a>>1 #右移 1 位相当于除以 

优先级

如下优先级,从高到低

字符串

使用内置函数 ord()可以把字符转换成对应的 Unicode 码。
使用内置函数 chr()可以把十进制数字转换成对应的字符。

ord('A') >>> 65
ord('耗') >>> 39640
chr(66) >>>  'B'
ord('子') >>> 28103

连续三个单引号或三个双引号,可以帮助我们创建多行字符串。

resume = ''' name="耗子哥"
company="sxt"
age=18
lover="耗子嫂"'''
print(resume)
>>> name="耗子哥"
>company="sxt"
>age=18 lover="耗子嫂"'''

转义字符

字符 功能
\r 回车
(在行尾时) 续行符
\b 退格(Backspace)

不换行打印

print("sxt",end=' ')
print("sxt",end='##')
print("sxt")

用[]提取字符串中的特定字符。

replace()实现字符串替换

字符串不可改变。但是,我们确实有时候需要替换某些字符。这时,只能通过创建新的字符串来实现。

a = 'abcdefghijklmnopqrstuvwxyz'
a 'abcdefghijklmnopqrstuvwxyz'
a = a.replace('c','高')
>>> 'ab 高 defghijklmnopqrstuvwxyz'

整个过程中,实际上我们是创建了新的字符串对象,并指向了变量 a,而不是修改了以前的 字符串。

字符串切片 slice 操作

split()分割和 join()合并

split()可以基于指定分隔符将字符串分隔成多个子字符串(存储到列表中)。如果不指定分隔 符,则默认使用空白字符(换行符/空格/制表符)。
join()的作用和 split()作用刚好相反,用于将一系列子字符串连接起来。

a = "to be or not to be"
a.split()
>>>['to', 'be', 'or', 'not', 'to', 'be']
a.split('be')
>>>['to ', ' or not to ', '']
a = ['sxt','sxt100','sxt200']
'*'.join(a)
>>> 'sxt*sxt100*sxt200'

字符串驻留机制

a = "abd_33"
b = "abd_33"
a is b
>>> True
c = "dd#"
d = "dd#"
c is d
>>> False
str1 = "aa"
str2 = "bb"
str1+str2 is "aabb"
>>> False
str1+str2 == "aabb"
>>> True

常用查找方法

我们以一段文本作为测试: a=’’'我是高淇,今年 18 岁了,我在北京尚学堂科技上班。我的儿子叫高洛希,他 6 岁了。我 是一个编程教育的普及者,希望影响 6000 万学习编程的中国人。我儿子现在也开始学习编 程,希望他 18 岁的时候可以超过我

去除首尾信息

"*s*x*t*".strip("*")
>>> 's*x*t'
"*s*x*t*".lstrip("*")
>>> 's*x*t*'
"*s*x*t*".rstrip("*")
>>> '*s*x*t' >>> " sxt ".strip()
>>>> 'sxt' 

大小写转换

格式排版

center()、ljust()、rjust()这三个函数用于对字符串实现排版。示例如下:

 a="SXT"a.center(10,"*")  >>>'***SXT****' a.center(10) >>>' SXT ' a.ljust(10,"*") >>>'SXT*******' 

还有一些方法,例如:

 1. isalnum() 是否为字母或数字 2. isalpha() 检测字符串是否只由字母组成(含汉字)。3.  isdigit() 检测字符串是否只由数字组成。 4. isspace() 检测是否为空白符 5. isupper() 是否为大写字母 6. islower() 是否为小写字母
a = "名字是:{0},年龄是:{1}"
a.format("耗子",18)
>>> '名字是:耗子,年龄是:18'
a.format("耗子哥",6)
>>> '名字是:耗子哥,年龄是:6'
b = "名字是:{0},年龄是{1}。{0}是个好小伙"
b.format("耗子",18)
>>> '名字是:耗子,年龄是 18。耗子是个好小伙'
c = "名字是{name},年龄是{age}"
c.format(age=19,name='耗子')
>>> '名字是耗子,年龄是 19' 

填充与对齐

填充常跟对齐一起使用 ^、<、>分别是居中、左对齐、右对齐,后面带宽度 :号后面带填充的字符,只能是一个字符,不指定的话默认是用空格填充。

 "{:*>8}".format("245") >>>'*****245' "我是{0},我喜欢数字{1:*^8}".format("耗子","666")
'我是耗子,我喜欢数字**666***'
a = "我是{0},我的存款有{1:.2f}"
a.format("高淇",3888.234342)
>>> '我是高淇,我的存款有 3888.23' 

可变字符串

在 Python 中,字符串属于不可变对象,不支持原地修改,如果需要修改其中的值,智 能创建新的字符串对象。但是,经常我们确实需要原地修改字符串,可以使用 io.StringIO 对象或 array 模块。

import io
s = "hello, sxt"
sio = io.StringIO(s)
print(sio)
>>><_io.StringIO object at 0x02F462B0>
sio.getvalue()
>>>'hello, sxt'
sio.seek(7)
>>>7
sio.write("g")
>>>1sio.getvalue() >>>'hello, gxt' 

sio.seek可以定位坐标,sio.write()对该坐标位置点的数据进行修改。

列表

列表是内置可变序列,是包含多个元素的有序连续的内存空间。列表定义的标准语法格式: a = [10,20,30,40] 其中,10,20,30,40 这些称为:列表 a 的元素。 列表中的元素可以各不相同,可以是任意类型。比如: a = [10,20,‘abc’,True] 。
示例代码

a = list() #创建一个空的列表对象
a = list(range(10))
>>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

append()方法 :原地修改列表对象,是真正的列表尾部添加新的元素,速度最快,推荐使用。

python a = [20,40]
a.append(80)
a [20, 40, 80] 

+运算符操作:
并不是真正的尾部添加元素,而是创建新的列表对象;将原列表的元素和新列表的元素依次 复制到新的列表对象中。这样,会涉及大量的复制操作,对于操作大量元素不建议使用。

a = [20,40]
>>> id(a) 46016072
a = a+[50]
>>> id(a) 46015432 

extend()方法
将目标列表的所有元素添加到本列表的尾部,属于原地操作,不创建新的列表对象。

a = [20,40]
>>> id(a) 46016072
a.extend([50,60])
>>> id(a) 46016072

insert()插入元素
使用 insert()方法可以将指定的元素插入到列表对象的任意制定位置。这样会让插入位置后 面所有的元素进行移动,会影响处理速度。涉及大量元素时,尽量避免使用。类似发生这种 移动的函数还有:remove()、pop()、del(),它们在删除非尾部元素时也会发生操作位置后 面元素的移动。

a = [10,20,30]
a.insert(2,100)
>>> a [10, 20, 100, 30] 

乘法扩展
使用乘法扩展列表,生成一个新列表,新列表元素时原列表元素的多次重复。

a = ['sxt',100]
b = a*3
>>> a ['sxt', 100]
>>> b ['sxt', 100, 'sxt', 100, 'sxt', 100] 

index()获得指定元素在列表中的首次出现的索引

a=[10,20,30,40,50,20,30,30]
a=index(20)
>>>1
a=index(20,3)
>>>5
a=index(20,3)#从索引位置3开始往后搜索的第一个20
>>>5
a=index(30,5,7)#从索引位置3开始往后搜索的第一个20

count()获得指定元素在列表中出现的次数

a = [10,20,30,40,50,20,30,20,30]
a.count(20)
>>>3

列表切片

列表的复制

list1 = [30,40,50]
list2 = list1

只是将 list2 也指向了列表对象,也就是说 list2 和 list2 持有地址值是相同的,列表对象本 身的元素并没有复制。我们可以通过如下简单方式,实现列表元素内容的复制:

list1 = [30,40,50]
list2 = [] + list1

修改原列表,不建新列表的排序

a = [20,10,30,40]
id(a)
>>> 46017416
a.sort() #默认是升序排列
a
>>> [10, 20, 30, 40]
a = [10,20,30,40]
a.sort(reverse=True) #降序排列
a
>>> [40, 30, 20, 10]
import random
random.shuffle(a) #打乱顺序
a
>>>[20, 40, 30, 10] 

我们也可以通过内置函数 sorted()进行排序,这个方法返回新列表,不对原列表做修改。具体操作与sort函数一致。

a = [20,10,30,40] >>> c = reversed(a) >>> c <list_reverseiterator object at 0x0000000002BCCEB8> >>> list(c) [40, 30, 10, 20] >>> list(c) []

reversed()返回迭代器

a = [20,10,30,40]
c = reversed(a)
c
>>><list_reverseiterator object at 0x0000000002BCCEB8>
list(c)
[40, 30, 10, 20]
list(c)
[]

第一次输出了元素,第二次为空。那是因为迭代对象 在第一次时已经遍历结束了,第二次不能再使用。
max 、sum和 min

a = [3,10,20,15,9]
max(a)
>>>20
min(a)
>>>3
sum(a)
>>>57

二维列表

a = [["高小一",18,30000,"北京"],["高小二",19,20000,"上海"], ["高小一",20,10000,"深圳"], ]
for m in range(3): for n in range(4): print(a[m][n],end="\t") print() #打印完一行,换行 

元组 tuple

列表属于可变序列,可以任意修改列表中的元素。元组属于不可变序列,不能修改元组中的 元素。因此,元组没有增加元素、修改元素、删除元素相关的方法。

元组的创建

a = (1)
type(a)
>>> <class 'int'>
a = (1,) #或者 a = 1
type(a) <class 'tuple'>
b = tuple() #创建一个空元组对象
b = tuple("abc")
b = tuple(range(3))
b = tuple([2,3,4])

tuple()可以接收列表、字符串、其他序列类型、迭代器等生成元组。 list()可以接收元组、字符串、其他序列类型、迭代器等生成列表。

zip

zip(列表 1,列表 2,…)将多个列表对应位置的元素组合成为元组,并返回这个 zip 对象。

a = [10,20,30]
b = [40,50,60]
c = [70,80,90]
d = zip(a,b,c)
list(d)
>>>[(10, 40, 70), (20, 50, 80), (30, 60, 90)]

字典

以通过{}、dict()来创建字典对象

a = {'name':'gaoqi','age':18,'job':'programmer'}
b = dict(name='gaoqi',age=18,job='programmer')
a = dict([("name","gaoqi"),("age",18)])
c = {} #空的字典对象
d = dict() #空的字典对象 

通过 zip()创建字典对象

k = ['name','age','job']
v = ['gaoqi',18,'techer']
d = dict(zip(k,v))
d
>>>{'name': 'gaoqi', 'age': 18, 'job': 'techer'} 

通过 fromkeys 创建值为空的字典

a = dict.fromkeys(['name','age','job'])
a {'name': None, 'age': None, 'job': None}

通过 [键] 获得“值”。若键不存在,则抛出异常

a = {'name':'gaoqi','age':18,'job':'programmer'}
a['name']
>>>'gaoqi'
a['age']
>>>18
a['sex'] 

通过 get()方法获得“值”。推荐使用。优点是:指定键不存在,返回 None;也可以设 定指定键不存在时默认返回的对象。推荐使用 get()获取“值对象”。

a.get('name')
>>> 'gaoqi'
a.get('sex')
a.get('sex','一个男人')
>>> '一个男人' 

列出所有的键值对

a.items()
>>> dict_items([('name', 'gaoqi'), ('age', 18), ('job', 'programmer')]) 

列出所有的键,列出所有的值

a.keys()
>>> dict_keys(['name', 'age', 'job'])
a.values()
>>> dict_values(['gaoqi', 18, 'programmer']) 

len() 键值对的个数
检测一个“键”是否在字典中

a = {"name":"gaoqi","age":18}
"name" in a
>>>True

给字典新增“键值对”。如果“键”已经存在,则覆盖旧的键值对;如果“键”不存在, 则新增“键值对”。

a = {'name':'gaoqi','age':18,'job':'programmer'}
a['address']='西三旗 1 号院'
a['age']=16
a
>>>{'name': 'gaoqi', 'age': 16, 'job': 'programmer', 'address': '西三旗 1 号院'} 

使用 update()将新字典中所有键值对全部添加到旧字典对象上。如果 key 有重复,则直接覆盖。

a = {'name':'gaoqi','age':18,'job':'programmer'}
b = {'name':'gaoxixi','money':1000,'sex':'男的'}
a.update(b)
a
>>>{'name': 'gaoxixi', 'age': 18, 'job': 'programmer', 'money': 1000, 'sex': '男的'}

字典中元素的删除,可以使用 del()方法;或者 clear()删除所有键值对;pop()删除指定 键值对,并返回对应的“值对象”。

a = {'name':'gaoqi','age':18,'job':'programmer'}
del(a['name'])
a
>>> {'age': 18, 'job': 'programmer'}
b = a.pop('age')
b
>>> 18 

popitem() :随机删除和返回该键值对。字典是“无序可变序列”,因此没有第一个元素、最后一个元素的概念;popitem 弹出随机的项,因为字典并没有"最后的元素"或者其 他有关顺序的概念。若想一个接一个地移除并处理项,这个方法就非常有效(因为不用首先获取键的列表)。

a = {'name':'gaoqi','age':18,'job':'programmer'}
a.popitem()
>>>('job', 'programmer')
a
>>>{'name': 'gaoqi', 'age': 18}
a.popitem()
>>>('age', 18)
a
>>>{'name': 'gaoqi'}

序列解包

序列解包可以用于元组、列表、字典。序列解包可以让我们方便的对多个变量赋值。

x,y,z=(20,30,10)
x
>>>20
y
>>>30
z
>>>10
(a,b,c)=(9,8,10)
a
>>>9
[a,b,c]=[10,20,30]
a
>>>10
b
>>>20 

序列解包用于字典时,默认是对“键”进行操作; 如果需要对键值对操作,则需要使用 items();如果需要对“值”进行操作,则需要使用 values()。

s = {'name':'gaoqi','age':18,'job':'teacher'}
name,age,job=s #默认对键进行操作
name
>>> 'name'
name,age,job=s.items() #对键值对进行操作
name
>>>('name', 'gaoqi')
name,age,job=s.values() #对值进行操作
name
>>>'gaoqi' 

集合

使用{}创建集合对象,并使用 add()方法添加元素。

a = {3,5,7}
a
>>> {3, 5, 7}
a.add(9)
a
>>> {9, 3, 5, 7}

使用 set(),将列表、元组等可迭代对象转成集合。如果原来数据存在重复数据,则只保 留一个。

a = ['a','b','c','b']
b = set(a)
b
>>>{'b', 'a', 'c'}

remove()删除指定元素;clear()清空整个集合

a = {10,20,30,40,50}
a.remove(20)
a
>>>{10, 50, 30}

像数学中概念一样,Python 对集合也提供了并集、交集、差集等运算。

a = {1,3,'sxt'}
b = {'he','it','sxt'}
a|b #并集
>>>{1, 3, 'sxt', 'he', 'it'}
a&b #交集
>>>{'sxt'}
a-b #差集
>>>{1, 3}
a.union(b) #并集
{1, 3, 'sxt', 'he', 'it'}
a.intersection(b) #交集
>>>{'sxt'}
a.difference(b) #差集
>>>{1, 3} 

列表推导式

[x*2 for x in range(1,20) if x%5==0 ]
>>>[10, 20, 30]

字典推导式

my_text = ' i love you, i love sxt, i love gaoqi'
char_count = {c:my_text.count(c) for c in my_text}
char_count
>>>{' ': 9, 'i': 4, 'l': 3, 'o': 5, 'v': 3, 'e': 3, 'y': 1, 'u': 1, ',': 2, 's': 1, 'x': 1, 't': 1, 'g': 1, 'a': 1, 'q': 1} 

集合推导式

{x for x in range(1,100) if x%9==0}
>>>{99, 36, 72, 9, 45, 81, 18, 54, 90, 27, 63}
for x in gnt:  print(x,end=' ')

全局变量的作用域测试

a = 100 #全局变量
def f1(): global a #如果要在函数内改变全局变量的值,增加 global 关键字声明 print(a) #打印全局变量 a 的值 a = 300
f1()
print(a)
>>>100
>>>300

输出局部变量和全局变量

a = 100
def f1(a,b,c): print(a,b,c) print(locals()) #打印输出的局部变量 print("#"*20) print(globals()) #打印输出的全局变量 f1(2,3,4)

浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用。
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象

#测试浅拷贝和深拷贝
import copy
def testCopy():
'''测试浅拷贝''' a = [10, 20, [5, 6]] b = copy.copy(a) print("a", a) print("b", b)b.append(30) b[2].append(7) print("浅拷贝......") print("a", a) print("b", b)
def testDeepCopy():
'''测试深拷贝''' a = [10, 20, [5, 6]] b = copy.deepcopy(a) print("a", a) print("b", b) b.append(30) b[2].append(7) print("深拷贝......") print("a", a) print("b", b)
testCopy()
print("*************")
testDeepCopy() 

函数参数传递

def f1(a,b,c): print(a,b,c)
f1(8,9,19) #位置参数
f1(c=10,a=20,b=30) #命名参数
>>>8 9 19
>>>20 30 10 

可变参数指的是“可变数量的参数”。分两种情况: 1. *param(一个星号),将多个参数收集到一个“元组”对象中。 2. **param(两个星号),将多个参数收集到一个“字典”对象中。

def f1(a,b,*c): print(a,b,c)
f1(8,9,19,20)
def f2(a,b,**c): print(a,b,c)
f2(8,9,name='gaoqi',age=18)
def f3(a,b,*c,**d): print(a,b,c,d)
f3(8,9,20,30,name='gaoqi',age=18)
>>>8 9 (19, 20)
>>>8 9 {'name': 'gaoqi', 'age': 18}
>>>8 9 (20, 30) {'name': 'gaoqi', 'age': 18}

在带星号的“可变参数”后面增加新的参数,必须在调用的时候“强制命名参数”。

def f1(*a,b,c): print(a,b,c) #f1(2,3,4) #会报错。由于 a 是可变参数,将 2,3,4 全部收集。造成 b 和 c 没有赋值。
f1(2,b=3,c=4) 

ambda 表达式使用

f = lambda a,b,c:a+b+c
print(f)
print(f(2,3,4))
g = [lambda a:a*2,lambda b:b*3,lambda c:c*4] print(g[0](6),g[1](7),g[2](8))
>>><function <lambda> at 0x0000000002BB8620>
>>>9
>>>12 21 32 

eval()函数
功能:将字符串 str 当成有效的表达式来求值并返回计算结果。

#测试 eval()函数
s = "print('abcde')"
eval(s) 

使用递归函数计算阶乘

def factorial(n): if n==1:return 1 return n*factorial(n-1)
for i in range(1,6):print(i,'!=',factorial(i))
结果:
1 != 1
2 != 2
3 != 6
4 != 24
5!=120

嵌套函数定义

def f1(): print('f1 running...')
def f2(): print('f2 running...') f2()
f1() 

测试 nonlocal、global 关键字的用法

a = 100
def outer():b = 10def inner():nonlocal b #声明外部函数的局部变量print("inner b:",b)b = 20global a #声明全局变量a = 1000inner()print("outer b:",b)
outer()
print("a:",a)
>>> inner b: 10
>>> outer b: 20
>>> a: 1000

__del__方法称为“析构方法”,用于实现对象被销毁时所需的操作。比如:释放对象 占用的资源,例如:打开的文件资源、网络连接等。

#析构函数
class Person: def __del__(self): print("销毁对象:{0}".format(self)) p1 = Person()
p2 = Person()
del p2
print("程序结束") 

定义了__call__方法的对象,称为“可调用对象”,即该对象可以像函数一样被调用。

class SalaryAccount:
'''工资计算类''' def __call__(self, salary): yearSalary = salary*12 daySalary = salary//30 hourSalary = daySalary//8 return
dict(monthSalary=salary,yearSalary=yearSalary,daySalary=daySalary ,hourSalary=hourSalary)
s = SalaryAccount()
print(s(5000)) #可以像调用函数一样调用对象的__call__方法
运行结果: {'monthSalary': 5000, 'yearSalary': 60000, 'daySalary': 166, 'hourSalary': 20}

方法的动态性

#测试方法的动态性
class Person: def work(self): print("努力上班!")
def play_game(self): print("{0}玩游戏".format(self))
def work2(s): print("好好工作,努力上班!")
Person.play = play_game
Person.work = work2
p = Person()
p.play()
p.work() 

@property 可以将一个方法的调用方式变成“属性调用”。

#简单测试@property
class Employee: @property def salary(self): return 30000;
emp1 = Employee()
print(emp1.salary) #打印 30000
print(type(emp1.salary)) #打印<class 'int'>

通过 getter、setter 方法限制薪水

#测试@property
class Employee:def __init__(self,name,salary): self.name = name self.__salary = salary @property #相当于 salary 属性的 getter 方法 def salary(self): print("月薪为{0},年薪为 {1}".format(self.__salary,(12*self.__salary))) return self.__salary; @salary.setter def salary(self,salary): #相当于 salary 属性的 setter 方法 if(0<salary<1000000): self.__salary = salary else:print("薪水录入错误!只能在 0-1000000 之间")
emp1 = Employee("高淇",100)
print(emp1.salary)
emp1.salary = -200
运行结果:
月薪为 100,年薪为 1200 100
月薪为 100,年薪为 1200 100
薪水录入错误!只能在 0-1000000 之间
  1. 成员继承:子类继承了父类除构造方法之外的所有成员。
  2. 方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类的方法,也称为“重写”。
class Person: def __init__(self,name,age): self.name = name self.age = age def say_age(self): print(self.name,"的年龄是:",self.age) def say_name(self): print("我是",self.name)
class Student(Person): def __init__(self,name,age,score): self.score = score Person.__init__(self,name,age) #构造函数中包含调用父类构造函数 def say_score(self): print(self.name,"的分数是:",self.score) def say_name(self): #重写父类的方法 print("报告老师,我是",self.name) s1 = Student("张三",15,85) s1.say_score() s1.say_name() s1.say_age()
执行结果: 张三 的分数是: 85 报告老师,我是张三 张三 的年龄是: 15 

通过类的方法 mro()或者类的属性__mro__可以输出这个类的继承层次结构

class A:pass
class B(A):pass
class C(B):pass
print(C.mro())
执行结果:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

object 有一个__str__()方法,用于返回一个对于“对象的描述”,对应于内置函数 str() 经常用于 print()方法,帮助我们查看对象的信息。str()可以重写。

class Person: def __init__(self,name,age): self.name = name self.__age = age def __str__(self): '''将对象转化成一个字符串,一般用于 print 方法''' return "名字是:{0},年龄是{1}".format(self.name,self.__age)
p = Person("高淇",18)
print(p)
>>>名字是:高淇,年龄是 18
#super()
class A: def say(self): print("A: ",self) print("say AAA")
class B(A): def say(self): #A.say(self) 调用父类的 say 方法 super().say() #通过 super()调用父类的方法 print("say BBB")
b = B()
b.say() 

多态

class Animal: def shout(self): print("动物叫了一声")
class Dog(Animal): def shout(self):print("小狗,汪汪汪")
class Cat(Animal): def shout(self): print("小猫,喵喵喵")
def animalShout(a): if isinstance(a,Animal):a.shout() #传入的对象不同,shout 方法对应的实际行为也不 同。
animalShout(Dog())
animalShout(Cat()) 

组合

class MobilePhone: def __init__(self,cpu,screen): self.cpu = cpu self.screen = screen
class CPU: def calculate(self): print("计算,算个 12345")
class Screen: def show(self): print("显示一个好看的画面,亮瞎你的钛合金大眼")
c = CPU()
s = Screen()
m = MobilePhone(c,s)
m.cpu.calculate() #通过组合,我们也能调用 cpu 对象的方法。相当于手机对象间接拥有了“cpu 的方法”
m.screen.show()
运算结果:
计算,算个 12345
显示一个好看的画面,亮瞎你的钛合金大眼 

多线程传递参数

from multiprocessing import Process
import os
from time import sleep
#创建子进程代码
def run_proc(name,age,**kwargs):for i in range(5):                  print('子进程运行中,参数name:%s,age:%d'%(name,age))print('字典参数kwargs:',kwargs)sleep(0.5)if __name__=='__main__':print('主进程开始运行')p=Process(target=run_proc,args=('test',18),kwargs={'m':23})print('子进程将要执行')p.start()

join()方法的使用

from multiprocessing
import Processfrom time
import sleep
def worker(interval):    print("work start");    sleep(interval)    print("work end");
if __name__ == "__main__":p = Process(target = worker, args = (3,))    p.start()    #等待进程p终止    p.join()    print("主进程结束!")

join()方法中加超时的使用

from multiprocessing
import Processfrom time
import sleep
def worker(interval):    print("work start");    sleep(interval)    print("work end");
if __name__ == "__main__":p = Process(target = worker, args = (3,))    p.start()    #等待进程p终止    p.join(3)    print("主进程结束!")

属性的使用

#导入模块
import multiprocessing
import time#定义进程执行函数
def clock(interval):    for i in range(5):        print('当前时间为{0}:'.format(time.ctime()))        time.sleep(interval)
if __name__=='__main__':    #创建进程    p=multiprocessing.Process(target=clock,args=(1,))    #启动进程    p.start()    p.join()    #获取进程的ID    print('p.id:',p.pid)    #获取进程的名称    print('p.name:',p.name)    #判断进程是否运行    print('p.is_alive:',p.is_alive())

进程池的使用(非阻塞)

import multiprocessing
import time
def func(msg):    print("start:", msg)    time.sleep(3)    print("end:",msg)
if __name__ == "__main__":pool = multiprocessing.Pool(processes = 3)    for i in range(5):        msg = "hello %d" %(i)        #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去        pool.apply_async(func, (msg, ))
pool.close()#进程池关闭之后不再接收新的请求    #调用join之前,先调用close函数,否则会出错。    # 执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
pool.join()

进程池的使用(阻塞)

import multiprocessing
import time
def func(msg):    print("start:", msg)    time.sleep(3)    print("end:",msg)
if __name__ == "__main__":pool = multiprocessing.Pool(processes = 3)    for i in range(5):        msg = "hello %d" %(i)        #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去        pool.apply(func, (msg, ))
pool.close()#进程池关闭之后不再接收新的请求    #调用join之前,先调用close函数,否则会出错。    # 执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
pool.join()

进程池的使用(

多个进程中数据不共享
```python
from multiprocessing import Process
num=1
def work1():global numnum+=5print('子进程1运行,num:',num)def work2():global numnum += 10print('子进程2运行,num:',num)
if __name__=='__main__':print('父进程开始运行')p1=Process(target=work1)p2=Process(target=work2)p1.start()p2.start()p1.join()p2.join()print('现在的变量值为%d'%num)

Queue的方法使用

from multiprocessing import Queue
q=Queue(3)
q.put('消息1')
q.put('消息2')
print('消息队列是否已满:',q.full())
q.put('消息3')
print('消息队列是否已满:',q.full())# q.put('消息4')因为消息队列已满,需要直接写入需要等待,如果超时会抛出异常,
# 所以写入时候需判断,消息队列是否已满
if not q.full():q.put('消息4')#同理读取消息时,先判断消息队列是否为空,再读取
if not q.empty():for i in range(q.qsize()):print(q.get())


Queue队列实现进程间通信

from multiprocessing import *
import time
def write(q):    #将列表中的元素写入队列中    for i in ["a","b","c"]:        print('开始写入值%s' % i)        q.put(i)        time.sleep(1) #读取
def read(q):    print('开始读取')    while True:        if not q.empty():print('读取到:',q.get())            time.sleep(1)        else:            break
if __name__=='__main__':    #创建队列    q=Queue()    #创建写入进程    pw=Process(target=write,args=(q,))    pr=Process(target=read,args=(q,))    #启动进程    pw.start()    pw.join()    pr.start()    pr.join()

进程池创建进程完成进程之间的通信

from multiprocessing import Manager,Pool
import time
def write(q):    #将列表中的元素写入队列中for i in ["a","b","c"]:        print('开始写入值%s' % i)        q.put(i)        time.sleep(1) #读取
def read(q):    print('开始读取')    while True:        if not q.empty():            print('读取到:',q.get())            time.sleep(1)        else:            break
if __name__=='__main__':    #创建队列    q=Manager().Queue()    #创建进程池    p=Pool(3)    #使用阻塞模式创建进程    p.apply(write,(q,))    p.apply(read,(q,))    p.close()    p.join()


使用_thread模块创建线程

import _thread
import time
def fun1():print('开始运行fun1')    time.sleep(4)    print('运行fun1结束')
def fun2():    print('开始运行fun2')    time.sleep(2)    print('运行fun2结束')
if __name__=='__main__':    print('开始运行')    #启动一个线程运行函数fun1    _thread.start_new_thread(fun1,())     #启动一个线程运行函数fun2    _thread.start_new_thread(fun2,())    time.sleep(6)

为线程传递参数

import _thread
import time
def fun1(thread_name,delay):    print('线程{0}开始运行fun1'.format(thread_name))    time.sleep(delay)    print('线程{0}运行fun1结束'.format(thread_name))
def fun2(thread_name,delay):    print('线程{0}开始运行fun2'.format(thread_name))    time.sleep(2)    print('线程{0}运行fun2结束'.format(thread_name))
if __name__=='__main__':print('开始运行')    #启动一个线程运行函数fun1    _thread.start_new_thread(fun1,('thread-1',4))     #启动一个线程运行函数fun2    _thread.start_new_thread(fun2,('thread-2',2))    time.sleep(6)

threading.Thread直接创建线程

import threading
import time
def fun1(thread_name,delay):    print('线程{0}开始运行fun1'.format(thread_name))    time.sleep(delay)print('线程{0}运行fun1结束'.format(thread_name))
def fun2(thread_name,delay):print('线程{0}开始运行fun2'.format(thread_name))    time.sleep(delay)    print('线程{0}运行fun2结束'.format(thread_name))
if __name__=='__main__':print('开始运行')    #创建线程    t1=threading.Thread(target=fun1,args=('thread-1',2))    t2=threading.Thread(target=fun2,args=('thread-2',4))    t1.start()    t2.start()

继承threading.Thread类创建线程

import threading
import time
def fun1(delay):print('线程{0}开始运行fun1'.format(threading.current_thread().getName()))    time.sleep(delay)    print('线程{0}运行fun1结束'.format(threading.current_thread().getName()))
def fun2(delay):print('线程{0}开始运行fun2'.format(threading.current_thread().getName()))    time.sleep(2)    print('线程{0}运行fun2结束'.format(threading.current_thread().getName()))
#创建线程类继承threading.Thread
class MyThread(threading.Thread):    #重写父类的构造方法,其中func是线程函数,args是传入线程的参数,name是线程名def __init__(self,func,name,args):super().__init__(target=func,name=name,args=args)    #重写父类的run()方法    def run(self):self._target(*self._args)
if __name__=='__main__':print('开始运行')    #创建线程    t1=MyThread(fun1,'thread-1',(2,))    t2=MyThread(fun2,'thread-2',(4,))    t1.start()    t2.start()

互斥锁

import time
from threading import Thread,Lock
#定义全局变量
numnum=0#创建一把互斥锁
mutex=Lock()
def test1():global num
'''在两个线程中都调用上锁的方法,则这两个线程就会抢着上锁,如果有1方成功上锁,那么导致另外一方会堵塞(一直等待)直到这个锁被解开
'''    for i in range(100000):mutex.acquire()  # 上锁num+=1        mutex.release()    print('test1输出num:',num)
def test2():global num    for i in range(100000):mutex.acquire()  # 上锁        num+=1        mutex.release()    print('test2输出num:',num)
if __name__=='__main__':t1=Thread(target=test1)    t2=Thread(target=test2)    t1.start()    t2.start()    t1.join()    t2.join()


在线程共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。

import timefrom threading
import Thread,Lockimport threadingmutexA=threading.Lock()mutexB=threading.Lock()
class MyThread1(Thread):def run(self):if mutexA.acquire():print(self.name,'执行')            time.sleep(1)            if mutexB.acquire():print(self.name,'执行')               mutexB.release()            mutexA.release()
class MyThread2(Thread):def run(self):    if mutexB.acquire():     print(self.name,'执行')            time.sleep(1)            if mutexA.acquire():       print(self.name,'执行')                mutexA.release()            mutexB.release()
if __name__ == '__main__':t1=MyThread1()    t2=MyThread2()    t1.start()    t2.start()

线程同步应用:如进程、线程同步,可以理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行,B运行后将结果给A,A继续运行。

import time
from threading import Thread,Lock
import threading
lock1=Lock()
lock2=Lock()
lock3=Lock()
lock2.acquire()
lock3.acquire()
class Task1(Thread):def run(self):while True:if lock1.acquire():print('...task1...')time.sleep(1)lock2.release()class Task2(Thread):def run(self):while True:if lock2.acquire():print('...task2...')time.sleep(1)lock3.release()class Task3(Thread):def run(self):while True:if lock3.acquire():print('...task3...')time.sleep(1)lock1.release()if __name__ == '__main__':t1=Task1()t2=Task2()t3=Task3()t1.start()t2.start()t3.start()

生产者-消费者模型
生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入生产者和消费者模式

import time
import threading
from queue import Queue
class Producer(threading.Thread):def run(self):global queuecount=0while True:if queue.qsize()<1000:for i in range(100):count += 1msg = '生成产品' + str(count)queue.put(msg)print(msg)time.sleep(0.5)
class Consumer(threading.Thread):def run(self):global queuewhile True:if queue.qsize()>100:for i in range(3):msg=self.name+'消费了'+queue.get()print(msg)time.sleep(1)
if __name__ == '__main__':queue = Queue()p=Producer()p.start()time.sleep(1)c=Consumer()c.start()


我们知道多线程环境下,每一个线程均可以使用所属进程的全局变量。如果一个线程对全局变量进行了修改,将会影响到其他所有的线程对全局变量的计算操作,从而出现数据混乱,即为脏数据。为了避免多个线程同时对变量进行修改,引入了线程同步机制,通过互斥锁来控制对全局变量的访问。所以有时候线程使用局部变量比全局变量好,因为局部变量只有线程自身可以访问,同一个进程下的其他线程不可访问。
ThreadLocal 变量,它本身是一个全局变量,但是每个线程却可以利用它来保存属于自己的私有数据,这些私有数据对其他线程也是不可见的。

import threading
# 创建全局ThreadLocal对象:
local = threading.local()
def process_student():# 获取当前线程关联的name:student_name = local.nameprint('线程名:%s 学生姓名:%s' % (threading.current_thread().name,student_name))
def process_thread(name):# 绑定ThreadLocal的name:local.name = nameprocess_student()
t1 = threading.Thread(target=process_thread, args=('张三',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('李四',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()

python系列笔记--耗子(巨细)相关推荐

  1. python独立图形_Python图形界面(自学Python系列笔记-4)(不定期更新)

    lGUI Graphical User Interfaces ltkinter模块 n是Python系统配置的标准GUI库 n采用tkinter模块编写的界面可以在所有主流操作系统上运行 l从应用的角 ...

  2. python学习笔记目录

    人生苦短,我学python学习笔记目录: week1 python入门week2 python基础week3 python进阶week4 python模块week5 python高阶week6 数据结 ...

  3. Cocos2dx游戏开发系列笔记6:怎样让《萝莉快跑》的例子运行在vs和手机上

    2019独角兽企业重金招聘Python工程师标准>>> 感谢听D同学赞助的Demo. 那怎样让它运行在vs中呢: 1 使用cocos2d-x-2.2\tools\project-cr ...

  4. python 学习笔记 12 -- 写一个脚本获取城市天气信息

    近期在玩树莓派,前面写过一篇在树莓派上使用1602液晶显示屏,那么可以显示后最重要的就是显示什么的问题了. 最easy想到的就是显示时间啊,CPU利用率啊.IP地址之类的.那么我认为呢,假设可以显示当 ...

  5. Java系列笔记(1) - Java 类加载与初始化

    2019独角兽企业重金招聘Python工程师标准>>> 目录 类加载器 动态加载 链接 初始化 示例 类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如 ...

  6. Python学习笔记(六)

    1. IO编程 1.1 文件读写 1.2 StringIO和BytesIO 1.3 操作文件和目录 1.4 序列化 2. 进程和线程 2.1 多进程 2.2 多线程 2.3 ThreadLocal 2 ...

  7. python字符串与列表与运算_[Python学习笔记1]Python语言基础 数学运算符 字符串 列表...

    这个系列是我在学习Python语言的过程中记录的笔记,主要是一些知识点汇总,而非学习教程,可供有一定编程基础者参考.文中偏见和不足难以避免,仅供参考,欢迎批评指正. 本系列笔记主要参考文献是官网文档: ...

  8. 带你自学Python系列(五):Python解决列表字符不区分大小写问题

    ↑ 点击上方[计算机视觉联盟]关注我们 今天是小编持续更新关于Python的知识总结以及Python实践项目应用的第5天,带你利用零碎时间自学最受欢迎的编程语言之一Python语言.你和小编一起打卡了 ...

  9. 与孩子一起学编程python_与孩子一起学编程(Python读书笔记3)

    第十一章 嵌套与可变循环 Python 3.X里 print()函数默认是自动换行的,所以本章代码会有很多问题,实际上 print()函数里有一个默认参数 end, 默认情况下: end= " ...

最新文章

  1. 全网最细节的sds讲解,轻松拿下offer
  2. C# Webbrowser 常用方法及多线程调用
  3. 基于纤程(Fiber)实现C++异步编程库(一):原理及示例
  4. JAVA基础系列:ThreadLocal
  5. 实验2.2编写重载函数Max1
  6. bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑(倍增floyd)
  7. SylixOS 缺页异常
  8. 电子商务网站评价研究与应用分析
  9. 32位java jre_jre-7u4-windows-i586.exe|java 1.7.0(Java TM 7)JRE7 32位_最火软件站
  10. 射频电路设计的常见问题及经验总结
  11. 简易智能自动问答机器人
  12. 数据分析师说坐飞机安全么
  13. 万历名士袁宏道的自在人生——独抒性灵,不拘格套
  14. 通过css让图片设置成黑白色
  15. 全局阙值分割中的直方图算法和熵算法
  16. ubuntu使用minicom连接交换机/路由器Console口详细教程
  17. dedecms常见修改,参考大全,二次开发
  18. 爬取取百度和Flickr图像
  19. 微信小程序 - 3D 立体正方形展示控制(水平、垂直、多维拖动)
  20. hyperterminal停止工作_CiscoAironet接入点常见问题.PDF

热门文章

  1. mysql出现core dumped_mysql 段错误 (core dumped)
  2. 计算机应用 网络管理开发,基于XML的iBAC网络管理系统的研究与开发-计算机应用技术专业论文.docx...
  3. html 拉伸幕,html 对 div 进行 拉伸 拖拽
  4. matlab fisher检验,FISHER线性判别MATLAB实现.doc
  5. 最基础硬件学习 | 简单闪烁灯制作
  6. elasticSearch(二)springboot与es的整合
  7. 刻意练习这本书。。。。。。。
  8. 每周分享第 38 期
  9. LINUX IIO子系统分析之四 IIO EVENT介绍
  10. 基于卷积神经网络的猫种类的识别