python语法
变量名规则:
名称第一字符为英文或者下划线
名称第一字符后可以使用英文字母、下划线和数字
名称不能使用关键字或保留字符
名称区别大小写,但此语单词之间使用下划线链接
数据类型:
numbers 数字类型
strings 字符串类型
lists 列表
tuples 元组
dictionaries 字典
sets 集合
type()
用于查看数据类型
type(1)
<class 'int'>
1.整型(Int)
表示整数,在python中表示无限大只要内存足够
2.布尔型(Boolen)
用于判断逻辑
在Python中,False可是是0,对象为None或者是序列中的空字符串,空列表,空元组。
3.浮点型(Float)
范围-1.8308~+1.8308
4.复数型
5.字符串型
*可以复制当前字符串
算数运算符
%取余
**指数
//取整删俞
逻辑运算符
and、or、not
运算优先级
python组合数据类型
flowchart LR
组合数据类型-->序列类型
组合数据类型-->集合类型-->集合set
组合数据类型-->映射类型-->字典dict
序列类型-->列表list
序列类型-->元组tuple
序列类型-->字符串string
1.列表
创建和初始化
a=[12,51,15,4,5]
list=list()
`````````````````
[12, 51, 15, 4, 5]
[]
访问元素
a=[12,51,15,4,5]
for i in range(0,len(a)):
print(a[i])
··························
12
51
15
4
5
a=[12,51,15,4,5]
print(a[0:2])
a=[12,51,15,4,5]
print(a[0:5:2])
````````````````````
[12, 51]
[12, 15, 5]
[开始:结束:步长]
步长为-则倒取
a=[12,51,15,4,5]
print(a[-1:-6:-1])
··················
[5, 4, 15, 51, 12]
list.append(obj) #在列表末尾添加新的对象
list.count(obj) #统计出现次数
list.extend(obj) #在后面加上另一个序列
list.index(seq) #找出某个值的索引位置
list.insert(index,obj) #将对象插入列表
list.pop(obj=list[-1]) #移除一个元素(默认最后一个),返回该元素值
list.remove(obj) #移除第一个匹配项
list.reverse() #元素反向
list.sort([func]) #元素排序
list.clear() #清空列表
list.copy() #复制列表
列表解析
# 使用列表解析创建九九乘法表
b = [['%d*%d=%d' % (j, i, i*j) for j in range(1, i+1)] for i in range(1, 10)]
# 将列表解析结果转换为字符串并打印
for row in b:
print(' '.join(row))
````````````````````````````````````````
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
这段代码创建了一个二维列表b,其中包含了从1到9的每个整数i,对于每个i,它生成一个子列表,子列表中的元素是i与1到i的每个整数j相乘的结果。具体解释如下:
for i in range(1, 10): 这是一个外部循环,i的值从1遍历到9(不包括10)。
'%d%d=%d' % (j, i, ij): 这是一个字符串格式化操作,将j、i和它们的乘积ij插入到模板字符串中,形成如11=1、21=2、22=4等格式的字符串。
最终,b将会是一个9x9的二维列表,其中每个子列表都包含i个字符串,表示i与1到i之间所有整数的乘积。
例如,当i=3时,子列表将是['13=3', '23=6', '3*3=9']。整个b列表将包含这样的子列表,分别对应于i为1到9的情况。
2.元组
b = (1,52,7,4,7)
与列表相似,但是元组元无法修改
创建
tup()
tup1(50,) #只有一个元素时最后要加上,
字符串转换和加入
#将字符串Jack 转换成元组并加入元组b中
a="jack"
b = b + tuple(a)
print(b)
·····················
(1, 52, 7, 4, 7, 'j', 'a', 'c', 'k')
遍历输出
#遍历输出
for i in b:
print(i)
································
1
52
7
4
7
索引值
b = (1,52,7,4,7)
#获取索引值为【1,3】
print(b[1:4:1])
·····························
(52, 7, 4)
找位置
b = (1,52,7,4,7)
#找出元素4在元组b中的索引位置
print(b.index(4))
`````````````````````````
3
计数
#找出元组b中元素7出现的次数
print(b.count(7))
·················
2
#元组转换列表
c = list(b)
print(c)
内置函数
len(tuple)
max(tuple)
min(tuple)
tuple(seq)#列表转换元组
元组的封装与序列解封
3.字符串
创建
var1='hello'
var2="world"
var3=str("hello world")
‘’‘和"""用于多行
字符串的切片访问
text=" School of Information Engineering, Huzhou University "
print(text[2:10:2])
·································
colo
内置函数
text=" School of Information Engineering, Huzhou University "
#请输出text变量对应的值的前10个字符。
print(text[:10])
#移除 text变量对应的值首尾的空格。
text=text.strip()
print(text)
#请输出text变量对应的值的后7个字符。
print(text[-7:])
#请输出text 变量对应的值中"E"所在的索引位置。
print(text.find("E"))
#将 text变量对应的值根据"o"分隔,并输出结果。
print(text.split("o"))
#将 text 变量对应的值中的"o"替换为"a",并输出结果
print(text.replace("o","a"))
#将 text变量对应的值变为全大写,并输出结果
print(text.upper())
#将 text 变量对应的值变为全小写,并输出结果。
print(text.lower())
#判断 text 变量对应的值是否以"school"开头,并输出结果。
print(text.startswith("school"))
#判断text变量对应的值是否以"sity"结尾,并输出结果。
print(text.endswith("sity"))
``````````````````````````````````````````````````````````````
School of
School of Information Engineering, Huzhou University
versity
22
['Sch', '', 'l ', 'f Inf', 'rmati', 'n Engineering, Huzh', 'u University']
Schaal af Infarmatian Engineering, Huzhau University
SCHOOL OF INFORMATION ENGINEERING, HUZHOU UNIVERSITY
school of information engineering, huzhou university
False
True
编写程序,判断用户输入的字符是数字、字母还是其他字符
#编写程序,判断用户输入的字符是数字、字母还是其他字符
print("请输入一个字符:")
ch = str(input())
if ch.isdigit():
print("输入的是数字")
elif ch.isalpha():
print("输入的是字母")
else:
print("输入的是其他字符")
4.字典
允许查找与任意键相关联的信息的集合称为“映射”。
创建和初始化
c={'k1':'v1','k2':'v2','k3':'v3'}
键值为一不可改变,但值可以修改
遍历
for k in c:
print(k,c[k])
······························
k1 v1
k2 v2
k3 v3
修改
#将字典c中键名'k1'对应的键值修改为'1'。
c['k1']='1'
print(c)
#将字典c中的键名'k4'修改为' k5'。
c['k4']='k5'
print(c)
·································
{'k1': '1', 'k2': 'v2', 'k3': 'v3'}
{'k1': '1', 'k2': 'v2', 'k3': 'v3', 'k4': 'k5'}
增加
#在字典c中新增一个键值对k4:v4,输出添加后的字典。
c['k4']='v4'
print(c)
#将字典d={k6':v6’}和字典c合并。
d={'k6':'v6'}
c.update(d)
print(c)
························································
{'k1': 'v1', 'k2': 'v2', 'k3': 'v3', 'k4': 'v4'}
{'k1': 'v1', 'k2': 'v2', 'k3': 'v3', 'k4': 'v4', 'k6': 'v6'}
删除
#删除键名为1'的键值对。
c.pop('k1')
print(c)
#清空字典并删除字典变量c。
c.clear()
print(c)
·······························
{'k2': 'v2', 'k3': 'v3'}
{}
内置函数
5.集合
创建
set1={"banana","apple","orange"}
set2=set()
set3=set([1,2,3])#转换
一个集合不能有相同元素。
frozenset()#创建不可变集合
方法
python控制流程
if
while
for
break
continue
python函数与模块与类和对象
#为汽车建立一个名为 Car 的类,为其设置颜色(Color)和百公里耗油量(CSFE)两个实例变量,并定义初始化方法。同时创建一个让对象实例“自我介绍”的方法:在屏幕上输出对象实例的自我介绍。
class Car:
def __init__(self, color, CSFE):
self.color = color
self.CSFE = CSFE
def introduce(self):
print("This is a car, color is %s, CSFE is %s" % (self.color, self.CSFE))
#使用继承机制。为Car类创建两个子类:赛车(RacingCar)类和公交车(Bus)类。对赛车类应当关注赛车的百公里加速秒数、最高时速等属性;对公交车类应当关注其核载人数等属性。分别为这两个子类新增上述已描述的属性,保留父类定义的属性并初始化所有属性。
class RacingCar(Car):
def __init__(self, color, CSFE, acceleration_time, max_speed):
super().__init__(color, CSFE)
self.acceleration_time = acceleration_time
self.max_speed = max_speed
print("This is a racing car, acceleration time is %s, max speed is %s" % (self.acceleration_time, self.max_speed))
def introduce(self):
print("This is a racing car, color is %s, CSFE is %s, acceleration time is %s, max speed is %s" % (self.color, self.CSFE, self.acceleration_time, self.max_speed))
class Bus(Car):
def __init__(self, color, CSFE, max_passengers):
super().__init__(color, CSFE)
self.max_passengers = max_passengers
def introduce(self):
print("This is a bus, color is %s, CSFE is %s, max passengers is %s" % (self.color, self.CSFE, self.max_passengers))
#进行方法重写。分别将创建的 Racing Car 类和 Bus 类所继承的 Car 类的“自我介绍”方法进行重写:输出当前类的各个属性以及自我介绍。
class RacingCar(Car):
def __init__(self, color, CSFE, acceleration_time, max_speed):
super().__init__(color, CSFE)
self.acceleration_time = acceleration_time
self.max_speed = max_speed
def introduce(self):
print("This is a racing car, color is %s, CSFE is %s, acceleration time is %s, max speed is %s" % (self.color, self.CSFE, self.acceleration_time, self.max_speed))
class Bus(Car):
def __init__(self, color, CSFE, max_passengers):
super().__init__(color, CSFE)
self.max_passengers = max_passengers
def introduce(self):
print("This is a bus, color is %s, CSFE is %s, max passengers is %s" % (self.color, self.CSFE, self.max_passengers))
#应用多态。创建一个类外的函数,为其传入一个类的对象实例参数(需要保证能够传入创建的 Car 类及其子类的对象实例)和一个整型参数,使其调用传入对象实例的“自我介绍”方法,整型参数代表重复调用对象实例方法的次数。
def introduce_car(car, times):
for i in range(times):
car.introduce()
def __main__():
car0=Car("black", 15)
car = RacingCar("red", 10, 2, 100)
introduce_car(car, 3)
bus = Bus("blue", 20, 50)
introduce_car(bus, 3)
car0.introduce()
bus.introduce()
类和对象
面向对象概述
什么叫做面向对象?
所谓的面向对象其实就是把属性和方法封装起来,以供重复调用。
比如人:
人的属性:姓名,年龄,性别
人的方法:唱,跳,rap
之前我们没有学习面向对象的时候会这样定义:
伪代码:
姓名 = “帅帅”
年龄 = 18
性别 = “superman”
def 唱():
print(“唱的真好听”)
def 跳():
print("跳的真好看")
def rap():
print("rap世界第一")
12345678910
这样写有一个弊端,就是只有帅帅,淇淇不服啊。为什么她不出来一下?那么下面我们在实现淇淇的伪代码:
姓名 = “淇淇”
年龄 = 18
性别 = “girl”
def 唱():
print(“唱的真好听”)
def 跳():
print("跳的真好看")
def rap():
print("rap世界第一")
123456789
这个时候淇淇的伪代码就完成了,但是淇淇在某些方面是不如帅帅的,这个时候我们要把函数给重新架构一下,成下面这样:
伪代码:
姓名 = “淇淇”
年龄 = 18
性别 = “girl”
def 唱():
print(“唱的没帅帅真好听”)
def 跳():
print("跳的没帅帅好看")
def rap():
print("rap世界第二,搁帅帅后面排着")
123456789
到此,我们写完了两个人的,那么如果我们要写很多人呢?这个时候是不是可以把他们给抽象出来,变成一张图纸一样,用的时候直接拿过来用就可以?我们尝试着写成以下的伪代码:
伪代码:
人:
属性:
姓名
年龄
性别
方法:
唱
跳
rap
123456789
这个时候我们发现,只要是人,就可以拥有着写属性和方法。那么这个时候我们可以造出很多这样的人,比如薛之谦,王一博,周杰伦,他们有个共同的特征就是拥有人的属性和方法。
那么在python里面我们是怎样解决的呢?且看我把上面的伪代码实现
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def sing(self):
print(f"{self.name}唱的真好听")
def dump(self):
print(f"{self.name}跳的真不错")
def rap(self):
print(f"{self.name}世界第一")
123456789101112
这个时候我们肯定很奇怪,这不就是把之前的属性和方法前面套了一个class嘛,有什么神奇的?
下面我带你见证这一神奇的时刻:
shuaishuai = Person("帅帅",18,"superman")
shuaishuai.sing()
shuaishuai.dump()
shuaishuai.rap()
#结果:
帅帅唱的真好听
帅帅跳的真不错
帅帅世界第一
12345678
到这是不是还是有些不服,这上面的代码完全可以实现,我这写的都多了,是不是?
那么我们在把淇淇也写出来:
qiqi = Person("淇淇",18,"beautifulgirl")
qiqi.sing()
qiqi.dump()
qiqi.rap()
#结果
淇淇唱的真好听
淇淇跳的真不错
淇淇世界第一
12345678
这个时候是不是也没多少感觉,只是减少了一点点代码而已啦,那么接下来就是见证帅帅有多帅的时刻了:
zhoujielun = Person("周杰伦",28,"man")
wangyibo = Person("王一博",21,"man")
xuezhiqian = Person("薛之谦",32,"man")
linjunjie = Person("林俊杰",25,"man")
1234
连续生成四个人,而且他们四个人都可以进行唱,跳,rap
你要用以前的方式写,现在都好几十行了,而我这,短短的四行。
这就是面向对象的魅力
对象
什么叫做对象呢?
这道题就是送分题,你的女朋友或者你的男朋友。这里有个狗粮,帅帅&淇淇。单身狗看我博客是不是特别心酸?
开个玩笑,对象就是实际生活中具体的事物
。比如你的车就是一个对象,你的小狗就是一个对象,我的手机也是一个对象。我手机老破了,太难过。
python中一切皆对象,linux
中一切皆文件
淇淇的进阶课堂:判断下面那个是对象
我的电脑
你的电脑
电脑
鼠标
键盘
手机
我的自行车
Alex的特斯拉
我假装有个特斯拉
类
什么叫做类?
类是封装对象的属性和行为的载体
类是对象的抽象。刚才我们说了对象就是具体的事物。那么比如我的车,你的车都是对象,这个时候他们有个统一的标准,比如四个轮胎,一个方向盘,四个座椅。而这个时候我们说车的时候,就会知道他会有我们所说的那些属性和方法。
我们住的房子,他就是对象,但是设计房子的图纸,他就是类。他可以设计成各种各样的,然后由我们勤劳的劳动人民去实现。比如天津的网红图书馆,天津的失恋博物馆(好像在这说这个有点尴尬,毕竟俺是有对象的人)。
那么我们刚才说的什么馆,抽象出他们的相同点,他们统一有一个专有名词,叫做馆。这个就是类。
总结:类是对象的抽象,对象是类的具体实例。
面向对象程序设计的特点
面向对象的三大特性:封装,继承,多态
封装:
我们使用电视遥控器,只需要知道按上下就可以进行换台操作,而不知道遥控器是具体怎么实现的,这就是封装。所谓封装,就是把具体实现隐藏起来,别人使用的时候只给固定的结构进行调用。
继承:
继承跟我们现实生活中的继承类似,你爸有好几套房,看你长大了,老在外面租房住,感觉不太好,送了你一套。这就是继承,而面向对象的继承比现实生活中强了不知道无数倍。继承来的东西你的父类还是存在。也就是说,你爸有十套房,你继承之后你也会有十套房,而且你爸还不会少。不像我们现实世界,你爸给你之后,你爸就没了这十套房。
多态:
一种事物的不同表现形态。python中是非常喜欢鸭子模型的,就是有个鸟,它会游泳,它会跑,它会叫,它就是鸭子。关于多态请看后面的多态详细描述。
类的定义和使用
类表示具有相同属性和方法的集合,使用类就是创建对象。
定义类
固定结构:
class 类名: #类名一般使用大驼峰命名
类属性
类方法
123
写好了类之后并不能直接使用。就跟房子的图纸一样,你写好并不能进行住,需要盖好才可以。
创建类的实例(创建对象)
class Person:
def __init__(self,name,age,sex): #self:代表当前对象 剩下的三个属性在类创建对象的时候必须实现
#类属性,可以在__init__中添加,也可以在其他方法里面添加
self.name = name
self.age = age
self.sex = sex
#类方法
def sing(self):
print(f"{self.name}唱的真好听")
def dump(self):
print(f"{self.name}跳的真不错")
def rap(self):
print(f"{self.name}世界第一")
shuaishuai = Person("帅帅",18,"superman")
12345678910111213141516
删除对象属性:del 对象名.属性名
不建议删除
__init__
魔术方法
当类中写了这个方法的时候,第一个参数必须是self,代表当前对象,然后第二个参数开始就随意,但是这些参数在创建对象的时候必须一一实现。
创建对象的时候自动调用__init__
方法
命名空间
类空间和对象空间
类也遵从自上而上执行,所以如果类里面有同名的方法,前一个方法会被后一个方法覆盖。
然后对象初始化的时候,会调用类覆盖好的方法
# 创建一个类,能够自动统计当前类创建了多少个对象
class Person():
num = 0
def __init__(self):
Person.num += 1
print(Person.num)
Person()
Person()
Person()
Person()
print(Person.num)
1234567891011
魔术方法
python中前后用两个下划线包起来的叫做魔术方法
python3中的魔术方法有:
常用的魔术方法:
__init__:
1.用来构造初始化函数,用来给对象进行初始化属性,所以不需要返回值
2.创建对象的时候自动调用
3.自定义类如果不定义的话,默认调用父类object的,同理继承也是,子类若无,调用父类的,若有,调用自己的
class Animal:
def __init__(self):
print("init初始化方法,没有调用父类object")
Animal()
#结果:
init初始化方法,没有调用父类object
__new__:
1.用所给类创建一个对象,并且返回这个对象
2.因为是给类创建实例,所以至少传一个参数cls,参数cls代表代表要实例化的类,此参数在实例化时用python解释器自动提供
3.在类实例化时内部创建类实例的函数,并且返回这个实例,所以它是实例时最先被调用的方法,一般不要人为定义该方法
4.因为要创建实例返回实例,所以要有返回值。return父类__new__出来的实例,或者直接是object的__new__出来的实例
__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__
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
创建类的成员并访问
类的成员主要有属性和方法,属性可以随意,方法的第一个参数必须是self
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def sing(self):
print(f"{self.name}唱的真好听")
def dump(self):
print(f"{self.name}跳的真不错")
def rap(self):
print(f"{self.name}世界第一")
shuaishuai = Person("帅帅",18,"superman") #初始化
#访问成员方法
shuaishuai.sing()
shuaishuai.dump()
shuaishuai.rap()
123456789101112131415161718
访问类中的属性和方法只需要对象使用成员运算符点
来进行调用
类属性通过类来访问,对象属性通过对象来访问
访问限制
如果想把某些属性给隐藏起来,不想让外界直接访问,可以在属性名前面加两个下划线。比如帅帅不想直接让别人知道他的年龄或者修改他的年龄:
可以使用单下划线,双下划线,首尾双下划线来限制访问权限
单下划线开头的是protected类型的成员,只允许类本身和子类进行访问,不能使用from xxx import ccc进行导入
双下划线只能由定义了该属性或方法的类调用,而不能由类的对象调用,类的对象如果想调用,必须使用set/get方法
首尾双下划线是系统定义的特殊方法,一般是系统定义的名字
class Person:
def __init__(self, name,sex):
self.name = name
self.__age = None
self.sex = sex
def set(self,age):
self.__age = age
def get(self):
return self.__age
def sing(self):
print(f"{self.name}唱的真好听")
def dump(self):
print(f"{self.name}跳的真不错")
def rap(self):
print(f"{self.name}世界第一")
shuaishuai = Person("帅帅","superman") # 初始化
#这个时候初始化帅帅的年龄就会报错,可以使用set方法来赋值,get方法取值
shuaishuai.set(18)
print(shuaishuai.get())
123456789101112131415161718192021222324252627
属性
创建用于计算的属性
有的时候我们需要创建对象的时候就进行给属性赋值,但是这样的方法往往是不安全的,会直接修改我们类中的属性,这样的话安全性不高。比如你的年龄是18岁,但是这个时候有用户进行恶作剧,直接将其修改为600岁,你是不是乐坏了?但是你感觉现实吗?
python中使用@property
将一个方法转换为属性,从而实现用于计算的属性,将方法转换为属性后,可以直接通过方法名来访问,而不需要加括号。
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
@property
def func(self):
if self.age < 150 and self.age > 0:
print(self.age)
else:
print("想啥呢?")
shuaishuai = Person("帅帅",18)
shuaishuai.func #func这个属性不能对其赋值,因为他本质也是一个函数
1234567891011121314
@property
可以将属性设置为只读属性
为属性添加安全保护机制
为此,python中有了私有属性和私有方法供大家使用。私有属性就是在属性前面加两个下划线,然后给这个私有属性给予set和get方法,这样对象调用的时候就只能通过set方法来进行赋值,get方法来获取值
class Person:
def __init__(self, name,sex):
self.name = name
self.__age = None
self.sex = sex
def set(self,age):
self.__age = age
def get(self):
return self.__age
1234567891011
类与类之间的关系
一个一个的类就跟我们现实世界中的模板一样,只有把他们全部关联起来,才会使我们做事更加高效。比如轮胎跟发动机组合成了车,零食跟零食袋组合成了零食一样。类和类的组合,一般分为以下三种关系:
依赖(关联)
一个动作执行的时候,需要另一个动作来帮忙。比如打开电脑,帅帅去玩电脑或者帅帅去打王者
依赖就是我用你,你需要我。
比如帅帅玩电脑,电脑需要帅帅玩
#依赖
class Person:
def run(self):
print("我没事干")
class Computer:
def play(self,tool):
tool.run()
print("我是电脑,玩我")
class Phone:
def play(self,tool):
tool.run()
print("我有王者荣耀,来玩啊")
shuaishuai = Person()
dnf = Computer()
dnf.play(shuaishuai) #依赖是给一个类的对象的方法给另一个对象
wangzhe = Phone()
wangzhe.play(shuaishuai)
12345678910111213141516171819202122
一个类使用某个类中的某个方法
这种情况下,类与类之间的关系是最轻的,可以随时替换。
依赖就是一个类的对象的方法自己完不成一些功能,需要另一个对象来完成,把他加载到此方法中。就是依赖
组合(聚合)
一个类需要某个类的具体对象去做一些事情,这就是组合。轮胎和发动机组合成了车一样。
组合可以一对一,也可以一对多。
一个类与另一个类没有共同点,但是他们之间有关系,这就是组合
组合就是我需要什么,但是我没有这些东西,我就拿你。
class Car:
def __init__(self,name,power = None):
self.__name = name
self.__power = power
def set_power(self,power):
self.__power = power
def zhuang_Tread(self):
print(f"{self.__name}装好了{self.__power.get_name()}的轮胎")
def saiche_power(self):
print(f"{self.__name}装好了{self.__power.get_name()}的发动机")
class Tread:
def __init__(self,name):
self.__name = name
def set_name(self,name):
self.__name = name
def get_name(self):
return self.__name
class Engine:
def __init__(self,name):
self.__name = name
def set_name(self,name):
self.__name = name
def get_name(self):
return self.__name
tread = Tread("牛逼牌")
engine = Engine("赛车")
car = Car("奔驰",tread)
car.zhuang_Tread()
car.set_power(engine)
car.saiche_power()
#分析:
是不是发现了有很多的重复代码,而且极其麻烦,不如用继承好。刚开始用,还是没有那么的得心应手,我还的努力。
1234567891011121314151617181920212223242526272829303132333435363738394041424344
将一个类的对象封装到另一个类的属性中进行一些操作
淇淇的进阶课堂
老师和学生模型(老师对学生是一对多,学生对老师是一对一)
创建教师类和学生类
教师类有姓名和学生列表两个属性
教师类有添加学生的方法(添加的学生是具体对象)
教师类有显示对应学生姓名和学号的方法
学生类有学号/姓名/年龄属性
创建多个学生,并添加到某位教师的学生列表中
打印该教师的所有学生学号
123456789
继承(实现)
一般我们看到继承
这两个字都有一种一夜暴富的心态。比如我们看的西虹市首富,猛虫过江,都是有了巨额的财富,令继承人过上了幸福的生活。那么在我们的Python中,继承究竟是怎么样的呢?在python中子类会拥有父类的属性和方法,但是不会继承私有属性和私有方法。被继承的类叫父类或基类,继承的类叫做子类或派生类。
继承的基本语法
#固定结构:
#父类
class Person(object): #括号里面写要继承的类
def __init__(self, name,sex):
self.name = name
self.__age = None
self.sex = sex
def set(self,age):
self.__age = age
def get(self):
return self.__age
def sing(self):
print(f"{self.name}唱的真好听")
def dump(self):
print(f"{self.name}跳的真不错")
def rap(self):
print(f"{self.name}世界第一")
#子类
class Boy(Person):
pass
shuaishuai = Boy("帅帅","superman")
shuaishuai.sing()
#结论:
可以看出,子类Boy什么都没有写,只是继承了一下父类Person,他就拥有了父类的属性和方法,但是私有属性没有被继承。
1234567891011121314151617181920212223242526272829303132
淇淇的进阶课堂
老师和学生模型(老师对学生是一对多,学生对老师是一对一)
创建教师类和学生类
教师类有姓名和学生列表两个属性
教师类有添加学生的方法(添加的学生是具体对象)
教师类有显示对应学生姓名和学号的方法
学生类有学号/姓名/年龄属性
创建多个学生,并添加到某位教师的学生列表中
打印该教师的所有学生学号
123456789
组合是指在新类里面创建原有类的对象,重复利用已有类的功能“has-a”关系
而继承允许设计人员根据其它类的实现来定义一个类的实现“is-a”关系
方法重写
方法重写就是子类继承父类的方法,然后把方法体进行重写。
比如父类是房子的图纸,因为每个人对美的定义不一样,你感觉你爸弄得这个图纸不适合你,你又不想重新弄。就把比如卧室进行重新设计一下,床啥的就不换了。这就是方法重写
class Person(object):
def __init__(self, name):
self.name = name
def sing(self):
print(f"{self.name}唱的真好听")
#子类
class Boy(Person):
def sing(self):
print(f"{self.name}最帅")
shuaishuai = Boy("帅帅")
shuaishuai.sing()
#结果:帅帅最帅
这个时候我们可以发现,原来我们不重写sing方法的时候,他调用的是父类的sing方法,当我们在子类中进行重写之后,他显示的就是子类的方法。
由此可以得出查找顺序:对象调用某个属性或者方法的时候,会先在当前类中进行查找,如果找不到,就去他的父类对象今进行查找。
12345678910111213141516
深度优先和广度优先
派生类中调用基类的方法
子类如果有自己的初始化属性,也就是有魔术方法__init__
的时候,子类不会自动执行父类的方法,必须使用super来进行调用,获取父类的初始化属性
使用super关键字调用父类的方法
子类如果编写了自己的构造方法,但没有显式调用父类的构造方法,而父类构造函数初始化了一些属性,就会出现问题
解决方式:调用超类构造方法,或者使用super函数 super(当前类名, self).init()
super在Python3和python2中的区别:
Python3可以使用直接使用 super().xxx 代替 super(Class, self).xxx
super钻石继承
super的内核 mro方法:返回的是一个类的方法解析顺序表(顺序结构)
我们定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,这也是super在父类中查找成员的顺序,它是通过一个C3线性化算法来实现的
我们可以使用下面的方式获得某个类的 MRO 列表
类名.mro() 或者 对象名.__class__.mro()
12345
淇淇的进阶课堂
练习:
有一个动物类,猫狗两个类都继承了动物,动物类拥有动物的属性,定制猫狗类的个性属性
动物都有吃的方法,动物在吃东西之后会打印自己的血量值和智力值,但是猫和狗吃的东西不一样
猫狗在吃了食物之后,猫会增加血量值,狗会增加智力
1234567
多继承和多重继承的区别
多继承是子类不断的继承父类,依次类推,最后的孙子类拥有父类跟子类的方法
#多继承
class Person(object):
def run(self):
print("人会跑")
class Boy(Person):
def like_girl(self):
print("男孩喜欢女孩子")
class Girl(Boy):
def like_boy(self):
print("女孩子也喜欢男孩子")
class Kid(Girl):
def kids(self):
print("孩子是男孩跟女孩的爱情结晶")
kid = Kid()
kid.run()
kid.like_girl()
kid.like_boy()
kid.kids()
#结果
人会跑
男孩喜欢女孩子
女孩子也喜欢男孩子
孩子是男孩跟女孩的爱情结晶
12345678910111213141516171819202122232425262728
可以看出,多继承就是最后的一个类拥有上面的类的属性和方法(除了私有属性和私有方法)
多重继承逻辑不行的人就别看了。
补充内容isinstance()及issubclass()
isinstance()及issubclass()
isinstance() 用于检查实例类型:isinstance(对象,类型)
issubclass() 用于检查类继承:issubclass(子类,父类)
123
super
使用多继承,会涉及到查找顺序(MRO)、钻石继承等问题
钻石继承
单继承时 类名.init()的方式和super().init()方式没啥区别
但是使用 类名.init()的方式在钻石继承时会出现问题
super的内核 mro方法:返回的是一个类的方法解析顺序表(顺序结构)
我们定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,这也是super在父类中查找成员的顺序,它是通过一个C3线性化算法来实现的
我们可以使用下面的方式获得某个类的 MRO 列表
类名.mro() 或者 对象名.class.mro()
封装性
栈:先进后出
栈在内存中保存对象的引用
堆在内存中保存对象
总结:对象在栈中保存,在堆中被引用
队列:先进先出
淇淇的进阶课堂
实现栈和队列
封装的定义
封装就是把一个个的属性和方法隐藏起来,只留下具体的接口供下一个人使用
我们最常见的封装就是遥控器,你不需要知道遥控器是怎么装的,直接拿来开始换台就行。比如动物世界。
私有属性
私有属性就是在属性前面加get/set方法,然后再当前类中进行调用和实现,外界只能使用这个属性的set/get方法来操作他。而且不能被子类继承
私有方法
私有方法跟私有属性一样,在方法前面加两个下划线
破解私有属性和私有方法
_类名__属性
12
破解私有属性
破解私有属性和私有方法:
在名称前加上 _类名,即 _类名__名称(例如a._A__N)
其实加双下划线仅仅是一种变形操作
类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式
多态性
多态
一个变量可以有不同的数据类型
一个事物的不同表现形态,具体表现在比如狗,有柯基,二哈,还有淇淇(淇淇那么可爱,哈哈哈)
python天生支持多态
多态性
多态基础上,定义统一的接口。不同的类对象作为参数使用时,得到的结果不同
python著名的鸭子模型:
只要你会某一类功能,你就是一只鸭子。
比如会游泳,会飞,会跑,好了,你是鸭子,周黑鸭的鸭子。
对比:
多态强调的是:一类事物 不同的形态
多态性强调的是:同一操作,作用对象不同,表现出不同实现方式(只关心行为结果)
练习:
创建汽车类(Car)含实例属性颜色red,对象方法run,功能是打印XX颜色小汽车在跑。
创建猫类(Cat)含实例属性名字name,对象方法run,功能是打印猫咪XX在跑。
实例化汽车类颜色为红色,实例化猫类,使用公共函数调用对象方法
设计模式
设计模式就是前人总结的经验,解决某一类问题的具体方法。比如我们肯定都做过算术题,知道首先做括号里面的,然后在做乘除,最后加减。还有我们的城市群落的形成,也是先盖新城,拉动经济,在弄旧改。所以我们学习设计模式之后,以后解决某一类问题,都不需要再重复造轮子。
单例模式
有时通过单一对象方便集中管理资源
单例模式是保证一个类仅有一个实例的设计模式
保证了在程序的不同位置都可以且仅可以取到同一个对象实例:如果实例不存在,会创建一个实例;如果已存在就会返回这个实例。
总结:某一个类只有一个对象,可以处处调用
实现单例模式的几种方式
使用模块
- python的模块是天然的单例模式,模块第一次导入时,会生成.pyc文件,第二次导入时,他只会加载.pyc文件,而不会再次执行模块代码。
- 使用装饰器
- 使用类
基于魔术方法new(*)
当实例化一个对象时,是先执行了类的
__new__
方法(我们没写的时候默认调用object.__new__
)然后再实例化类的__init__
方法class Singleton(object): instance= None def __new__(cls, *args, **kwargs): if not cls.instance: cls.instance = object.__new__(cls) return cls.instance s1 = Singleton() s2 = Singleton() print("s1的地址:{},s2的地址:{}".format(id(s1), id(s2))) 结果: s1的地址:1085113828968,s2的地址:1085113828968 12345678910111213
基于metaclass方式实现
- 相关知识
- 实现单例模式
工厂模式
python中不需要创建类,创建子类来实现工厂模式,可以直接使用
class Factory(object):
def get_person(self, name, gender='M'):
if gender == 'M':
return Male(name)
if gender == 'F':
return Female(name)
1234567
约束
约束的定义
约束就是一些约定,我们以后早晨八点来上课,晚上十点回家。这就是一种约束。在学校我们听老师的话,在家里听爸爸妈妈的话,在社会上听领导的话。什么时候不听话呢?就是你成了爷爷的时候,哈哈哈。现在既然咋们还没有是爷爷的时候,就按照规定来干。
在父类建立一种约束(通过抛出异常)
class Animal(): def eat(self): raise Exception("子类必须拥有eat方法") class Dog(Animal): def eat(self): print("dog eat") class Cat(Animal): def eat(self): print("cat eat") class Bir(Animal): def bireat(self): print("bir eat") def change(tool): tool.eat() dog = Dog() change(dog) bir = Bir() change(bir) 1234567891011121314151617181920212223
引入抽象类的概念
from abc import ABCMeta,abstractmethod class Airer(metaclass=ABCMeta): @abstractmethod def airfly(self): pass #结论: 抽象类在父类中抽象完毕之后,必须在子类中重写,不然会报错。 1234567
实例方法
类中定义的普通方法
class Person:
def func(self):
pass
只有实例化之后才可以使用,接收的第一个参数一定为对象本身
1234
类方法
指一个类中通过@classmethod
修饰的方法
第一个参数必须是当前类的对象,该参数名一般约定为cls,通过它来传递类的属性和方法。
调用:实例对象和类对象都可以调用
类方法是将类本身作为对象进行操作的方法
123
通过使用类方法可以在不创建对象的时候直接进行操作。比如有的时候我们不想要实例化对象,而执行一些操作的时候,完全可以使用
应用场景:当一个方法中只涉及到静态属性的时候可以使用类方法(类方法用来修改类属性)
#使用类方法对商品进行统一打折
#分析:商场里面客户购买东西,打几折的时候,用户自己算往往不是很快,而且还很累,这个时候就需要直接计算出打折后的价格。客户只需要调用这个类方法就可以。
class Shop:
def __init__(self,price):
self.__price = price
@property
def func(self):
return self.__price * 0.5
s = Shop(100)
print(s.func)
print(Shop.func)
#进阶版
class Shop:
__discount = 1 #折扣价
def __init__(self,name,price):
self.__name = name
self.__price = price
@property
def discount_money(self):
self.__discount = 0.5
@property
def finally_money(self):
return self.__price * self.__discount
s = Shop("橘子",5)
s.discount_money
print(s.finally_money)
Shop("苹果",10)
Shop.discount_money
print(Shop.finally_money)
#类方法进阶版
class Shop:
__discount = 1 #折扣价
def __init__(self,name,price):
self.__name = name
self.__price = price
@classmethod
def discount_money(cls,num):
cls.__discount = num / 10
@property
def finally_money(self):
return self.__price * self.__discount
s = Shop("橘子",5)
s.discount_money(8)
print(s.finally_money)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
类方法说了这么多,具体应用场景还是不太明确,还需要接着研究。
静态方法
使用@staticmethod
修饰的方法
参数随意,没有self
和cls
参数
方法体中不能使用类或实例的任何属性和方法
实例对象和类对象都可以调用
静态方法是类中的函数,不需要使用实例。也就是说不需要进行实例化就可以调用
静态方法一般定义后就不需要再进行修改,用来写一些固定的操作
应用场景:一般是与类和对象无关的代码
#静态方法
class Person:
@staticmethod
def func():
print("""
1.搞嘛?
2.不知道
3.先记下来吧
4.记下来不知道应用场景
5.我好累
""")
Person.func()
12345678910111213
property
使用property修饰的方法可以直接使用对象.
方法名进行调用,不需要给方法加括号。
应用场景:商场打折,计算周长,面积等
一般具有三种访问方式:获取,修改,删除
只有在属性定义property后才能定义setter,deleter
方法一
class Foo:
@property
def AAA(self):
print('get的时候运行我')
@AAA.setter
def AAA(self,value):
print('set的时候运行我')
@AAA.deleter
def AAA(self):
print('delete的时候运行我')
12345678910
方法二
class Foo:
def get_AAA(self):
print('get的时候运行我啊')
def set_AAA(self,value):
print('set的时候运行我啊')
def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA)
#内置property三个参数与get,set,delete一一对应
123456789101112
只有@property定义只读,加上@setter定义可读可写,加上@deleter定义可读可写可删除
反射.
反射是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!
有四个可以实现自省的函数:hasattr,getattr,setattr,delattr
user = User()
while True:
choose = input('>>>').strip()
if hasattr(user,choose):
func = getattr(user,choose)
func()
else:
print('输入错误。。。。')
123456789
内置方法
__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__
123456789101112131415161718192021222324252627
异常机制
异常(Exception)是一个事件,该事件可能会在程序执行过程中发生,影响了程序的正常执行
raise语句显式的抛出异常
Python解释器自己检测到异常并引发它
异常的固定结构:
try:
被检测的代码块
except 异常类型:
try中一旦检测到异常,就执行这个位置的逻辑
12345
自定义异常:
python中提供的错误类型可能并不能解决所有错误
如果以后你在工作中,出现了某种异常无法用已知的错误类型捕获(万能异常只能捕获python中存在的异常),那么你就可以尝试自定义异常,只要继承BaseException类即可
自定义异常:
class HelloError(Exception):
def __init__(self,n):
self.n=n
try:
n=input("请输入数字:")
if not n.isdigit():
raise HelloError(n)
except HelloError as hi:
print("HelloError:请输入字符。\n您输入的是:",hi.n)
else:
print("未发生异常")
python异常与文件操作
1.文件操作
在Python中进行文件操作通常涉及以下几个步骤:
打开文件:
使用open()函数打开文件,需要指定文件路径和模式(如读取'r',写入'w',追加'a'等)。
file = open("example.txt", "r")
执行操作:
读取文件内容:
content = file.read()
逐行读取:
for line in file:
print(line)
写入或追加内容:
with open("example.txt", "w") as file:
file.write("Some text")
关闭文件:
文件操作完成后,记得使用close()方法关闭文件以释放资源。
file.close()
或者使用with语句,它会在操作结束后自动关闭文件:
with open("example.txt", "r") as file:
# 文件操作
# 文件在这里会自动关闭
异常处理:
在进行文件操作时,最好使用try/except来捕获可能出现的错误,如文件不存在或权限问题。
try:
file = open("example.txt", "r")
# 文件操作
except FileNotFoundError:
print("File not found.")
except PermissionError:
print("Permission denied.")
finally:
if 'file' in locals():
file.close()
2.异常处理
try:
file = open("example.txt", "r")
# 文件操作
except FileNotFoundError:
print("File not found.")
except PermissionError:
print("Permission denied.")
finally:
if 'file' in locals():
file.close()
其他方法:
seek()和tell()用于移动文件指针。
write()用于写入字符串到文件。
readline()和readlines()用于读取单行或多行。
flush()用于刷新缓冲区,确保所有数据都已写入文件。
文本与二进制模式:
对于非文本数据(如图片、音频等),可以使用二进制模式,如'wb'(写入)、'rb'(读取)。
请根据具体需求选择合适的方法进行文件操作
2.异常处理
处理异常
join() 在 Python 中有多种上下文,具体取决于它在哪种类型的对象上调用。以下是两种主要的用法:
字符串的 .join() 方法:
str.join(iterable) 是 Python 字符串对象的一个方法,用于将一个可迭代对象(如列表、元组或字符串)的所有元素连接成一个新的字符串。
iterable 必须包含字符串元素,因为 join() 只能连接字符串。
分隔符是调用该方法的字符串,例如:'-'.join(['apple', 'banana', 'cherry']) 返回 'apple-banana-cherry'。
如果不提供分隔符,直接使用空字符串 '',则所有元素会被连接在一起,没有间隔,如 ''.join(['Python', 'is', 'fun']) 返回 'Pythonisfun'。
线程的 .join() 方法:
在多线程编程中,Thread.join() 是一个方法,用于等待指定的线程结束。
当在一个线程实例上调用 join() 时,调用线程会被阻塞,直到该线程执行完成。
可选参数 timeout 可以设置等待的最大时间(以秒为单位)。如果超时,join() 会返回,即使目标线程还没有结束。
使用 join() 可以确保主线程不会在子线程完成之前继续执行,这在需要等待所有子任务完成时很有用。
下面是一些示例代码:
# 字符串 join() 示例
fruits = ['apple', 'banana', 'cherry']
separator = ', '
result = separator.join(fruits)
print(result) # 输出: 'apple, banana, cherry'
# 线程 join() 示例
import threading
def worker():
print("Worker thread is running")
thread = threading.Thread(target=worker)
thread.start()
thread.join() # 等待线程完成
print("Main thread continues after worker thread")
当然,除了 str.isdigit() 方法,还有其他一些方法可以用来检查字符或字符串是否包含数字。以下是几种常见的方法:
使用 str.isnumeric(): 这个方法在 Unicode 字符串上工作,除了基本的 ASCII 数字(0-9),它还会接受其他语言的数字字符,如阿拉伯数字。但是,它不会接受带有小数点或千位分隔符的数字。
ch = '١' # 阿拉伯数字1
if ch.isnumeric():
print(f"'{ch}' 是一个数字字符")
else:
print(f"'{ch}' 不是一个数字字符")
# 输出: "'١' 是一个数字字符"
使用正则表达式 re.match() 或 re.search(): 正则表达式可以更灵活地匹配数字模式。例如,^\d+$ 匹配整个字符串都是数字的情况。
import re
ch = '1234'
if re.match(r'^\d+$', ch):
print(f"'{ch}' 只包含数字")
else:
print(f"'{ch}' 不只包含数字")
# 输出: "'1234' 只包含数字"
使用 any() 和 str.isdigit(): 如果你想检查字符串中的任何字符是否为数字,可以遍历字符串并使用 any() 函数。
ch = 'abc123'
if any(char.isdigit() for char in ch):
print(f"'{ch}' 包含数字")
else:
print(f"'{ch}' 不包含数字")
# 输出: "'abc123' 包含数字"
使用 str.isdecimal(): 这个方法与 str.isnumeric() 类似,但更严格,它只接受那些在人类语言中被视为十进制数的字符,不包括罗马数字或其他非十进制的计数系统。
ch = '①' # 一个非十进制的数字字符
if ch.isdecimal():
print(f"'{ch}' 是一个十进制数字字符")
else:
print(f"'{ch}' 不是一个十进制数字字符")
# 输出: "'①' 不是一个十进制数字字符"
评论0
暂时没有评论