Python

一、Python中的异常处理

1.try…except的语法结构为:

1
2
3
4
5
6
7
8
9
10
11
12
13
`try:`
`可能会抛出异常的代码`
`except 异常类型:`
`异常处理代码(报错后执行的代码)`
#例:
`try:`
`num1=int(input('请输入一个整数:'))`
`num2=int(input('请输入另一个整数:'))`
`result=num1/num2`
`print('结果为:',result)`
`#可能出现错误的代码`
`except ZeroDivisionError:#可能的错误类型`
`print('除数为0')`

2.try…except…except的语法结构为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
`try:`
`可能会抛出异常的代码`
`except 异常类型A:`
`异常处理代码(报错后执行的代码)`
`except 异常类型B:`
`异常处理代码(报错后执行的代码)`

`#例:`
``try:``
    ``num1=int(input('请输入一个整数:'))``
    ``num2=int(input('请输入另一个整数:'))``
    ``result=num1/num2``
``print('结果为:',result)``
``#可能出现错误的代码``
``except ZeroDivisionError:#可能的错误类型``
    ``print('除数为0')``
``except ValueError:``
    ``print('不能将字符串转成整数')``
``except BaseException:``
    ``print('未知异常')``

3.try…except…else的语法结构为:

1
2
3
4
5
6
`try:`
`可能会抛出异常的代码`
`except 异常类型:`
`异常处理代码(报错后执行的代码)`
`else:
`没有抛异常要执行的代码`

4.try…except…else…finally的语法结构为:

1
2
3
4
5
6
7
8
`try:`
`可能会抛出异常的代码`
`except 异常类型:`
`异常处理代码(报错后执行的代码)`
`else:`
`没有抛异常要执行的代码`
`finally:`
`无论是否发生异常都要执行的代码`

二、raise关键字的使用

异常处理中手动抛出异常的方法是raise

raise抛出一个异常,从而提醒程序出现了异常情况,程序能够正确地处理这些异常情况
raise关键字的语法结构为:
raise [Exception类型(异常描述信息)]
例:

1
2
3
4
5
6
7
8
`try:`
`score=eval(input('请输入成绩为:'))`
`if 0<=score<=100:`
`print('分数为:%d'%score)`
`else:`
`raise Exception('分数不正确')`
`except Exception as e:`
`print(e)`
1
2
3
4
5
6
7
8
`try:
`gender=input('请输入性别:')`
`if gender!='男' and gender!='女':`
`raise Exception('性别只能是男或女')`
`else:`
`print('您的性别是%s'%gender)`
`except Exception as a:#捕获异常对象`
`print(a)

三、函数的参数传递——默认值参数:

函数定义中位置参数和默认值参数同时存在时,默认值参数要置于位置参数之后:

1
2
3
def fun1(a,b=20):
pass
def fun2(a=20,b):#报错,语法错误pass

四、函数的参数传递——可变参数:

个数可变的位置参数:

​ 在参数前加==一颗星(*para)==,para为形式参数的名称,函数调用时可接收任意个数的实际参数,并将其一同放进一个元组中。

1
2
3
4
5
6
7
8
9
10
#个数可变的位置参数
def fun(para):
print(type(para))
for i in para:
print(i)
#调用
fun(10,20,30,40)
fun(10)
fun([10,20,30,40])#实际传递的是一个参数
#想要将列表拆开来传递值,可以在调用时,参数前加一颗星,将列表进行解包fun([10,20,35,40])个数可变的关键字参数:

个数可变的关键字参数:

在参数前加==两颗星( * * para)==,在函数调用时可接收任意多个“参数=值”形式的参数,并放到一个字典中。

1
2
3
4
5
6
7
8
9
`#个数可变的关键字参数`
`def fun2(**kwpara):`
`print(type(kwpara))`
`for key,value in kwpara.items():`
`print(f'{key}:{value}')`
`#调用`
`fun2(name='娟子姐',age=18,height=165)`
`d={'name':'娟子姐','age':18,'height':165}`
`fun2(**d)#参数若是字典,需要通过参数前加两个星的方式,做到系列解包

五、函数的返回值:

​ return可以出现在函数中的任意一个位置,用于结束函数。
​ 返回值可以是一个值,或者多个值。若返回的值是多个,结果就是一个元组类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
`def fun(num):`
`odd_sum=0`
`even_sum=0`
`tot_sum=0`
`for i in range(1,num+1):`
`if(i%2==0):`
`even_sum+=i`
`else:`
`odd_sum+=i`
`tot_sum+=i`
`return odd_sum,even_sum,tot_sum`
`print(type(fun(10)))`
`print(fun(10))`
`#可进行解包赋值`
`a,b,c=fun(10)`
`print(a,b,c)`

六、变量的作用域:

局部变量:

定义:

在函数定义处的参数和函数内部定义的变量。
#### 作用范围:

仅在函数内部、函数执行结束,局部变量的生命周期也结束。

全局变量:

定义:

在函数外定义的变量或==函数内部使用global关键字修饰的变量。#使用global关键字时声明和赋值要分开来进行。==
#### 作用范围:

整个程序,程序运行结束,全局变量的生命周期才结束。

温馨提示:

当局部变量和全局变量的名称相同时,局部变量的优先级更高

七、匿名函数lambda

定义

指没有名字的函数,这种函数只能使用一次,一般是在函数的函数体只有一句代码且只有一个返回值时,可以使用匿名函数来简化

语法结构:

result=lambda 参数列表:表达式

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
`def calc(a,b):`
`return a+b`
`print(calc(10,20))`
`#匿名函数`
`s=lambda a,b:a+b #s表示的就是一个匿名函数`
`print(type(s))`#function
`#调用匿名函数`
`print(s(10,20))`
`print()`
`lst=[10,20,30,40,50]`
`for i in range(len(lst)):`
`print(lst[i])`
`print()`
`for i in range(len(lst)):`
`result=lambda x:x[i] #根据索引取值,result的类型是function,其中x为形式参数`
`print(result(lst)) #lst是实际参数`
`#排序时使用`
`student_scores=[`
`{'name':'陈美美','score':98},`
`{'name':'张三','score':95},`
`{'name':'李四','score':100},`
`{'name':'王五','score':68}`
`]`
`#列表中的字典进行排序,排序规则是字典值的成绩`
`student_scores.sort(key=lambda x:x.get('score'),reverse=True) #按成绩降序排列`
`print(student_scores)`

八、常用的内置函数:

数据类型转换函数

函数名称 描述说明
bool(obj) 获取指定对象obj的布尔值
str(obj) 将指定对象obj转成字符串类型
int(x) 将x转成int类型
float(x) 将x转成float类型
list(sequence) 将序列转成列表类型
tuple(sequence) 将序列转成元组类型
set(sequence) 将序列转成集合类型
dict(sequence) 将序列转成字典类型

数学函数

函数名称 描述说明
abs(x) 返回x的绝对值
divmod(x,y) 返回x与y的商和余数
max(sequence) 返回sequen的最大值
min(sequence) 返回sequen的最小值
sum(iter) 对==可迭代对象==进行求和运算
pow(x,y) 返回x的y次幂
round(x,d) 对进行保留d位小数,结果==四舍五入==
code:
1
2
3
4
5
6
`print('求和:',sum([10,20,30,40,1]))`
`print(round(3.1415926))#round函数若只有一个参数,仅保留整数`
`print(round(3.9))`
`print(round(3.1415926,2))`
`print(round(314.264,-1))#-1位,个位数进行四舍五入`
`print(round(314.656,-2))#-2位,对十位数进行四舍五入`

迭代器操作函数

函数名称 描述说明
sorted(iter) 对可迭代对象进行排序
reversed(sequence) 反转序列生成新的迭代器对象
zip(iter1,iter2) 将iter1与iter2打包成==元组==并返回一个可迭代的zip对象
enumerate(iter) 根据iter对象创建一个enumerate对象
all(iter) 判断可迭代对象iter中所有元素的布尔值是否都为True
any(iter) 判断可迭代对象iter中所有元素的布尔值是否都为False
next(iter) 返回迭代器的下一个元素
filter(function,iter) 通过指定条件function(单参数函数)过滤序列(在function作用下为False的元素)并返回一个迭代器对象
map(function,iter) 通过函数function对可迭代对象iter的操作返回一个map类型的迭代器对象,要通过list()tuple()等转换为具体序列才能直接查看;函数参数数量需匹配可迭代对象数量,否则报错,每个iter的第i个元素将按照位次作为返回结果中func的第i个参数。多个可迭代对象长度不同时,会在最短的可迭代对象遍历结束后停止,相比之下列表推导式更加可读:[x*2 for x in [1,2,3]]
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
`lst=[51,12,31,21,12,244]`
`asc_lst=sorted(lst)`
`dasc_lst=sorted(lst,reverse=True)`
`print(f'原列表:{lst}')`
`print(f'升序:{asc_lst}')`
`print(f'降序:{dasc_lst}')`
`#反转 reverse`
`new_lst=reversed(lst)`
`print(type(new_lst))`
`print(new_lst)#返回结果不是列表,是一个迭代器对象,需要进行list转换才能得到相应的列表对象`
`print(list(new_lst))`
`#zip`
`x=['a','b','c','d']`
`y=[10,20,30,40,50]`
`zipobj=zip(x,y)`
`print(type(zipobj))`
`print(zipobj)`
`#print(list(zipobj))#结果为[('a', 10), ('b', 20), ('c', 30), ('d', 40)]`
`#enumerate`
`enum=enumerate(y,start=1)`
`print(type(enum))#<class 'enumerate'>`
`print(tuple(enum))#((1, 10), (2, 20), (3, 30), (4, 40), (5, 50))`
`#all`
`lst2=[10,20,30,'']`
`print(all(lst2))`
`print(all(lst))`
`#any`
`print(any(lst2))#True`
`lst3=['',[]]`
`print(any(lst3))#False`
`#next`
`print(next(zipobj))#('a', 10)`
`print(next(zipobj))#('b', 20)`
`#filter`
`def fun(num):`
`return num%2==1`
`obj=filter(fun,range(10))#将range(10),即0到9的所有整数都执行一遍fun函数`
`print(list(obj))#[1, 3, 5, 7, 9],返回为结果为True的值`
`#map`
`def upper(x):`
`return x.upper()`
`new_lst2=['hello','world','python']`
`obj2=map(upper,new_lst2)`
`print(list(obj2))`

其他常用内置函数

函数名称 描述说明
format(value,format_spec) 将value以format_spec格式进行显示
len(s) 返回s的长度或者s元素的个数
id(obj) 返回对象的内存地址
type(x) 返回x的数据类型
eval(s) 执行s这个字符串所表示的Python代码,即去掉引号后执行该代码
xxx.shuffle() 随机打乱数据顺序
1
2
3
4
5
6
7
8
9
10
11
`#format函数`
`print(format(3.14,'20'))#数值型默认右对齐`
`print(format('Hello','20'))#字符串默认左对齐`
`print(format('hello','*>20'))#*为填充符,>为右对齐`
`print(format('hello','*^20'))#*为填充符,^为居中对齐`
`print(format('hello','*<20'))#*为填充符,<为左对齐`
`print(format(3.1415926,'.2f'))#3.14`
`print(format(20,'b'))#二进制`
`print(format(20,'o'))#八进制`
`print(format(20,'x'))#十六进制`
`print(format(20,'X'))#十六进制`

九、随机列表的生成

1
2
3
4
import random
lst=[ random.randint(1,100) for i in range(10)]#列表中的元素由1到100中随机生成10个
print(lst)
random_num=random.randint(1,100)#产生1到100之间的随机数

十、三元运算符/三目运算符:

1
print('存在' if result else '不存在')#result为bool值

十一、类和对象

类:

定义:

由N多个对象抽取出“====”的==属性==和==行为==从而对那总结出来的一种==类别==。
在Python中一切皆对象
字符串对象:’hello’、’python’、’world’ etc
str字符串类型
整数对象:10,20,30 ,etc
int整数类型

自定义数据类型的语法结构为:

1
2
class 类名():#小括号可以省略不写,类相当于C语言中的结构体
pass
 #### 创建对象的语法结构格式为:

​ 对象名=类名()#小括号依据类创建时可相应的省略,对象相当于C中结构体创建后定义的一个结构体变量

十二、类的组成:

 ### 类属性:

直接定义在类中,方法外的==变量==
### 实例属性:

定义在_init_方法中,使用self打点的==变量==,即==self. ……===
### 实例方法:

定义在类中的函数,而且自带参数==self==,也称为方法
### 静态方法:

使用装饰器==@staticmethod==修饰的方法
### 类方法:

使用装饰器==@classmethod==修饰的方法

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#编写一个Person类型
class Student:
#类属性:
school='北京XXXX高中'
#初始化方法
def __init__(self,name,age):#name和age是方法的参数,为局部变量,name和age的作用域是整个__init__方法
self.name=name#左侧为实例属性,右侧为局部变量
self.age=age

def show(self):
print(f'我叫:{self.name},今年:{self.age}岁了')
#静态方法
@staticmethod
def sm():
print('这是一个静态方法,不能使用实例属性,也不能调用实例方法')
#类方法
@classmethod
def cm(cls):#cls-->class的简写
print('这是一个类方法,不能使用实例属性,也不能调用实例方法')

#创建类的对象
stu=Student('王梓恒','19')
#实例属性,使用对象名进行打点调用的
print(stu.name,stu.age)
#类属性,直接使用类名打点调用
print(Student.school)
#实例方法,使用对象名进行打点调用
stu.show()
#类方法,直接使用类名打点调用
Student.cm()
#静态方法,直接使用类名进行打点调用
Student.sm()

十三、动态绑定属性和方法:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Student:
#类属性:
school='北京XXXX高中'
#初始化方法
def __init__(self,name,age):#name和age是方法的参数,为局部变量,name和age的作用域是整个__init__方法
self.name=name#左侧为实例属性,右侧为局部变量
self.age=age

def show(self):
print(f'我叫:{self.name},今年:{self.age}岁了')
stu1=Student('张三',18)
stu2=Student('李四',19)
print(stu1.name,stu1.age,stu2.age,stu2.name)
stu2.gender='男'#动态绑定属性
print(stu2.name,stu2.age,stu2.gender)
#print(stu1.gender)
def introduce():
print('我是一个普通的函数,我是被动态绑定成了stu2对象的方法')
stu2.fun=introduce#动态绑定方法
stu2.fun()

十四、面向对象的三大特征:

封装:

一、

隐藏内部细节,对外提供操作方式,提高程序的安全性(健壮性)。

二、权限保护:通过对属性或者方法添加单下划线、双下划线以及首尾下划线来实现

单下划线开头:

​ 以单下划线开头的属性或方法表示protected受保护的成员,这类成员被视为仅供内部使用,允许类本身和子类进行访问,但实际上它可以被外部代码访问。

双下划线开头:

​ 表示private私有的成员,这类成员只允许定义该属性或方法的类本身进行访问,不能通过类的对象访问,但可以通过==”对象名._类名__xxx”==的方式来访问。

首尾双下划线:

​ 一般表示特殊的方法,一般是系统定义的名字。
​ examp:__init__ ()__str__()__new__()

代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Student:
def __init__(self,name,age,gender):
self._name=name #self._name受保护的,只能在本类和子类中访问
self.__age=age #self.__age表示私有的,只能类本身访问
self.gender=gender #类的普通实例属性,类的内部、外部以及子类都可访问
def _fun1(self):
print('子类以及本身可以访问')

def __fun2(self):
print('只有定义的类可以访问')
def display(self):#普通的实例方法
self._fun1() # 类本身访问受保护的方法
self.__fun2() # 类本身访问私有方法
print(self._name)
print(self.__age)
print(self.gender)


stu=Student('张三',18,'男')
stu.display()
print(stu._name)
#print(stu.__age)#会报错
stu._fun1()
#stu.__fun2()#会报错
#通过以下方法访问私有属性和方法
#访问私有属性的方式:对象名._类名__私有属性名
#访问私有方法的方式:对象名._类名__私有方法名
print(stu._Student__age)
stu._Student__fun2()

三、属性的设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Student:
def __init__(self,name,gender):
self.name=name
self.__gender=gender
# 使用property修改方法,将方法转成属性使用
@property
def gender(self):
return self.__gender
# 通过gender.setter将我们的gender这个属性设置为可写属性
@gender.setter
def gender(self,value):
if value!='男' and value!='女':
print('性别有误,已经性别默认设置为男')
self.__gender='男'
else:
self.__gender=value

stu=Student('张三','男')
print(f'{stu.name}的性别是{stu.gender}')#stu.gender就会去执行stu.gender()这个方法
#这样操作使私有值只能查看不能被修改
stu.gender='女'
print(f'{stu.name}的性别是{stu.gender}')

继承:

性质:

是在函数调用时,使用”形参名称=值“的方法进行传参,传递参数
在Python中一个子类可以继承N多个父类
一个父类也可以拥有N多个子类
若一个类没有继承任何类,那么这个类默认继承的是object类

实现代码的复用,通过继承可以理顺类与类之间的关系。

语法结构:

1
2
class 类名(父类1,父类2,……,父类N):
pass

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Person:#默认继承了object
def __init__(self,name,age):
self.name=name
self.age=age
def show(self):
print(f'大家好,我叫{self.name},我今年{self.age}岁')

#Student继承Person类
class Student(Person):
#编写初始化的方法
def __init__(self, name, age,stuno):
super().__init__(name, age) #调用父类的初始化方法,为name与age赋值
self.stuno=stuno

#Doctor也继承Person类
class Doctor(Person):
#编写初始化方法
def __init__(self, name, age,department):
super().__init__(name, age)
self.depar=department

#创建第一个子类对象
stu=Student('张三',20,1001)
stu.show()#大家好,我叫张三,我今年20岁
doctor=Doctor('李四',26,'外科')
doctor.show()#大家好,我叫李四,我今年26岁

多继承:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class FatherA():
def __init__(self,name):
self.name=name
def showA(self):
print('父类A的方法')
class FatherB():
def __init__(self,age):
self.age=age
def showB(self):
print('父类B的方法')

#多继承
class Son(FatherA,FatherB):
def __init__(self, name,age,gender):
#需要调用两个父类的初始化方法,用super()无法分辨其为哪个父类的初始化方法
FatherA.__init__(self,name)
FatherB.__init__(self,age)
self.gender=gender

son=Son('张三',20,'男')
son.showA()#从FatherA中继承来
#父类A的方法
son.showB()#从FatherB中继承来
#父类B的方法


方法重写:

性质:

1.子类继承了父类,就拥有了父类中公有成员和受保护的成员。

2.父类的方法并不能完全适合子类的需求时,子类可以重写父类的方法。

3.子类重写父类的方法时,要求方法名称必须同父类方法名称相同,在子类重写后的方法中可以通过super().xxx()的方式调用父类中的方法。

4.若子类重写父类方法,则只执行子类重写的方法。

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Person:#默认继承了object
def __init__(self,name,age):
self.name=name
self.age=age
def show(self):
print(f'大家好,我叫{self.name},我今年{self.age}岁')

#Student继承Person类
class Student(Person):
#编写初始化的方法
def __init__(self, name, age,stuno):
super().__init__(name, age) #调用父类的初始化方法,为name与age赋值
self.stuno=stuno
def show(self):
#调用父类中的方法
super().show() #ps:不要忘了super方法后的()
print(f'我来自北京航空航天大学,我的学号是{self.stuno}')

#Doctor也继承Person类
class Doctor(Person):
#编写初始化方法
def __init__(self, name, age,department):
super().__init__(name, age)
self.depar=department
def show(self):
print(f'大家好,我叫{self.name},今年我{self.age},我的部门是{self.depar}')

#创建第一个子类对象
stu=Student('张三',20,1001)
stu.show()#大家好,我叫张三,我今年20岁
doctor=Doctor('李四',26,'外科')
doctor.show()#大家好,我叫李四,我今年26岁

object 类

性质

1.所有类直接或间接的父类

2.所有类都拥有object类的属性和方法

object类中特殊的方法
方法 功能描述
__new__() 由系统调用,用于创建对象。
__init__() 创建对象时手动调用,用于初始化对象属性值。
__str__() 对象的描述,返回值是str类型,默认输出对象的内存地址。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age

per=Person('张三',18)#创建对象时会自动调用__init__()方法
print(dir(per))
#['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name', 'show']
print(per) #自动调用了__str__()方法
#<__main__.Person object at 0x000001D45E7C9E50>,__str__()方法默认输出对象的内存地址
#__str__()方法的重写
class Personn():
def __init__(self,name,age):
self.name=name
self.age=age
#__str__()方法的重写
def __str__(self):
return '这是一个Personn类,具有name和age两个实例属性' #返回值为一个字符串

perr=Personn('张三',18)
print(perr)
print(perr.__str__())#手动调用方法的方式

多态

1.指的是“==多种形态==”,即便不知道一个变量所引用的对象到底是什么类型,仍可以通过这个变量调用对象的方法。

2.在程序运行过程中根据变量所引用对象的数据类型,==动态决定==调用哪个对象中的方法。

3.Python语言中的多态,根本不关心对象的数据类型,也不关心类之间是否存在继承关系,==只关心对象的行为(方法)==。只要不同的类中有同名的方法,即可实现多态。

4.提高程序的可拓展性和可维护性。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Person():
def eat(self):
print('人吃五谷杂粮。')


class Cat():
def eat(self):
print('猫吃鱼。')


class Dog():
def eat(self):
print('狗吃肉。')

#三个类中有同名的方法:eat
def fun(obj):#obj是函数的形式参数,在定义的时候并不知道其数据类型
obj.eat() #通过变量obj(对象)调用eat方法

per=Person()
cat=Cat()
dog=Dog()
#小括号不能省略
fun(per) #这就构成了多态,只关心对象是否有同名方法
fun(cat)
fun(dog)
#这三个类都隐式继承了自object类(所有类的爹),当传参时obj就指向了传参时的那个子类对象,所以调用函数就该子类对象方法

十五、对象的特殊方法

运算符 特殊方法 功能描述
+ __add__() 加法
- __sub__() 减法
<,<=,== __lt__(),__le__(),__eq__() 比较
>,>=,!= __gt__(),__ge__(),__ne__() 比较
*,/ __mul__(),__truediv__() 乘法,非整除运算
%,// __mod__(),__floordiv__()(floor指向下取整,也即整除) 取余与整除运算
** __pow__() 幂运算

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a=10
b=20
print(dir(a))
print(a+b)
print(a.__add__(b))
print(a.__add__(b))#执行减法运算
print(f'{a}<{b}吗?',a.__lt__(b))#10<20吗? True
print(f'{a}<={b}吗?',a.__le__(b))#10<=20吗? True
print(f'{a}=={b}吗?',a.__eq__(b))#10==20吗? False
print(f'{a}>{b}吗?',a.__gt__(b))#10>20吗? False
print(f'{a}>={b}吗?',a.__ge__(b))#10>=20吗? False
print(f'{a}!={b}吗?',a.__ne__(b))#10!=20吗? True
print(a.__mul__(b))#200
print(a.__truediv__(b))#0.5
print(a.__mod__(b))#10
print(a.__floordiv__(b))#0
print(a.__pow__(2))#100

十六、Python中的特殊属性

特殊属性 功能描述
obj.__dict__ 对象的属性字典
obj.__class__ 对象所属的类
class.__bases__ 类的父类元组
class.__base__ 类的父类
class__mro__(mro==Method Resolution Order 方法解析顺序) 类的层次结构
class._subclasses__() 类的子类列表

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name,age):
self.name=name
self.age=age
a=A()
b=B()
c=C('张三',18)
print('对象a的属性字典:',a.__dict__)
print(f'对象b的属性字典:{b.__dict__}')
print(f'对象c的对象属性字典:{c.__dict__}')

print('对象a所属的类:',a.__class__)#<class '__main__.A'>
print(f'对象b所属的类:{b.__class__}')
print(f'对象c所属的类:{c.__class__}')#<class '__main__.C'>

print('A类的父类元组:',A.__bases__)#(<class 'object'>,)
print(f'B类的父类元组:{B.__bases__}')
print(f'C类的父类元组:{C.__bases__}')#(<class '__main__.A'>, <class '__main__.B'>)

print('A类的父类:',A.__base__)#<class 'object'>
print(f'B类的父类:{B.__base__}')
print(f'C类的父类:{C.__base__}')#<class '__main__.A'>
#嫡长父制,若继承多个父类,只显示第一个赋予的父类

print('A类的层次结构:',A.__mro__) #(<class '__main__.A'>, <class 'object'>
print(f'B类的层次结构:{B.__mro__}')
print(f'C类的层次结构:{C.__mro__}')#(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
#打印出一个包含自己和直接父类以及间接父类(父类的父类等)的元组,

#子类列表
print(f'A类子类列表:{A.__subclasses__()}')#A类子类列表:[<class '__main__.C'>]
print(f'B类子类列表:{B.__subclasses__()}')
print(f'C类子类列表:{C.__subclasses__()}')#[]

十七、类的深拷贝与浅拷贝

变量的赋值

只是形成两个变量,实际上还是指向==同一个对象==。

浅拷贝

拷贝时,对象包含的==子对象内容不拷贝==,因此,源对象与拷贝对象会引用同一个子对象。

深拷贝

使用copy模块的。

deepcopy函数,递归拷贝对象中包含的子对象,==源对象和拷贝对象所有的子对象也不相同==。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class CPU():
pass
class Disk():
pass

class Computer():
def __init__(self,cpu,disk):
self.cpu=cpu
self.disk=disk

cpu=CPU()
disk=Disk()

com=Computer(cpu,disk)
#变量(对象)的赋值
com1=com
print(f'{com}子对象的内存地址:{com.cpu},{com.disk}')#<__main__.Computer object at 0x0000021FF4D2A2A0>子对象的内存地址:<__main__.CPU object at 0x0000021FF4D2A300>,<__main__.Disk object at 0x0000021FF4D2A270>
print(f'{com1}子对象的内存地址:{com1.cpu},{com1.disk}')#<__main__.Computer object at 0x0000021FF4D2A2A0>子对象的内存地址:<__main__.CPU object at 0x0000021FF4D2A300>,<__main__.Disk object at 0x0000021FF4D2A270>

#类对象的浅拷贝
import copy
com2=copy.copy(com) #com2是新产生的对象,com2的子对象cpu、disk不变
print(f'{com}子对象的内存地址:{com.cpu},{com.disk}')#<__main__.Computer object at 0x0000021FF4D2A2A0>子对象的内存地址:<__main__.CPU object at 0x0000021FF4D2A300>,<__main__.Disk object at 0x0000021FF4D2A270>
print(f'{com2}子对象的内存地址:{com2.cpu},{com2.disk}')#<__main__.Computer object at 0x000002750FECA7E0>子对象的内存地址:<__main__.CPU object at 0x000002750FECA6F0>,<__main__.Disk object at 0x000002750FECA660>

#类对象的深拷贝
com3=copy.deepcopy(com) #com3是新产生的对象,其子对象也是新产生的
print(f'{com}子对象的内存地址:{com.cpu},{com.disk}')#<__main__.Computer object at 0x0000021FF4D2A2A0>子对象的内存地址:<__main__.CPU object at 0x0000021FF4D2A300>,<__main__.Disk object at 0x0000021FF4D2A270>
print(f'{com3}子对象的内存地址:{com3.cpu},{com3.disk}')#<__main__.Computer object at 0x0000022CF50EED50>子对象的内存地址:<__main__.CPU object at 0x0000022CF50EEE10>,<__main__.Disk object at 0x0000022CF50EEE70>

十八、使用PIL获取和修改像素的RGB值

先通过编译器内的终端输入指令

1
pip install pillow

下载PIL(Python Imaging Library)库

之后先导入库,并使用PIL提供的Image.open()函数打开照片文件。

1
2
from PIL import Image
image = Image.open('image.jpg')#'image.jpg'可以是相对路径或绝对路径,格式也可为jpg、png、bmp等

打开了图像文件后,可以使用.size函数获取图像的尺寸,用两个变量接收刚好为图像的长和宽,再通过.getpixel方法即可获取某一坐标点的RGB值或者通过.putpixel((坐标),(RGB值))来修改像素块的RGB值并通过save()方法将修改后的图像保存为modified_image.jpg

1
2
3
4
5
6
7
8
9
10
11
12
#获取图像尺寸
width,height = image.size
#遍历每一个像素点
for x in range(width):
for y in range(height):
#获取坐标为(x,y)的RGB值
R , G , B = image.getpixel((x,y))
for x in range(width):
for y in range(height):
image.putpixel((x,y),(250,0,0))

image.save('modified_image.jpg')

Numpy库

提供两种基本对象:ndarray存储单一数据类型的多维数组;ufunc可对数组进行处理的函数。