python_面向对象(6)

时间:2022-02-22 00:31:10

第1章 递归函数
1.1 概述
1.2 练习
1.3 二分查找
第2章 面向对象•类
2.1 类的介绍
2.2 书写格式
2.3 类的属性
2.4 self介绍
2.5 类属性补充
2.6 调用查看静态变量
2.6.1 .__dict__(双下方法)
2.6.2 类名.变量名
2.6.3 对比总结
2.7 操作动态变量方法
2.7.1 类名.__dict__[方法名]()
2.7.2 类名.方法名()
2.7.3 对比总结
第3章 面向对象•对象
3.1 对象本质
3.2 对象介绍
3.3 实例应用
3.4 __init__方法
第4章 类的名称空间与对象的名称空间
4.2 查找顺序
4.3 对象操作属性变量的两种方式
4.4 类操作的方法的两种方式
4.5 操作实例
4.6 对象操作方法有两种:
第5章 面向对象的名称空间,执行顺序
第6章 组合
第7章 面向对象的三个特征
7.1 继承
7.2 继承实例
7.3 内部继承顺序:
7.4 python3与python2类别
7.5 新式类经典类的区别
7.6 经典和新式的写法
7.7 经典类应用
7.8 新式类应用
7.9 继承:单继承和多继承
7.10 supper
7.10.1 新式类——单继承
7.10.2 新式类——多继承(钻石继承)
7.10.3 mro
7.10.4 Python2经典类——深度优先(默认)
7.10.5 坑

第1章 递归函数

1.1 概述

解释:人理解函数,神理解递归,一般100次没有解决问题,放弃递归

定义:自己调用自己,默认递归深度998

1.2 练习

1)例深度998

count = 0

def func1():

global  count

count += 1

print(count)

func1()

func1()

输出

992

993

994

995

996

997

998

Process finished with exit code 1

2)练习

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import sys

sys.setrecursionlimit(100000)

count = 0

def func1():

global count

count += 1

print(count)

func1()

func1()

输出

3217

3218

3219

3220

3)例:用递归解决一个年龄问题

def age(n):

if n == 1:

return 23

else:

return age(n-1) +2

print(age(2))

print(age(3))

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

25

27

1.3 二分查找

递归实现二分查找:

1)用索引的方式在下列列表中取到77这个值的索引:

l = [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25,  75, 77, 79, 81, 83, 85, 87]

print(l.index(77))

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

13

2)自定义index,解决取值77的索引:

l = [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25,  75, 77, 79, 81, 83, 85, 87]

index = 0

for i  in l:

if i == 77:

print(index)

index += 1

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

13

3)例:

for i in range(len(l)):

if l[i] == 77:

print(i)

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

13

4)利用递归函数,通过二分查找的方法去寻找77的索引:

l = [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 75, 77, 79, 81, 83, 85, 87]

def two_search(l,aim):

mid_index = len(l) // 2

if aim > l[mid_index]:

return two_search(l[mid_index+1:],aim)

elif aim < l[mid_index]:

return two_search(l[:mid_index],aim)

elif aim == l[mid_index]:

return mid_index

else:

return '没有此值'

print(two_search(l,77))

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

0

报错原因:二分查找取值为每一次的中间值作为对比值,当下一次对比值为77时,索引从当前位置计算所以是0.

4)二分查找实例:

l = [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 75, 77, 79, 81, 83, 85, 87]

def two_search(l,aim,start=0,end=len(l)-1):

if end >= start:

mid_index = (end - start) // 2 + start

if aim > l[mid_index]:

return two_search(l,aim,start=mid_index+1,end=end)

elif aim < l[mid_index]:

return two_search(l,aim,start=start,end=mid_index -1)

elif aim == l[mid_index]:

return mid_index

else:

return '没有此值'

print(two_search(l,77))

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

13

解决传值问题

def two_search(l,aim,start=0,end=None):

end = len(l) - 1 if end is None else end

if end >= start:

mid_index = (end - start) // 2 + start

if aim > l[mid_index]:

return two_search(l,aim,start=mid_index+1,end=end)

elif aim < l[mid_index]:

return two_search(l,aim,start=start,end=mid_index -1)

elif aim == l[mid_index]:

return mid_index

else:

return '没有此值'

print(two_search(l,77))

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

13

第2章 面向对象·类

l  初识:面向对象,实际工作中,python都是面向对象,写代码,或者面向对象加函数。面向对象编程:要具有上帝思维

l  优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

l  缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。

2.1 类的介绍

l  类 :是具有相同属性和技能的一类事物。

2.2 书写格式

class Person:       èclass 关键字,定义了一个类

'''

类里面的所有内容

'''

animal = '高级动物' è静态变量

soup = '有思想'     è静态变量

def work(self):     è动态变量,所具有的方法

print('人会工作')

2.3 类的属性

class Person:   #定义一个人类

role = 'person'  #人的角色属性都是人

def walk(self):  #人都可以走路,也就是有一个走路方法

print("person is walking...")

print(Person.role)  #查看人的role属性

print(Person.walk)  #引用人的走路方法,注意,这里不是在调用

2.4 self介绍

self:在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给他起个别的名字,但是正常人都不会这么做

2.5 类属性补充

一:我们定义的类的属性到底存到哪里了?有两种方式查看

dir(类名):查出的是一个名字列表

类名.__dict__:查出的是一个字典,key为属性名,value为属性值

二:特殊的类属性

类名.__name__# 类的名字(字符串)

类名.__doc__# 类的文档字符串

类名.__base__# 类的第一个父类(在讲继承时会讲)

类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)

类名.__dict__# 类的字典属性

类名.__module__# 类定义所在的模块

类名.__class__# 实例对应的类(仅新式类中)

2.6 调用查看静态变量

2.6.1 .__dict__(双下方法)

一般你想查询全部的静态变量时,用__dict__其他全部都用类名.变量名

通过类名.__dict__方法,只能查,不能增删改

class Person: #class 关键字,定义了一个类

'''

类里面的所有内容

'''

animal = '高级动物'

soup = '有思想'

def work(self): #所具有的方法

print('人会工作')

print(Person.__dict__['animal'])

Person.__dict__['name'] ='动物世界'

输出:

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

高级动物

Traceback (most recent call last):

File "D:/python/untitled2/python_6/lession.py", line 182, in <module>

Person.__dict__['name'] ='动物世界'

TypeError: 'mappingproxy' object does not support item assignment

2.6.2 类名.变量名

通过类。变量名可以增删改查

class Person: #class 关键字,定义了一个类

'''

类里面的所有内容

'''

animal = '高级动物'

soup = '有思想'

def work(self): #所具有的方法

print('人会工作')

print(Person.animal)

Person.animal = '低级动物'

Person.kind = '有性格'

print(Person.__dict__)

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

高级动物

{'__module__': '__main__', '__doc__': '\n    类里面的所有内容\n    ', 'animal': '低级动物', 'soup': '有思想', 'work': <function Person.work at 0x00000000027F98C8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, 'kind': '有性格'}

2.6.3 对比总结

l  一般你想查询全部的静态变量时,用__dict__其他全部都用类名.变量名

l  修改类要用到‘类名.变量名%

2.7 操作动态变量方法

2.7.1 类名.__dict__[方法名]()

只要创建类就加载到内存????

class Person: #class 关键字,定义了一个类

'''

类里面的所有内容

'''

animal = '高级动物'

soup = '有思想'

def work(self): #所具有的方法

print('人会工作')

操作方法

print(Person.__dict__['work']('self'))

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

人会工作

None

2.7.2 类名.方法名()

操作方法:

Person.work(11)

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

人会工作

2.7.3 对比总结

l  一般通过对象方法去调用,基本不使用

l  如果是类操作方法:类名.方法名()

第3章 面向对象·对象

3.1 对象本质

class 类名:

def __init__(self,参数1,参数2):

self.对象的属性1 = 参数1

self.对象的属性2 = 参数2

def 方法名1(self):pass

def 方法名2(self):pass

对象名 = 类名(1,2)

#对象就是实例,代表一个具体的东西

#类名(): 类名+括号就是实例化一个类,相当于调用了__init__方法。

#括号里传参数,参数不需要传self,与其他init中的形参--对应

#结果返回一个 对象

对象名.对象属性1 #查看对象属性,直接用,对象名 即可

对象名.方法名() #调用类中的方法,直接用 对象名.方法名()即可

3.2 对象介绍

l  对象:实例化的一个类,是类的具体体现

猫是一个类,楼下那只小白这是一个对象

l  实质

类名() è 实例化一个对象

l  定义方式

p1 = Person() #p1 对象,实例化对象类名()过程就叫做实例化一个对象

p2 = Person() #p2

3.3 实例应用

例:

class Person: #class 关键字,定义了一个类

'''

类里面的所有内容

'''

animal = '高级动物'

soup = '有思想'

def __init__(self): #构造方法

print(999)

def work(self): #所具有的方法

print('人会工作')

p1 = Person()

3.4 __init__方法

解释:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征

构造方法,只要实例化一个对象,自动触发__init__

不用传参,直接可以运行__init___的原因???

内部进行三步:

l  第一步:实例化一个对象,在内存中产生一个对象空间

l  第二步:自动执行init方法,并将这个空间对象<__main__.Person object at 0x0000000001EB8860>传给self

l  第三步:通过构造方法里的代码给空间对象添加一些属性,并返回给对象。

class Person:  è定义一个人类

role = 'person' è人的角色属性都是人

def __init__(self,name):

self.name = name è每一个角色都有自己的昵称

def walk(self): è人都可以走路,这里是方法

print('person is walking')

print(Person.role) è查看人的role属性

print(Person.walk) è引用人的走路方法,并不是调用

第4章 类的名称空间与对象的名称空间

解释:创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性

4.1 类的名称空间

类有两种属性:静态属性和动态属性

n  静态属性就是直接在类中定义的变量

n  动态属性就是定义在类中的方法

n  其中类的数据属性是共享给所有对象的

4.2 查找顺序

在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

4.3 对象操作属性变量的两种方式

1)对象.__dict__方法 只能查看不能增删改

print(p1.__dict__)

2)对象.变量名 可憎删改查

print(p1.name)

print(p1.eye)

总结:一般在查询全部静态变量时,用__dect__ 其他全都用 类名.变量名

4.4 类操作的方法的两种方式

1)类名.__dict__[方法名]()

print(Person.__dict__['work'](11))

2)类名.方法名

Person.work(11)

3)对象.变量名

4.5 操作实例

class Person:

'''

类里面所有内容

'''

animal = '高级动物' #静态变量

soup = '有思想'     #静态变量

def __init__(self,name,sex,eye,high,weifht): #构造方法

self.eye = eye #属性

self.name = name

self.sex = sex

self.high = high

self.weifht = weifht

print(666)

def work(self): #动态变量,动态方法

print(self)

对象对属性的操作:对象.__dict__

p1 = Person('li','nan','大眼睛',180,180)

print(p1.__dict__)

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

666

{'eye': '大眼睛', 'name': 'li', 'sex': 'nan', 'high': 180, 'weifht': 180}

对象.变量名 可增删改查

p1 = Person('li','nan','大眼睛',180,180)

print(p1.name)

p1.color = '黄皮肤'

print(p1.coler)

4.6 对象操作方法有两种:

1)对象.方法名()

2)类名.方法名()

p1.work()

print(p1)

print(p1.__dict__)

对象只能访问类的东西,不能增删改

class Person:

'''

类里面所有内容

'''

animal = '高级动物' #静态变量

soup = '有思想'     #静态变量

def __init__(self,name,sex,eye,high,weifht): #构造方法

self.eye = eye #属性

self.name = name

self.sex = sex

self.high = high

self.weifht = weifht

print(666)

def work(self): #动态变量,动态方法

print(self)

p1 = Person('li','nan','大眼睛',180,180)

# print(p1.__dict__)

print(p1.eye)

print(p1.animal)

print(p1.work())

输出

666

大眼睛

高级动物

<__main__.Person object at 0x0000000002218A20>

None

在构造对象时增加

class Person:

'''

类里面所有内容

'''

animal = '高级动物' #静态变量

soup = '有思想'     #静态变量

def __init__(self,name,sex,eye,high,weifht): #构造方法

self.eye = eye #属性

self.name = name

self.sex = sex

self.high = high

self.weifht = weifht

print(666)

def work(self,job): #动态变量,动态方法

self.job = job

print(self)

p1 = Person('li','nan','大眼睛',180,180)

print(p1.__dict__)

p1.work('It')

print(p1.__dict__)

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

666

{'eye': '大眼睛', 'name': 'li', 'sex': 'nan', 'high': 180, 'weifht': 180}

<__main__.Person object at 0x0000000002218AC8>

{'eye': '大眼睛', 'name': 'li', 'sex': 'nan', 'high': 180, 'weifht': 180, 'job': 'It'}

第5章 面向对象的名称空间,执行顺序

5.1 self

self 约定俗称叫self 不能改变

通过实例化对象查找属性,先从对象空间找,没有则通过类对象指从类空间找

class Pserson:

animal = '高级动物'

soup = '有思想'

name = 'li'

def __init__(self,name,sex,eye,high,weight):

self.eye = eye

self.name = name

self.sex = sex

self.high = high

self.weight = weight

print(999)

def work(self,job):

self.job = job

print('人会工作')

p1 = Pserson('xiaobai','nv','xiaoyanjing',123,123)

print(p1.__dict__)

输出

C:\python3\python.exe D:/python/untitled2/lianxi/lianxi.py

999

{'eye': 'xiaoyanjing', 'name': 'xiaobai', 'sex': 'nv', 'high': 123, 'weight': 123}

5.2 练习

在终端输出如下信息

小明,10岁,男,上山去砍柴

小明,10岁,男,开车去东北

小明,10岁,男,最爱大保健

老李,90岁,男,上山去砍柴

老李,90岁,男,开车去东北

老李,90岁,男,最爱大保健

class Dayaction:

def __init__(self,name,age,sex):

self.name = name

self.aage = age

self.sex = sex

def chop_wood(self,name,age,sex):

print('%s,%s岁,%s,上山去砍柴' %(name,age,sex))

def driver(self,name,age,sex):

print('%s,%s岁,%s,开车去东北' %(name, age, sex))

def healthcare(self,name,age,sex):

print('%s,%s岁,%s,最爱大保健' %(name, age, sex))

p1 = Dayaction('小明',15,'男')

p1.chop_wood('小明',15,'男')

p1.driver('小明',15,'男')

p1.healthcare('小明',15,'男')

输出

C:\python3\python.exe D:/python/untitled2/lianxi/lianxi.py

小明,15岁,男,上山去砍柴

小明,15岁,男,开车去东北

小明,15岁,男,最爱大保健

简洁代码self深入用法

class Dayaction:

def __init__(self,name,age,sex):

self.name = name

self.age = age

self.sex = sex

def chop_wood(self):

print('%s,%s岁,%s,上山去砍柴' %(self.name,self.age,self.sex))

def driver(self):

print('%s,%s岁,%s,开车去东北' %(self.name, self.age, self.sex))

def healthcare(self):

print('%s,%s岁,%s,最爱大保健' %(self.name, self.age, self.sex))

p1 = Dayaction('小明',15,'男')

p1.chop_wood()

p1.driver()

p1.healthcare()

输出

C:\python3\python.exe D:/python/untitled2/lianxi/lianxi.py

小明,15岁,男,上山去砍柴

小明,15岁,男,开车去东北

小明,15岁,男,最爱大保健

面向对象把参数封装一个空间直接调用

函数需要每用一次要传一次

第6章 组合

给一个类对象的属性 复值 (封装) 给另一个类的对象。

class Game_person:

def __init__(self,nickname,sex,hp,ad):

self.nickname = nickname

self.sex = sex

self.hp = hp

self.ad = ad

def attack(self,p):

p.ph -= self.ad

print('%s攻击了%s,%s还剩%s血量'%(self.nickname,p.nickname,p.nickname,p.hp))

def weapon_attack(self,武器):

self.武器 = 武器 #斧子对象

class Weapon:

def __init__(self,name,ad):

self.name=name

self.ad=ad

def fight(self,p1,p2):

p2.hp -= self.ad

print('%s使用%s打了%s%s血,%s还剩%s滴血'\

%(p1.nickname,self.name,p2.nickname,self.ad,p2.nickname,p2.hp))

ts = Game_person('泰森','男',200,50)

barry = Game_person('太白','男',100,10)

wea = Weapon('斧子',60)

# wea.fight(barry,ts) 这样写不好,主体应该是人

ts.attack(barry)

# barry.attack(ts)

barry.weapon_attack(wea)

# barry对象调用weapon_attack方法,

# 方法执行的是将斧子对象wea封装到barry对象的属性中、

# barry.武器 相当于 wea

barry.武器.fight(barry,ts)

第7章 面向对象的三个特征

7.1 继承

解释:可以有效的节省代码

7.2 继承实例

Animal è 称之:父类,基类

Cat    è 子类,派生类

class Animal:

def __init__(self,varieties,sex,color):

self.varieties = varieties

self.sex =sex

self.color = color

class Cat(Animal):

pass

class  Dog(Animal):

pass

class Rabbit(Animal):

pass

cat1 =Cat('bosimao','gong','hei')

print(cat1.__dict__)

输出:

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

{'varieties': 'bosimao', 'sex': 'gong', 'color': 'hei'}

7.3 内部继承顺序:

7.4 python3与python2类别

l  python3版本中,所有的类都默认进程object类,继承object类的类称为新式类。

l  python2中分为经典类和新式类,在python3中只有新式类

7.5 新式类经典类的区别

n  新式类:遵循的是广度优先

n  经典类:遵循到的是深度优先

解释:

1、Python的类可以继承多个类,Java和C#中则只能继承一个类

2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先

当类是经典类时,多继承情况下,会按照深度优先方式查找

当类是新式类时,多继承情况下,会按照广度优先方式查找

经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法。

7.6 经典和新式的写法

从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。

7.7 经典类应用

# 经典类多继承

class D:

def bar(self):

print('D.bar')

class C(D):

def bar(self):

print('C.bar')

class B(D):

def bar(self):

print('B.bar')

class A(B, C):

def bar(self):

print('A.bar')

a = A()

# 执行bar方法时

# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错

# 所以,查找顺序:A --> B --> D --> C

# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了

a.bar()

7.8 新式类应用

class D(object):

def bar(self):

print('D.bar')

class C(D):

def bar(self):

print('C.bar')

class B(D):

def bar(self):

print('B.bar')

class A(B, C):

def bar(self):

print('A.bar')

a = A()

# 执行bar方法时

# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错

# 所以,查找顺序:A --> B --> C --> D

# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了

a.bar()

7.9 继承:单继承和多继承

class Animal:

def __init__(self,varieties,sex,color):

self.varieties = varieties

self.sex =sex

self.color = color

def eat(self):

print('吃')

class Cat(Animal):

pass

class Bird(Animal):

def __init__(self,varieties,sex,color,fly):

#执行父类的方法第一种方式

#Animal.__init__(self,varieties,sex,color,)

#执行父类的方法第二种方法

#super(Animal.self).__init__(varieties,sex,color)

#执行父类的方法的第二种方式,省略写法

super().__init__(varieties,sex,color)

self.fly = fly

#个性化封装

def eat(self):

super().eat()

print('鸟该吃饭了')

#问题1

#执行顺序,所以执行 猫吃饭

cat1 =Cat('bosimao','gong','hei')

cat1.eat()

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

7.10 supper

解释:继承父类又显示子类

#问题2

#猫,鸟,都有自己独立属性,如何使用共同的属性并且使用独立的属性

b1 = Bird('鹦鹉','公','绿色','800')

print(b1.__dict__)

b1.eat()

输出

{'varieties': '鹦鹉', 'sex': '公', 'color': '绿色', 'fly': '800'}

鸟该吃饭了

7.10.1 新式类——单继承

class A():

def func(self):

print('A')

class B(A):

def func(self):

print('B')

class C(B):

def func(self):

print('C')

c1 = C()

c1.func()

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

C

7.10.2 新式类——多继承(钻石继承)

广度优先:每个节点只走一次,用最少的此处,只是个算法

class A:

def func(self):

print('A')

class B(A):

def func(self):

print('B')

class C(A):

def func(self):

print('C')

class D(B,C):

pass

d1 = D()

d1.func()

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

B

如下图:

7.10.3 mro

class D():

def func(self):

print('D')

class E():

def func(self):

print('E')

class F():

def func(self):

print('D')

print(F.mro())

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

[<class '__main__.F'>, <class 'object'>]

7.10.4 Python2经典类——深度优先(默认)

如果python2中改变经典为新式类,就让类(objec)

class D(object):

def bar(self):

print('D.bar')

class C(D):

def bar(self):

print('C.bar')

class B(D):

def bar(self):

print('B.bar')

class A(B, C):

def bar(self):

print('A.bar')

a = A()

7.10.5 坑

单继承中,先从自身开始引用

class A:

def func(self):

print('A')

def __init__(self):

self.func()

class B(A):

def func(self):

print('B')

b1 = B()

输出

C:\python3\python.exe D:/python/untitled2/python_6/lession.py

B