Python笔记(1)

Numpy安装

cmd中,pip install numpy --proxy http://10.144.1.10:8080
numpy应用:
import numpy as np (np可随意命名)
a=np.arange(10)
print(a)
import math
for i in a:
b=math.sqrt(i)
print(b)
c=np.sqrt(b)
print©
程序基本格式:
1.缩进表示程序块,不能随便缩进。
2.区分大小写
3.行注释#,段注释’’’三个连续单引号
图形化程序设计
Turtle模块:
#导入海龟绘图
import turtle
turtle.showturtle()#显示鼠标
turtle.write(“limin”)#打印字符串
turtle.forward(300)#前进300像素
turtle.color(“red”)#画笔颜色
turtle.left(90)#箭头左转90度
turtle.goto(0,50)#去坐标
turtle.goto(0,0)
turtle.penup()#抬笔,不显示路径
turtle.goto(0,300)
turtle.pendown()#落笔
turtle.circle(100)#画圆直径
turtle.width(10)#画笔粗细
python程序的构成:
模块(.py后缀)-语句(创建对象、变量赋值、调用函数、控制语句)
\行连接符,例如,a=”abcddddddd”和
a=”abcddd
dddd
dd”是一样的。

对象:

Python中,一切皆对象。对象本质是一个内存块,由标识(identity)、类型(type)、value(值)组成。
例:a=3,b=”我爱你”,实际关系为下图,右为对象,左为变量,变量是对对象的引用。
对象放在堆里,变量放在栈里。变量不需要显示声明类型,会根据引用对象类型自动获取。对象只支持该类型支持的操作。
在这里插入图片描述

标识符:(用于变量、函数、类、模块等的名称)

  1. 区分大小写
  2. 第一个字母必须是字母、下划线。后面的可以是字母、数字、 下划线。
  3. 不能使用关键字,不使用双下划线开头。
    在python shell中按F1可以调出帮助窗口,输入help()也可以。
    标识符命名规则
    1. 模块和包名:全小写,多单词间下划线
    2. 函数名:全小写,多单词间下划线
    3. 类名:首字母大写。多单词时,单词首字母大写(驼峰原则)
    4. 常量名:全大写,多单词下划线。
    变量和简单赋值语句:
    变量名=表达式
  4. 变量在使用之前必须初始化(先被赋值)
  5. 删除变量: del a
  6. 垃圾回收机制:对象没有被变量引用,就会被垃圾回收。
    例;a=3
    dle a
    变量a被删除,对象3被垃圾回收。
    链式赋值:(把同一个对象赋值给多个变量)
    X=y=123,相当于x=123 y=123
    系列解包赋值:(个数必须保持一致)
    A,b,c=4,5,6 相当于a=4,b=5,c=6
    系列解包可以简单实现变量互换:a,b=b,a 即可互换
    常量
    Python不支持常量,没有语法规则限制改变一个常量的值,我们只能根据命名规则在逻辑上不去进行修改。
    **

最基本的内置数据类型:


整型:整数。浮点型:小数。布尔型:真假,true和false。字符串
运算:/表示除,//表示整数除法,%取余数,**幂
divmod()函数可以同时得到商和余数。
整数有10进制、二进制(0b)、八进制(0o)、十六进制(0x)。
Python进制转换函数,bin二进制、oct八进制、int十进制、hex十六进制

使用int()实现类型转换:
例:int(9.9)转为 9,自动舍去小数点后。int(“123”)自动转为123
自动转型:整数和浮点数混合运算,自动转为浮点数
Python2整数会溢出,小于2的63次方-1,python3任意大小,不会溢出。
浮点数:用科学计数法表示3.14可以写成314e-2
类型转换:float()可以将其他类型转换为浮点型。
round(value)可以返回四舍五入的值。(不会改变原有值,而是产生新的值)
时间:计算机中把1970.1.1 0点开始作为时间零点,以毫秒为单位。该时刻为Unix时间点。
#coding=utf-8
#导入时间模块
import time
a=time.time()#获得当前时间,到微秒级
print(a)
b=int(time.time())#只取毫秒
c=a/60#分钟数
d=a//60#分钟整数
e=d//60#小时整数
print(b)
print©
print(d)
print(e)
例子:多点坐标,绘出折线,计算距离
#coding=utf-8
import turtle
#定义多点坐标
x1,y1=100,100
x2,y2=100,-100
x3,y3=-100,-100
x4,y4=-100,100
x5,y5=-150,130
#绘制折线
turtle.penup()
turtle.goto(x1,y1)
turtle.pendown()
turtle.goto(x2,y2)
turtle.goto(x3,y3)
turtle.goto(x4,y4)
turtle.goto(x5,y5)
#计算距离
import math
distance=math.sqrt((x1-x5)**2+(y1-y5)**2)
print(distance)
turtle.write(distance)
布尔值:
比较运算符,等于;!=不等于;>大于;<小于;>=大于等于;<=小于等于
逻辑运算符,or逻辑或;and逻辑与;not逻辑非
a=2
b=3
print(a
b)
print(a!=b)
print(a>=b)
print(a or b)
print(a and b)
print(not b)
结果为:
False
True
False
2 逻辑或,a为true,直接返回a,不计算b;a为false,返回b
3 逻辑与,a为ture,返回b,a为false,不计算b,直接返回false
False
同一运算符:
is 判断两个标识符是不是引用同一个对象(比较的是地址)
is not 判断是不是引用引用的不同的对象
is和==区别,==比较的是value
整数缓存问题:
Python对比较小的整数(范围是[-5,256])缓存起来,例如,a=10,b=10,a is b为true,因为10这个对象被缓存起来了,如果是a=1000,b=1000,则为false。
上面是在命令中,如果保存成文件了,缓存整数范围为[-5,任意正整数],即保存成文件后,a=1000,b=1000,a is b返回true
字符串
本质是字符序列,python中字符串是不可变的,如果要修改,可以复制一部分到新的字符串中,另外,python不支持单字符,单字符即为一个字符的字符串。
字符串的编码:unicode可以表示任何书面语言。16位unicode。AcsⅡ码是Unicode子集。
ord()可以把字符转换成对应unicode码,chr()可以把十进制数转换成对应字符。
创建字符串:单引号或者双引号创建。
如果碰到字符串里边包含单引号,则用双引号创建,反之亦然。
创建多行字符串:连续用三个单引号或者多引号定义。
空字符串:python允许空字符串存在,例:a=‘’,len(a)返回0。注意:Unicode字符中,一个汉字长度为1。
转义字符:+特殊字符,实现某些难以用字符表示的效果,比如换行。常见转义字符:\ 续行符,\反斜杠,\n换行符,\’单引号,\”双引号,\b退格,\t横向制表符,\r回车。
字符串拼接:1、+可实现,如果两边都是数字,加法运算,都是字符串,拼接;两边不同,报错。2、直接放一起也可拼接。
字符串复制:*可实现,*3即直接复制三次。
不换行打印:print打印的时候会自动换行,可以加上end=任意字符串,则以end后面的字符串结尾,而不是默认的换行符结尾。
从控制台读取字符串:input()从控制台读取键盘输入的内容。
例:name=input(“请输入名字:”)
Str()数字转型字符串,把其他类型数据转换为字符串。
[ ]提取字符,在字符串后面添加[],可以提取该位置的单个字符。
正向搜索,从左边开始第一个字符偏移量为0,到n-1
反向搜索,从右边开始第一个字符偏移量为-1,到-n
replace()字符替换,字符串不能改变,a.replace(‘c’‘1’),把字符串a中的c替换为1.生成新的字符串,原有的a不改变。
字符串切片:slice

a=‘abcdefghijklmn’
a[1:5] #只有一个冒号表示步长为1
‘bcde’ (不包含f是因为包头不包尾)

a[1:5:2] #第二个冒号表示步长,即隔一个取一个
‘bd’
a[:2] a[2:] a[:]都可以写。
如果[]中为负数,即倒数。例a[-9:-3],包头不包尾。
a[::-1] #步长-1,即从右到左逆序排列。
注意:起始偏移量和终止偏移量不在范围内的时候也不会报错,会直接取到最大值。
字符串分割split()和合并join():

a=‘to be or not to be’
a.split()
[‘to’, ‘be’, ‘or’, ‘not’, ‘to’, ‘be’] #按空格分割

a.split(‘be’)
['to ', ’ or not to ', ‘’] #按be切割
合并:

a=[‘li’,‘min’,‘100’]
‘’.join(a)
‘limin100’

‘#’.join(a) #井号为连接符
‘li#min#100’
拼接字符串+和jion区别:+操作一次就会生成一个新的对象,join只有一个对象,因为字符串不可以改变,但是列表可以变,所以涉及到性能的时候,要用join。
#coding=utf-8
import time
time01 = time.time() #起始时刻
a = “”
for i in range(1000000):
a += “sxt”
time02 = time.time() #终止时刻
print(u"运算时间:"+str(time02-time01))
list1 = []
time03=time.time()
for i in range(1000000):
list1.append(“sxt”)
a="".join(list1)
time04=time.time()
print(u"运算时间:"+str(time04-time03))
测试结果:运算时间:0.959000110626
运算时间:0.177999973297
所以+拼接字符串非常耗时间。
字符串驻留机制:
对于符合标识符规则的字符串(包含下划线_、字母和数字)会启用字符串驻留机制,即仅保存一分相同且不可改变的字符串。

a=(“nn#”)
b=(“nn#”)
a==b
True

a is b
False

a=(“b_1”)
b=(“b_1”)
a is b
True
成员操作符:in/not in,判断某个子字符串是否在字符串里边。

a=(“ab”)
b=(“abcd”)
a in b
True

c=(“f”)
c in b
False

c not in a
True
字符串常用方法:
查找方法: len()长度;a.startswith(“我”)是否以我开头;a.endwith(“我”)是否以我结尾;a.find(“我”)第一次出现“我”的位置,a.rfind(“我”)最后一次出现“我”的位置;a.count(“我”),我出现的次数;a.isalnum()是否所有字符全是字母或者数字。
去除首尾信息:
strip()可以去除首尾指定信息。
lstrip()去除左边指定信息
rstrip()去除右边指定信息
大小写转换:
capitalize()产生新的字符串,首字母大写
title()产生新的字符串,所有单词首字母大写
upper()产生新的字符串,所有字母转成大写
lower()产生新的字符串,所有字母转成小写
swapcase()产生新的,所有大小写转换
格式排版:
center() ljust() rjust()

a=(“sit”)
a.center(10,"") #一共十个字符,a居中,左右补齐。
sit*’

a.ljust(10,"@") #一共10个字符,a左对齐,右边@补齐。
‘sit@@@@@@@’

a.rjust(5,"&") #一共5个字符,a右对齐,左边&补齐。
‘&&sit’
其他方法:
isalnum() 是否为字母或数字
isalpha() 是否只有字母(包含汉字)
isdigit() 是否只有数字
isspace() 是否为空白符(\t\n)
isupper()是否大写
islower()是否小写字母
字符串格式化:
format()

a = “llmm:{0},dhausdyu:{1}”
a.format(“dsa”,“asd”) #直接对应到0,1中
‘llmm:dsa,dhausdyu:asd’

a = “llmm:{c},dhausdyu:{a}”
b = a.format(c=“dsa”,a=“asd”) #指定参数映射
b
‘llmm:dsa,dhausdyu:asd’
填充与对齐:
:后面加填充的字符,^<>分别为居中左对齐右对齐。

a = “llmm:{c},dhausdyu:{a:!^8}” #变量a居中,总共8字符,!填充。
b = a.format(c=“dsa”,a=“asd”)
b
‘llmm:dsa,dhausdyu:!!asd!!!’
数字格式化:
浮点数通过f,整数通过d进行格式化。

a = “llmm:{c},mmll:{a:.2f}” #.2f表示保留两位小数
b = a.format(c=“dsa”,a=333.11111)
b
‘llmm:dsa,mmll:333.11’
可变字符串:io.StringIO

s = u"helloworld" #python2要加u,表示unicode,python3不用
sio = io.StringIO(s)#sio为可变字符串
sio.getvalue() #获取sio值
u’helloworld’

sio.seek(6) #表示要修改第6个字符,从0开始
6L

sio.write(u’g’)#表示要替换成的字符
1L

sio.getvalue()
u’hellowgrld’

sio.seek(0)
0L

sio.write(u’g’)
1L

sio.getvalue()
u’gellowgrld’
符号运用:

a = 4
2< a < 5 #可以连着比较大小
True

a = 0b11001
b = 0b01000
c = a|b #按位或
c
25

bin© #二进制
‘0b11001’

bin(a&b) #按位与
‘0b1000’

bin(a^b) #按位或非
‘0b10001’

a = 3
a << 1 #左移符,左移一位乘以2
6

a = 8
a>>3 #右移符,右移一位除以2
1
注意,python中不支持自增自减,例如不支持a++,a–。
另外python中,+和*可以运用于字符串、列表和元组。
序列:
数据存储方式,存储一系列内容,内存中,序列是存放多个值的练习内存空间,包括:字符串、列表、元组、字典、集合。
字符串是字符序列,列表是任意对象序列。
a = [10,20,30,40] #列表
四个对象id(地址)存进去,是一个新的对象,即变量a

列表创建:

a =[10,20,a,b,40] #直接创捷
a[0]
10

a = [] #创建空列表,之后append
a.append(10)
a
[10]

a = list() #list创建空列表
a
[]

a = list(“ahsg,dsjidj”) # list转换字符串
a
[‘a’, ‘h’, ‘s’, ‘g’, ‘,’, ‘d’, ‘s’, ‘j’, ‘i’, ‘d’, ‘j’]

a = list(range(10)) #range创建
a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range生成列表应用:range(start,end,step)

list(range(1,20,3))#正序
[1, 4, 7, 10, 13, 16, 19]

list(range(30,10,-5))#倒序
[30, 25, 20, 15]
推导式生成列表:

a =[x*2 for x in range(5)]
a
[0, 2, 4, 6, 8]

a = [x*2 for x in range(100) if x%9==0]
a
[0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]
列表元素增加删除:
一般只在列表尾部增加删除元素,在中间增加删除会涉及元素大量移动,降低效率。
append()方法,推荐使用。

a = []
a.append(80)
a
[80]
+运算符操作,生成新的对象,不推荐。

a = [2,3]
a = a + [50]
a
[2, 3, 50]
extend(),和+效果类似,但是不产生新的对象,推荐使用。

a = [10]
a.extend([20,30])
a
[10, 20, 30]
insert()插入元素。

a = [10,20,30,40]
a.insert(2,60)
a
[10, 20, 60, 30, 40]
del删除

a
[10, 20, 60, 30, 40]

del a[0]
a
[20, 60, 30, 40]
pop()方法

a
[20, 60, 30, 40]

b = a.pop() #弹出最后一个元素,赋值给b
b
40

a
[20, 60, 30]

c = a.pop(1) #弹出第2个元素,赋值给c
c
60

a
[20, 30]
remove(),不删除索引,删除指定元素

a = [20,10,20,30,40]
a.remove(20)#删除a中第一个20
a
[10, 20, 30, 40]
列表元素访问和计数
通过索引直接访问元素
index()获得指定元素在列表中首次出现的索引

a = [20,10,20,30,40]
a.index(20)
0

a.index(20,1)#从第二个元素开始index
2

a.index(20,2,5)#从第三个到第六个元素中索引
2
count()指定元素在列表中出现的次数
len()列表长度,即有多少元素
成员资格判断

a
[20, 10, 20, 30, 40]

20 in a
True

70 in a
False

len(a)
5

a.count(20)
2
切片操作
[起始偏移量,终止偏移量,步长]

a[:] #全量截取
[20, 10, 20, 30, 40]

a[1:4:2] #第二个到第五个,步长2,包头不包尾
[10, 30]

a[:-1]
[20, 10, 20, 30] #除去最后一个

a[1:]
[10, 20, 30, 40] #除去第一个

a[-1:] #只有最后一个
[40]

a[::-1] #倒序
[40, 30, 20, 10, 20]
偏移量可以小于0,大于长度,会默认被当作0和最大长度。
列表的遍历:

for i in a:
print(i)
20
10
20
30
40
列表排序:
修改原列表,不建新的列表a.sort()

a
[20, 10, 20, 30, 40]

a.sort()
a
[10, 20, 20, 30, 40]

a.sort(reverse=True)#倒序排列
a
[40, 30, 20, 20, 10]

import random
random.shuffle(a) #随机排序
a
[30, 20, 10, 20, 40]
新建列表排序sorted()

a
[30, 20, 10, 20, 40]

a = sorted(a)
a
[10, 20, 20, 30, 40]

a = sorted(a,reverse=True)#倒序
a
[40, 30, 20, 20, 10]
reversed()返回迭代器

c = reversed(a)
c
<listreverseiterator object at 0x00000000055D74A8>#c为一个迭代器

list©#生成列表,但是只能用一次,用时间换空间
[10, 20, 20, 30, 40]
最大最小值max,min
求和sum,数字求和,非数字报错

max(a)
40

min(a)
10

sum(a)
120
多维列表
一维列表[10,20,30,40]
二维列表[[],[].[],[]],简单理解即为列表嵌套列表
三维依此类推

a = [
[‘gaoxiaoyi’,18,30000,‘beijing’],
[‘gaoxiaoyi’,18,30000,‘beijing’],
[‘gaoxiaowu’,20,25000,‘shenzhen’]
]

a
[[‘gaoxiaoyi’, 18, 30000, ‘beijing’], [‘gaoxiaoyi’, 18, 30000, ‘beijing’], [‘gaoxiaowu’, 20, 25000, ‘shenzhen’]]

a[0]
[‘gaoxiaoyi’, 18, 30000, ‘beijing’]

a[0][1] #第一行,第二个元素
18
嵌套循环打印二维列表所有数据:
#coding=utf-8
a = [
[“gaoxiaoyi”,19,2000,“北京”],
[“高小二”,18,2500,“上海”],
[‘高小三’,20,3000,“深圳”]
]
for i in range(3):
for j in range(4):
print(a[i][j],end="\t")#不换行
print()#换行

元组tuple

列表为可变元素,元组为不可变元素,因此没有增加元素,修改元素,删除元素等方法。
元组创建
小括号创建

a = (1,)
type(a)
<type ‘tuple’>

a = 1,
type(a)
<type ‘tuple’>
Tuple创建

b = tuple()
b = tuple(a)
b
(1,)

b = tuple(‘abc’)
b
(‘a’, ‘b’, ‘c’)

b = tuple(range(3))
b
(0, 1, 2)
元组的元素访问和计数

a = tuple(‘dahdnufdhasu’)
a[3]
‘d’

a[1:4]
(‘a’, ‘h’, ‘d’)

a[::-1]
(‘u’, ‘s’, ‘a’, ‘h’, ‘d’, ‘f’, ‘u’, ‘n’, ‘d’, ‘h’, ‘a’, ‘d’)
排序

b = (34,3,341,2,24,8)
sorted(b) #排序,注意会生成列表而不是元组
[2, 3, 8, 24, 34, 341]

sum(b)
412

max(b)
341

min(b)
2

a = (‘a’,‘df’)
a+b
(‘a’, ‘df’, 34, 3, 341, 2, 24, 8)
zip

a = [10,20,30]
b = [20,30,40]
c =[30,40,50]
d = zip(a,b,c) #将元组压缩到列表中
list(d)
[(10, 20, 30), (20, 30, 40), (30, 40, 50)]
生成器推导式创建元组

s =(x*2 for x in range(5))
s
<generator object at 0x0000000003C9F8B8> #生成器

tuple(s)
(0, 2, 4, 6, 8)
s =(x*2 for x in range(5))

s.next()#指针挨个输出s中的数字
元组总结:
核心特点是:不可变序列
元组的访问和处理速度比列表快
与整数和字符串一样,元组可以作为字典的键,列表不可以作为字典的键。
字典:
键值对的无序可变序列。
a = {‘name’:’gaoqi’,’age’:18,’job’:’programmer’}
键是任意的不可变的数据,整数、浮点数、字符串、元组。
并且键不可以重复。

字典的创建:

{}、dict()

a = {‘name’:‘lm’,‘age’:18,“job”:‘prog’} #花括号创建
a
{‘job’: ‘prog’, ‘age’: 18, ‘name’: ‘lm’}

b = dict(name=‘lm’,age=18) #dict创建
b
{‘age’: 18, ‘name’: ‘lm’}

b = dict[(‘name’,‘lm’),(‘age’,18)]#dict里面加入元组创建

k = [‘name’,‘sge’]#zip创建
v = [‘lm’,18]
d = dict(zip(k,v))
d
{‘sge’: 18, ‘name’: ‘lm’}

a = dict.fromkeys[‘name’,‘age’] #fromkeys创建空字典
字典元素的访问:

  1. 通过键获得值,若键不存在,抛出异常。

b
{‘age’: 18, ‘name’: ‘lm’}

b[‘name’]
‘lm’

  1. get()方法获得值,推荐。优点是指定键不存在的时候不会异常。

b
{‘age’: 18, ‘name’: ‘lm’}

b.get(‘name’) #get存在的键直接返回值
‘lm’

b.get(‘job’,‘no’)#get不存在键,指定返回内容
‘no’

b.get(‘job’)
print(b.get(‘job’)) #get不存在的键,返回none
None
3.其他用法

b.items()#列出所有键值对
[(‘age’, 18), (‘name’, ‘lm’)]

b.keys()#列出keys
[‘age’, ‘name’]

b.values()#列出values
[18, ‘lm’]

len(b)#输出键值对个数
2

‘name’ in b#判断键值是否在字典中
True

‘job’ in b
False
字典元素添加、修改、删除

b[‘job’] = ‘prom’ #添加,如果keys重复,直接覆盖
b
{‘job’: ‘prom’, ‘age’: 18, ‘name’: ‘lm’}
Update将新字典所有键值对添加进去,keys重复直接覆盖。

a = {‘xing’:‘lm’,‘ming’:‘lmj’}
b.update(a)
b
{‘job’: ‘prom’, ‘age’: 18, ‘xing’: ‘lm’, ‘name’: ‘lm’, ‘ming’: ‘lmj’}

删除,del删除,clear清空,pop删除key并且把value返回

c = b.pop(‘name’) #name对应的值返回给c
c
‘lm’

b
{‘job’: ‘prom’, ‘age’: 18, ‘xing’: ‘lm’, ‘ming’: ‘lmj’}

del(b[‘age’]) #删除age键值对
b
{‘job’: ‘prom’, ‘xing’: ‘lm’, ‘ming’: ‘lmj’}

b.clear()#清空b
b
{}
popitem(),随机删除和返回键值对

b = {‘job’: ‘prom’, ‘age’: 18, ‘xing’: ‘lm’, ‘ming’: ‘lmj’}
b.popitem()
(‘job’, ‘prom’) #随机弹出

b
{‘xing’: ‘lm’, ‘age’: 18, ‘ming’: ‘lmj’}
序列解包,方便的对多个变量赋值。

b = {‘job’: ‘prom’, ‘age’: 18, ‘xing’: ‘lm’, ‘ming’: ‘lmj’}
w,x,y,z = b #key值赋值
w
‘job’

a,s,d,f = b.values() #value赋值
a
‘prom’

g,h,j,k = b.items() #键值对赋值
g
(‘job’, ‘prom’)

字典核心底层原理:
列表通过索引找元素,字典通过键找元素。
字典称为散列表,稀疏数组,每个单元叫做一个bucket,包含键和值。
由于bucket大小一致,可以通过偏移量读取。
键值对放入底层
计算键值的哈希值(散列值),通过hash(),假设键值对数量为8,则从右边取三位二进制数,转换为十进制数,假设为5,若5为空,则该键索引为5,若5不空,则取右边四五六位二进制数转换为十进制,看是否为空。
扩容:bucket容量接近2/3的时候扩容,如从8扩为16。
根据键查找键值对的底层过程
先用哈希算法计算键值散列码,和存储流程算法一致,依次取散列值不同位置的数字。
总结
键必须可散列
数字、字符串、元组都是可散列的
自定义对象需要支持三点:支持哈希函数,支持通过__eq__()检测方法相等性,若a==ba为真,hash(a)==hash(b)为真。
往字典添加新建可能会导致扩容,导致散列表键的次序变化,所以不要边遍历遍添加。

集合

无需可变,且不能重复。集合底层是字典的键对象。
集合创建和删除

a = {220,23,‘shue’}#创建新集合
a
set([‘shue’, 220, 23])

a.add(10)#集合添加元素
a
set([10, ‘shue’, 220, 23])

b = set(a) #列表通过set转化为集合
b = {‘sa’,‘e’,‘ew’,21}
b.remove(‘sa’)#删除集合元素
b
set([‘ew’, ‘e’, 21])

b.clear()#清空集合
b
set([])
集合运算

a = {10,20,‘asd’,‘qwe’}
b = {10,20,‘fgh’,‘rere’}
a|b#病机
set([‘rere’, ‘qwe’, 20, ‘asd’, ‘fgh’, 10])

a&b#交集
set([10, 20])

a-b#差集
set([‘qwe’, ‘asd’])

a.union(b)#并集
set([‘rere’, ‘qwe’, 20, ‘asd’, ‘fgh’, 10])

a.intersection(b)#交集
set([10, 20])

a.difference(b)#差集
set([‘qwe’, ‘asd’])
控制语句
选择结构:如果,两要素,条件表达式和语句块。单分支结构,双分支结构,多分支结构。
单分支:
if条件表达式:
语句/语句块
条件表达式可以是逻辑表达式、关系表达式、算数表达式。
语句块可以多条语句、单条语句,缩进一致。
#测试if语句
a = 5
if a < 10:
print(a)
a = input(“请输入一个数字:”)
if a < 10:
print(a)
条件表达式为false情况:
False、0、0.0、空值none,空序列、空range、空迭代。其他为ture
条件表达式中,不能有赋值操作符“=”
双分支结构:
a = input(“请输入一个数字:”)
if 3 < a < 10:
print(a)
else:
print(“不符合”)
三元条件运算符:
print(a if (3 < a < 10) else “不符合”)#和上述程序效果一样
多分支选择结构:
score = input(“请输入成绩:”)
grade = ‘’
if score >= 90:
grade = ‘优秀’
elif score >= 80:
grade = ‘良好’
elif score >= 60:
grade = ‘及格’
else:
grade = ‘不及格’
print(grade)
print(‘成绩是{0},等级是{1}’.format(score,grade))
选择结构的嵌套:(控制好不同级别的缩进量)
score = int(input(“请输入成绩:”))
grade = ‘’
if 0 < score < 100:
if score >= 90:
grade = ‘A’
elif score >= 80:
grade = ‘B’
elif score >= 70:
grade = ‘C’
elif score >= 60:
grade = ‘D’
else:
grade = ‘E’
print(grade)
print(‘成绩是{0},等级是{1}’.format(score,grade))
else:
score = int(input(“请重新输入分数:”))
score = int(input(“请输入成绩:”))#和上述代码实现功能一致,但是代码行数大大减少
grade = ‘ABCDE’
num = 0
if 0 > score or 100 < score:
score = int(input(“请重新输入分数:”))
else:
num = score//10
if num < 6:
num = 5
print(grade[9-num])

循环结构:

While循环语法格式
While 条件表达式:
循环体语句
#测试while循环
num = 0
while num < 10:
print(num)
num += 1
#计算1-100累加和
num = 0
sum_all = 0
while num <= 100:
sum_all = num + sum_all
num += 1
print(“1-100所有数的累加和:”,sum_all)
for循环和可迭代对象遍历
for 变量 in 可迭代对象:
循环体语句
#遍历一个元组或列表
for i in (20,30,40,‘x’):
print(i3)
for i in ‘asdfg’:
print(i
3) ’
d = {‘name’:‘lm’,‘age’:18,‘job’:‘test’}
for i in d:
print(i)#打印key值
for i in d.keys():
print(i)#打印key值
for i in d.values():
print(i)#打印value值
for i in d.items():
print(i)#打印键值对
range对象,range(起始,结束,步长)包头不包尾
#1-100奇数累加和
sum_all = 0
for x in range(1,101,2):
sum_all = sum_all + x
print(‘1-100奇数和为:’,sum_all)
#1-100偶数累加和
sum_all = 0
for x in range(0,101,2):
sum_all = sum_all + x
print(‘1-100奇数和为:’,sum_all)
循环嵌套:
#打印九九乘法表
for m in range(1,10):
for n in range(1,10):
if n <= m:#这个地方也可以写成for n in range(1,m+1):
print(’{0}{1}={2}\t’.format(m,n,(mn)))
print(’\t’)
#列表字典存储表格信息
tb = []
r1 = {‘name’:‘gxy’,‘age’:18,‘salary’:30000,‘city’:‘bj’}
r2 = {‘name’:‘gxe’,‘age’:19,‘salary’:20000,‘city’:‘sh’}
r3 = {‘name’:‘gxw’,‘age’:12,‘salary’:10000,‘city’:‘sz’}
tb = [r1,r2,r3]
for i in tb:
if i.get(‘salary’)>15000:#打印薪水大于15000的数据
print(i)
break语句:
表示中断,表示结束整个循环,当有嵌套循环时,跳出最近一层。
Continue语句:
结束本次循环,执行下一次。
#测试break
while True:
a = input(‘请输入一个字符(输入q时退出):’)
if a==“q” or a==“Q”:
print(“exit”)
break
else:
print(a)
#输入薪资,小于0重新输入,打印员工数量薪资明细、平均薪水
empNum = 0
empSum = 0
salarys = []
while True:
s = input(“请输入员工薪水(输入q时退出):”)
if s==“q” or s==“Q”:
print(“exit”)
break
if s<0:
continue
empNum+=1
salarys.append(s)
empSum=empSum+s
print(“员工数为:{0}”.format(empNum))
print(“薪资明细:{0}”.format(salarys))#可以写为print(“薪资明细:”,salarys)
print(“平均薪资:{0}”.format(empSum/empNum))
循环中的else
While 条件表达式:
循环体
Else:
语句块
没有被break就执行else,被中断则不执行else
#输入薪资(4人),小于0重新输入,打印员工数量薪资明细、平均薪水
empNum = 0
empSum = 0
salarys = []
while empNum<4:
s = input(“请输入员工薪水(输入q时退出):”)
if s==“Q” or s==“q”:
print(“exit”)
break
if s<0:
continue
empNum+=1
salarys.append(s)
empSum=empSum+s
else:
print(“已输入所有员工薪水”)
print(“薪资明细:{0}”.format(salarys))
print(“平均薪资:{0}”.format(empSum/empNum))
循环代码优化:
避免不必要的低效计算

  1. 尽量减少循环内部不必要的计算,尽量放在循环外
  2. 嵌套循环中,尽量减少内层循环的计算,尽量外提
  3. 尽量使用局部变量,因为查询较快
    #循环代码优化测试,第二个优于第一个
    import time
    start = time.time()
    for i in range(1000):
    result = []
    for j in range(10000):
    result.append(i100+j10)
    end = time.time()
    print(“耗时:{0}”.format(end-start))
    start1 = time.time()
    for i in range(10000):
    result = []
    for j in range(1000):
    result.append(i100+j10)
    end1 = time.time()
    print(“耗时:{0}”.format(end1-start1))
    其他优化手段
    1.连接多个字符串,使用join而不使用+
    2.列表操作元插入和删除,尽量在尾部不是中间
    使用zip()并行迭代
    #测试zip()并行迭代
    names = (‘gq’,‘ge’,‘gs’)
    ages = (18,19,20)
    jobs = (‘ls’,‘cxy’,‘ys’)
    for name,age,job in zip(names,ages,jobs):
    print("{0}-{1}-{2}".format(name,age,job))
    相当于for i in range(3):
    print("{0}-{1}-{2}".format(names[i],ages[i],jobs[i]))
    结果:
    gq-18-ls
    ge-19-cxy
    gs-20-ys

#画同心圆
import turtle
t = turtle
t.width(2)#画笔粗细
t.speed(10)#画笔速度
My_colors = (‘red’,‘yellow’,‘green’,‘black’,‘pink’)
for i in range(14):#0,1,2,3,4
t.penup()
t.goto(0,-i10)#0,-100,-200,-300,-400
t.pendown()
t.color(My_colors[i%(len(My_colors))])
t.circle(15+10
i)#100,200,300,400,500
#画1818棋盘
import turtle
t = turtle
for i in range(18):
t.penup()
t.goto(-300+25
i,200)#-300,-280,-260……
t.pendown()
t.goto(-300+25i,-225)
for j in range(18):
t.penup()
t.goto(-300,200-25
j)#-300,-280,-260……
t.pendown()
t.goto(125,200-25*j)

函数用法和底层分析:

函数是什么?可重用的程序代码块。代表一个任务或者一个功能。
函数的分类:

  1. 内置函数,例如str()、list()、len()
  2. 标准库,import导入库
  3. 第三方库函数
  4. 用户自定义函数
    函数的定义和标记
    定义函数语法
    def 函数名([参数列表])
    “文档字符串”
    函数体/若干语句
    #测试函数的定义和调用
    def test01():
    print("*"*10)
    print("@"*10)

test01()
test01()
for i in range(10):
test01()
要点:

  1. def 后面一个空格和函数名称;
    (1) python执行函数的时候,会创建一个对象,
  2. 参数列表
    (1) 圆括号内时形式参数列表,多个参数逗号隔开
    (2) 形参不用声明类型,也不需要指定函数返回值类型
    (3) 无参数也要保留空的圆括号
    (4) 实参列表必须和形参一一对应
  3. return返回值
    (1) 如果函数中包含return语句,则结束函数执行并返回值
    (2) 若不包含,则返回none值
  4. 调用函数前,必须定义函数
    (1) 内置函数对象自动创建
    (2) 标准库和第三方库函数,通过import导入模块时,会执行模块中的def语句。
    形参和实参
    形参:定义函数时使用
    实参:调用函数时使用
    #测试形参、实参的基本用法
    def printMax(a,b):
    if a > b:
    print(a,“较大值”)
    else:
    print(b,“较大值”)
    printMax(10,20)
    文档字符串(函数的注释)
    函数的命名一般要见名知义,如果需要注释,则用三个单引号。
    def printMax(a,b):
    ‘’‘用于比较两个数大小’’’#文档字符串
    if a > b:
    print(a,“较大值”)
    else:
    print(b,“较大值”)
    printMax(10,20)
    help(printMax.doc)#可以查看文档字符串
    返回值
    调用函数以后返回的内容,不是必须的,可以不定义。Return作用,返回值、结束函数运行。
    #测试返回值的基本用法
    def add(a,b):
    print(‘计算两个数的和:{0},{1},{2}’.format(a,b,(a+b)))
    return a+b
    def test02():
    print(‘lm’)
    print(‘js’)
    return
    print(‘HD’)
    def test03(x,y,z):
    return[x10,y10,z*10]
    c = add(30,40)
    print(add(30,40)*10)
    print©
    test02()#HD不会被打印
    d = test02()
    print(d) #打印结果为None
    print(test03(1,2,3))#打印结果为[10,20,30]
    函数也是对象,内存底层分析
    #测试函数也是对象
    def test01():
    print(‘jsjs’)
    test01()
    c = test01
    c()
    print(id(test01))
    print(id©)
    print(type©)
    结果:jsjs
    jsjs
    53455560
    53455560
    <type ‘function’>

变量的作用域

(全局变量和局部变量)
全局变量:作用域从开始到模块结束
局部变量:函数体中声明的变量:

  1. 局部变量更快优先使用
  2. 要加global改变全局变量
    #测试全局变量、局部变量
    a = 3 #全局变量
    def test01():
    b = 4 #局部变量
    print(b*10)
    global a #声明这是全局变量a
    a = 300
    print(a) #输出局部变量a300
    print(locals())#输出局部变量
    print(globals())#输出全局变量
    test01()
    print(a)
    #局部变量和全局变量效率测试
    import math
    import time
    def test01():
    start1 = time.time()
    for i in range(10000000):
    math.sqrt(30)#通过全局调用math
    end1 = time.time()
    print(“耗时{0}”.format((end1-start1)))
    def test02():
    b = math.sqrt
    start2 = time.time()
    for i in range(10000000):
    b(30)
    end2 = time.time()
    print(“耗时{0}”.format((end2-start2)))
    test01()
    test02()
    test02时间优于test010.8s

参数的传递

本质是从实参的赋值操作,“引用的赋值”,python中都是引用传递,不是值传递。
“可变对象”:字典、列表、集合、自定义对象
传递可变对象时,进行写操作。
#参数的传递,可变对象
a = [10,20]
print(id(a))
print(a)
def test01(m):
print(id(m))
m.append(30)
print(id(m))
test01(a)
print(id(a))
print(a)
结果:57388936
[10, 20]
57388936
57388936
57388936
[10, 20, 30]说明操作的为同一个对象
#参数传递,不可变对象(数字、字符串、元组、布尔值)
a = 10
print(id(a))
print(a)
def test01(m):
print(id(m)) m和a为同一对象
m+=20
print(id(m)) #m对象改变
test01(a)
print(id(a))#a对象不变,值也不变
print(a)
结果:
44130656
10
44130656
44130176
44130656
10

浅拷贝和深拷贝

copy()浅拷贝,deepcopy()深拷贝
浅拷贝不拷贝对象内容,只拷贝对象引用;深拷贝拷贝内容
#测试浅拷贝
import copy
a = [10,20,30,[5,6]]
b = copy.copy(a)
print(“a:{0}”.format(a))
print(“b:{0}”.format(b))
b.append(30)
b[3].append(7)
print(“qcopy”)
print(“a:{0}”.format(a))
print(“b:{0}”.format(b))
结果为:
a:[10, 20, 30, [5, 6]]
b:[10, 20, 30, [5, 6]]
qcopy
a:[10, 20, 30, [5, 6, 7]]#因为b只拷贝了a的引用,没有拷贝a的内容,所以他们指向同一个内容
b:[10, 20, 30, [5, 6, 7], 30]
#测试深拷贝
def testdeepcopy():
a = [10,20,30,[5,6]]
b = copy.deepcopy(a)
b.append(30)
b[3].append(7)
print(“dcopy”)
print(“a:{0}”.format(a))
print(“b:{0}”.format(b))
testdeepcopy()
结果:
a:[10, 20, 30, [5, 6]]
b:[10, 20, 30, [5, 6]]
dcopy
a:[10, 20, 30, [5, 6]]#不改变a
b:[10, 20, 30, [5, 6, 7], 30]
‘‘测试传递不可变对象时,不可变对象里面包含的子对象是可变的,
则方法内修改了这个可变对象,源对象也发生了变化’’’
a = (10,20,[5,6])
print(“a:”,id(a))
def test01(m):
print(“m:”,id(m))
m[2][0] = 888
print(m)
print(“m:”,id(m))
test01(a)
print(a)
结果:===========================
(‘a:’, 60717456L)
(‘m:’, 60717456L)
(10, 20, [888, 6])
(‘m:’, 60717456L)
(10, 20, [888, 6])

参数的几种类型

位置参数,通过位置一一对应
默认值参数,默认值参数必须位于普通参数后面,如果传则改变,不传则为默认值
命名参数
#测试参数的类型:位置参数、默认值参数、命名参数
def test01(a,b,c,d):
ptint("{0}-{1}-{2}-{3}".format(a,b,c,d))

def test02(a,b,c=8,d=10):#默认参数
ptint("{0}-{1}-{2}-{3}".format(a,b,c,d))

test01(4,3,2,1)#位置参数
test01(c=10,a=20,c=2,d=3)#命名参数
test02(1,3)
test02(1,3,2,5)
可变参数(可变数量参数),一个元组,两个字典
强制命名参数,在后面增加新的参数,必须在调用时强制命名参数。
lambda表达式和匿名参数
lambda表达式只允许包含一个 表达式,不能包含复杂语句
lambda arg1,arg2,arg3……
#测试lambda表达式
f = lambda a,b,c:a+b+c
print(f)
print(f(2,3,4))
f = [lambda a:a
3,lambda b:b+2,lambda c:c//2]
print(f0,f1)
eval()函数
#测试eval()函数
s = ‘print(“abcde”)’
eval(s)#输出abcde

a = 10
b = 20
dict1 = dict(a=100,b=200)
c = eval(‘a+b’)
print©#输出3
d = eval(‘a+b’,dict1)
print(d)#输出300

递归函数

自己调用自己的函数,在函数体内,自己调用自己
#测试递归函数的基本原理
def test01(n):
print(‘test01:’,n)
if n == 0:
print(‘over’)
else:
test01(n-1)
print(‘test***’,n)
test01(5)
结果:(‘test01:’, 5)
(‘test01:’, 4)
(‘test01:’, 3)
(‘test01:’, 2)
(‘test01:’, 1)
(‘test01:’, 0)
over
(‘test***’, 0)#依次结束之前打开的栈帧
(‘test***’, 1)
(‘test***’, 2)
(‘test***’, 3)
(‘test***’, 4)
(‘test***’, 5)
#递归函数计算阶乘
def factorial(n):

if n == 1:
    return 1
else:
    return n * factorial(n-1)

result = factorial(5)
print(result)

嵌套函数(内部函数)

#嵌套函数定义
def f1():
print(‘f1 running’)

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

f1()
外部无法调用内部函数,所以可以作为代码的隐藏
#嵌套函数定义
def f1():
print(‘f1 running’)

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

f1()
#函数嵌套测试
def printName(isChinese,name,familyName):
def inner_print(a,b):
print(’{0} {1}’.format(a,b))
if isChinese:
inner_print(familyName,name)
else:
inner_print(name,familyName)
printName(True,“li”,“min”)
printName(False,“li”,“min”)
nonlocal
声明外层的局部变量。
#测试nonlocal和global
a = 100
def outer():
b = 10
def inner():
global a #声明全局变量
nonlocal b #声明外部函数的局部变量
print(“innner:”,b)
b = 20
a = 1000
inner()
outer()
print(“a:”,a)
LEGB规则:local-enlosed-global-built in
函数或类方法内部-嵌套函数(闭包)-模块中的全局变量—python为自己保留的特殊名称
#测试LEGB
str = ‘global’
def outer():
str = “outer”
def inner():
str = “inner”
print(str)
inner()
outer()

面向对象和面向过程

面向对象:设计者思维,处理复杂问题,拆分为名词
面向过程:执行者思维,简单问题,拆分为动词
面向对象之后仍需要面向过程来处理细节问题。
对象的进化
简单数据——数组(相同数据类型放一起)——结构体(不同数据类型放一起)——对象(不同类型数据、相关方法(函数)放一起)
类的定义:
类的结构:方法、属性。
对象的结构:方法、属性。
#coding=utf-8
#类
class Student:#类名一般首字母大写,多个单词采用驼峰规则

def __init__(self,name,score):#双下划线表示构造方法,self必须位于第一个参数
    self.name = name
    self.score = score
def say_score(self):#self必须位于第一个参数
    print("{0}的分数是:{1}".format(self.name,self.score))

s1 = Student(“高企”,18)#类名加括号,代表调用类里的构造方法
s1.say_score()
构造函数__init__():名字是固定的
init:初始化对象
new:创建对象,一般省略
实例属性:属于实例对象
class Student:#类名一般首字母大写,多个单词采用驼峰规则
def init(self,name,score):#双下划线表示构造方法,self必须位于第一个参数
self.name = name
self.score = score
def say_score(self):#self必须位于第一个参数
print("{0}的分数是:{1}".format(self.name,self.score))
s1 = Student(“高企”,18)#类名加括号,代表调用类里的构造方法
s1.say_score()
s1.age = 21#s1对象中添加新的属性
s1.salary = 3000#s1对象中添加新的属性
print(s1.salary)

s2 = Student(“高希希”,6)#新建s2不会有s1添加的属性,因为模(class)没有变化
实例方法:属于实例对象
定义格式和函数一样,但是实例方法需要self参数,调用方法时,不需要给self传参。
s2 = Student(“高希希”,6)
s2.say_score()#实际解释器翻译为Student.say_score(s2)
Student.say_score(s2)
class Man:
pass #空,可以理解为一个占位符

print(dir(s2))#dir可以获取对象的所有方法、属性
print(dir(s1))
print(s2.dict)#dict获取对象的属性字典(定义的直观上的属性)
print(s1.dict)
print(isinstance(s2,Student))#判断对象是否为指定类型,即s2是否为Student类中的对象
print(isinstance(s2,Man))
类对象
class Student:
pass
print(type(Student))
print(id(Student))
Stu2 = Student #类也是对象,id赋给stu2
s1 = Stu2()
print(s1)

类属性

从属于类,可以被所有实例对象共享。

#测试类属性
class Student:
company = ‘sxt’#类属性
count = 0 #类属性

def __init__(self,name,score):#双下划线表示构造方法,self必须位于第一个参数
    self.name = name #实例属性
    self.score = score #实例属性
    Student.count = Student.count + 1
def say_score(self):
    print('我的公司是:{0}'.format(Student.company))
    print("{0}的分数是:{1}".format(self.name,self.score))

s1 = Student(“张三”,80) #s1是实例对象,自动调用__init__方法
s1.say_score()
s2 = Student(“李四”,70)
s3 = Student(“王五”,90)
print(“一共创建了{0}个对象”.format(Student.count))
类方法
从属于类对象的方法,通过装饰器@classmethod定义
类方法用来操作类属性,实例方法用来操作实例属性
静态方法
用来在类里定义通过装饰器@staticmethod来定义
与类对象无关,可以通过类名访问,不用来操作类属性
#测试类方法/静态方法
class Student:
company = ‘sxt’#类属性
def init(self,name,age):
self.name = name
self.age = age

@classmethod
def printCompany(cls): #类方法,第一个参数必须是cls
    print(cls.company)
    print(self.name)#会报错,类方法和静态方法中不能调用实例变量和实例方法

Student.printCompany()

class Student2:
company = ‘sxt’
@staticmethod
def add(a,b):#静态方法
print("{0}+{1}={2}".format(a,b,(a+b)))
return a+b
Student2.add(20,30)
__del__方法(析构函数)和垃圾回收机制
#析构方法测试
class Person:
def del(self):
print(“销毁对象{0}”.format(self))
p1 = Person()
p2 = Person()
del p2
print(“over”)
call__方法和可调用对象
#测试可调用方法__call
()
class SalaryAccount:
‘’‘工资计算类’’’
def call(self,salary):
print(“算工资了…”)
yearSalary = salary*12
daySalary = salary//21.75
hourSalary = daySalary//8

    return dict(yearSalary=yearSalary,mothSalary=salary,daySalary=daySalary,hourSalary=hourSalary)

s = SalaryAccount()
print(s(16000))#call()让对象可以直接像函数一样使用
方法没有重载/方法的动态性
因为python中方法的参数没有类型(调用时确定参数的类型),而且参数数量也不确定,所以不支持重名方法,如果定义了多个重名参数,只有最后一个方法有效。
方法的动态性:python是动态语言,可以动态修改结构,动态为类添加新方法,修改类帆方法。
#测试方法的动态性
class Person:
def work(self):
print(“努力上班!”)
def play_game(s):
print(’{0}在玩游戏’.format(s))
def work2(s):
print(‘好好工作!’)
Person.paly = play_game #新增方法
p = Person()
p.work()
p.paly()#等价于Person.paly§
Person.work = work2 #修改方法
p.work()

私有属性和私有方法(实现封装)

封装:将复杂的细节封装在内部,外部的人不能访问
python没有严格的访问控制限制,通常通过约定俗成。
1. 约定__开头的属性是私有的,其他的公共的
2. 类内部可以访问私有属性
3. 类外部不能直接访问私有属性
4. 类外部可以通过“_类名__私有属性名”访问私有属性
方法本质也是属性
#测试私有属性
#测试私有属性
class Employee:
__company = “程序员”#私有类属性
def init(self,name,age):
self.name = name
self.__age = age#__开头为私有实例属性
def __work(self):#__开头为私有方法
print(“好好工作!”)
print("{0}的年龄是:{1}".format(self.name,self.__age))#类内部调用私有属性可以直接调用
print(Employee.__company)#类内部直接调用私有类属性

e = Employee(“张三”,18)
print(e.name)
print(e._Employee__age)#访问私有属性
print(dir(e))#查看e中的属性发现属性名为_Employee__age
e._Employee__work()#调用私有方法
print(“company是{0}”.format(e._Employee__company))#类外部调用私有类属性
@property装饰器
@property可以将一个方法的调用方式变为“属性调用”。
一般用来给属性增加get、set方法
#测试@property的用法
class Employee:
@property
def salary1(self):
print(“salary run……”)
return 10000
emp1 = Employee()
print(emp1.salary1)#可以当作属性调用
#emp1.salary = 20000 不可用,不能设置属性
#测试@property的最简化用法
class Employee(object):
def init(self,name,salary):
self.__name = name#属性私有
self.__salary = salary
‘’’
def get_salary(self):
return self.__salary
def set_salary(self,salary):#约束用户输入,防止出错
if 1000<salary<50000:
self.__salary = salary
else:
print(“error,1000-50000”)
‘’’
@property #用@property来实现上述功能
def salary(self):
return self.__salary
@salary.setter #@salart.setter针对salary属性设置
def salary(self,salary):
if 1000<salary<50000:
self.__salary = salary
else:
print(“error,1000-50000”)
emp1 = Employee(“张三”,20000)
“”“print(emp1.get_salary())
emp1.set_salary(100)
#emp1.salary = 20000 #实例属性可以修改
print(emp1.get_salary())
“””
emp1.salary = -200
print(emp1.salary)
面向对象三大特征
封装(隐藏):隐藏对象属性和实现细节,只对外提供必要的方法。
继承:子类继承父类中的方法
多态:不同的对象调用同一个方法产生不同的行为
继承:代码复用的重要手段
格式
class 子类类名(父类1,父类2……)
python支持多重继承,如果没有指定父类,则默认为object类,是所有类的父类。逻辑上,子类要调用父类的构造函数。
#测试继承的基本使用
class Person(object):
def init(self,name,age):
self.name = name
self.__age = age #私有属性
def say_age(self):
print(“age”,“age”,“age”)
class Student(Person):
def init(self,name,age,score):
Person.init(self,name,age)#必须显示的调用父类的初始化方法,不然解释器不会去调用
self.score = score
#Student–Person–object类
print(Student.mro())#打印内存层次

s = Student(“张三”,18,60)
s.say_age()
print(s.name)
print(s._Person__age)#父类私有属性继承

类成员继承与重写

继承:子类继承父类中除构造方法中的所有成员
重写:子类可以重新定义父类的方法,可以覆盖原有的
#测试方法的重写
class Person(object):
def init(self,name,age):
self.name = name
self.age = age #私有属性
def say_age(self):
print(“age”,self.age,“age”)
def say_introduce(self):
print(“my name:{0}”.format(self.name))
class Student(Person):
def init(self,name,age,score):
Person.init(self,name,age)#必须显示的调用父类的初始化方法,不然解释器不会去调用
self.score = score
def say_introduce(self):
“”“重写了父类的方法”""
print(“hi,my name is {0}”.format(self.name))
s = Student(“lm”,18,60)
s.say_introduce()
s.say_age()
object根类
查看类的继承层次结构:mro()
所有的类都有object的属性和方法
#测试object和其他属性
class Person(object):
def init(self,name,age):
self.name = name
self.age = age
def say_age(self):
print(“my age is {0}”.format(self.age))
obj = object()
p = Person(“lm”,18)
print(dir(obj))
print(dir§)
object有的属性person都有,增加了dict、module、weaef、age、name、say_age
重写str()
#测试重写object的__str
()
class Person(object):#继承object类
def init(self,name):
self.name = name
def str(self):
return “name is {0}”.format(self.name)
p = Person(“lm”)
print§
没有重写__str
()的时候,输出为<main.Person object at 0x0000000003660DD8>
重写之后,输出为name is lm
多重继承(不推荐使用)
python支持多继承,一个子类可以有多个直接的父类,缺点是破坏类的整体层次,所以不推荐使用
#多重继承
#多重继承
class A(object):
def aa(self):
print(‘aa’)
def bb(self):
print(‘aaa’)
class B(object):
def bb(self):
print(‘bb’)
class C(A,B):
def cc(self):
print(‘cc’)
c = C()
c.aa()#可以继承父类A中的方法
c.bb()#两个父类中有重名方法,按照从左到右顺序调用,即先调用A
c.cc()
super()获取父类定义,注意不是父类的对象
#测试super()
class A(object):
def say(self):
print(“A:”,self)
class B(A):
def say(self):#重写父类方法
#A.say(self) #重写父类方法,但是仍想使用父类中的方法
super().say()#和上面的A.say(self)效果一样,可以使用父类的方法
print(“B:”,self)
B().say()

多态

:同一个方法调用优于对象不同可能会产生不同的行为。

  1. 方法多态,属性没有多态
  2. 两个必要条件:继承、方法重写
    #多态
    class Man(object):
    def eat(self):
    print(“I am hugry”)
    class Chinese(Man):
    def eat(self):
    print(“kauizi”)
    class English(Man):
    def eat(self):
    print(“daocha”)
    class Indian(Man):
    def eat(self):
    print(“hand”)
    def manEat(m):
    if isinstance(m,Man):
    m.eat() #多态,一个方法调用,根据对象不同调用不同的方法
    else:
    print(“error”)
    manEat(Chinese())
    manEat(“Franch”)
    特殊方法和运算符重载
    每个运算符都对应相应的方法,+ add, - __sub__等等
    #测试运算符的重载
    class Person(object):
    def init(self,name):
    self.name = name
    def add(self,other):
    if isinstance(other,Person):
    return ‘{0}–{1}:’.format(self.name,other.name)
    else:
    return “error”
    def mul(self,other):
    if isinstance(other,int):
    return self.name*other
    else:
    return “error”
    p1 = Person(“lm”)
    p2 = Person(“js”)
    p3 = Person(“mj”)
    x = p2 * 3
    y = p1 + p2
    print(x)
    print(y)
    特殊属性
    #测试特殊属性
    class A(object):
    pass
    class B(object):
    pass
    class C(A,B):
    def init(self,name):
    self.name = name
    def cc(self):
    print(‘cc’)
    c = C(“lm”)
    print(dir©)#获得所有属性
    print(c.dict)#对象的属性字典
    print(c.class)#对象所属的类
    print(C.bases)#类的基类
    print(C.mro())#层次结构
    print(A.subclasses)#获得子类列表

对象的浅拷贝和深拷贝

浅拷贝不拷贝子对象,因此会引用同一个子对象;深拷贝递归拷贝对象包含的子对象,源对象和拷贝对象的子对象也不同。
#测试对象的浅拷贝和深拷贝
import copy
class MobilePhone(object):
def init(self,cpu,screen):
self.cpu = cpu
self.screen = screen
class CPU(object):
def caculate(self):
print(“12345”)
print(“cpu:”,self)
class screen(object):
def show(self):
print(“picture”)
print(“screen:”,self)
#测试变量赋值
c1 = CPU()
c2 = c1
print(c1)
print(c2)
#测试浅复制
print(“copy”)
s1 = screen()
m1 = MobilePhone(c1,s1)
m2 = copy.copy(m1)
print(m1,m1.cpu,m1.screen)
print(m2,m2.cpu,m1.screen)
#测试深复制
print(“deepcopy”)
m3 = copy.deepcopy(m1)
print(m1,m1.cpu,m1.screen)
print(m3,m3.cpu,m3.screen)

组合

Is – a用继承,例如狗是动物,has-a用组合,例如手机有cpu,都是代码复用
#测试组合
#使用继承实现代码复用
class A1(object):
def say_a1(self):
print(“a1 a1 a1”)
class B1(A1):
pass
b1 = B1()
b1.say_a1()
#使用组合实现代码复用
class A2(object):
def say_a2(self):
print(“a2 a2 a2”)
class B2(object):
def init(self,a):
self.a = a
b2 = B2(A2())
b2.a.say_a2()
#测试has-a关系,使用组合
class MobilePhone(object):
def init(self,cpu,screen):
self.cpu = cpu
self.screen = screen
class CPU(object):
def caculate(self):
print(“12345”)
print(“cpu:”,self)
class Screen(object):
def show(self):
print(“picture”)
print(“screen:”,self)
m = MobilePhone(CPU(),Screen())
m.cpu.caculate()
m.screen.show()
设计模式-工厂模式实现
#工厂模式
class CarFactory(object):
def create_car(self,brand):
if brand == “奔驰”:
return Benz()
elif brand == “宝马”:
return BWM()
elif brand == “比亚迪”:
return BYD()
else:
return “error”
class Benz(object):
pass
class BMW(object):
pass
class BYD(object):
pass
factory = CarFactory()
c1 = factory.create_car(“奔驰”)
c2 = factory.create_car(“本田”)
print(c1)
print(c2)

设计模式-单例模式实现

确保一个类只有一个实例,并且提供一个访问该实例的全局访问点
#单例模式
class MySingleton(object):
__obj = None #类属性,存储实例
__init_flag = True #为了保证init方法只被调用一次
def new(cls,*args,**kwargs):#需要重写new方法和构造方法
if cls.__obj == None:
cls.__obj = object.new(cls)
return cls.__obj
def init(self,name):
if MySingleton.__init_flag:
print(“init…”)
self.name = name
MySingleton.__init_flag = False
a = MySingleton(“aa”)
b = MySingleton(“bb”)
print(a)
print(b)
#测试工厂模式和单例模式的整合使用
class CarFactory(object):
__obj = None #类属性,存储实例
__init_flag = True #为了保证init方法只被调用一次
def create_car(self,brand):
if brand == “奔驰”:
return Benz()
elif brand == “宝马”:
return BWM()
elif brand == “比亚迪”:
return BYD()
else:
return “error”

def __new__(cls,*args,**kwargs):#需要重写new方法和构造方法
    if cls.__obj == None:
        cls.__obj = object.__new__(cls)
    return cls.__obj
def __init__(self):
    if CarFactory.__init_flag:
        print("init...")
        CarFactory.__init_flag = False

class Benz(object):
pass
class BMW(object):
pass
class BYD(object):
pass
factory = CarFactory()
factory2 = CarFactory()
c1 = factory.create_car(“奔驰”)
c2 = factory.create_car(“比亚迪”)
print(c1)
print(c2)
print(factory)
print(factory2)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值