面向对象(组合、继承(单继承、多继承)、多态)

复习上周内容:

# collections模块
# 有序字典 orderddict
# 默认字典 defaultdict
# 可命名元祖 namedtuple

# 时间模块
# 三种时间格式 时间戳时间 结构化时间 格式化时间
# 计算时间差
# 两个时间都转换成时间戳
# 时间戳之间相减 以秒为单位的小数差
# 将小数差转换成结构化时间 元组 1970 1.3
# 用当前结构化的时间差 减去 1970 1 1 0:0:0

# random模块
# 发红包 发200的红包,发5个 —— 代码
# (0,200) 取4个点
# 验证码
# 从数字中选一个 0-9
# 从a-z选一个
# 到底是字母还是数字也是随机的

# os模块 —— 操作系统打交道
# 文件相关
# 文件夹相关的
# 和执行系统命令相关
# 和路径相关的

# sys模块 —— 和解释器相关的
# sys.path
# sys.argv 执行py脚本的时候传入的参数

# 正则模块
# 正则表达式
# 能够判断 邮箱 手机号
# re模块


# 三个模块+序列化

一、初识面向对象

 



前言举例1:人狗大战

 

 
 
 函数 基础数据类型 循环 文件处理 模块
# 游戏公司
# 人狗大战
# 两个角色
# 人
# 昵称
# 性别
# 生命值
# 战斗力
# 背包
# 狗
# 昵称
# 品种
# 生命值
# 战斗力
def Person(name,sex,hp,dps):   # 人模子
dic = {'name':name,'sex':sex,'hp':hp,'dps':dps,'bag':[]}
def attack(dog):
print('dog为>>>>>>',dog)
dog['hp'] -= dic['dps']
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (dic['name'], dog['name'], dog['name'], dic['dps'], dog['hp']))
dic['attack'] = attack
return dic
def Dog(name,kind,hp,dps): # 狗模子
dic = {'name':name,'kind':kind,'hp':hp,'dps':dps}
def bite(person):
print('person为>>>>>>',person)
person['hp'] -= dic['dps']
print('%s咬了%s,%s掉了%s点血,剩余%s点血' % (dic['name'], person['name'], person['name'], dic['dps'], person['hp']))
dic['bite'] = bite
return dic
alex = Person('alex','不详',250,5)
ha2 = Dog('哈士奇','藏獒',15000,200)
# 人打狗
print(alex)
print(ha2)
print(alex['attack'])
alex['attack'](ha2)
ha2['bite'](alex)
print(ha2)

执行结果:

{'name': 'alex', 'sex': '不详', 'hp': 250, 'dps': 5, 'bag': [], 'attack': <function Person.<locals>.attack at 0x02144468>}
{'name': '哈士奇', 'kind': '藏獒', 'hp': 15000, 'dps': 200, 'bite': <function Dog.<locals>.bite at 0x02144420>}
<function Person.<locals>.attack at 0x02144468>
dog为>>>>>> {'name': '哈士奇', 'kind': '藏獒', 'hp': 15000, 'dps': 200, 'bite': <function Dog.<locals>.bite at 0x02144420>}
alex打了哈士奇,哈士奇掉了5点血,剩余14995点血
person为>>>>>> {'name': 'alex', 'sex': '不详', 'hp': 250, 'dps': 5, 'bag': [], 'attack': <function Person.<locals>.attack at 0x02144468>}
哈士奇咬了alex,alex掉了200点血,剩余50点血
{'name': '哈士奇', 'kind': '藏獒', 'hp': 14995, 'dps': 200, 'bite': <function Dog.<locals>.bite at 0x02144420>}

 

# 面向对象的编程思想
# 人狗大战
# 创建一个人
# 创建一个狗
# 人打狗 —— 函数
# 狗咬人 —— 函数

# 造模子 —— 面向对象
# 规范了一类角色的属性项目、属性的名字、技能、技能的名字
# 权限 有一些函数 只能是这个角色才能拥有 才能调用

1、初始面向对象
# 类  : 具有相同属性和相同动作的一类事物 组成一个类
# 对象 : 具体的某一个具有实际属性 和具体动作的一个实体

# 类:例如人类,类是抽象的
# 对象是具体的
# 类被创造出来 就是模子 是用来描述对象的

语法:
class 类名:
  静态属性=None(可以为任意的数据类型) --相当于变量
  def 动态属性(self):pass --相当于函数
# 在类中的方法的一个默认的参数,但也只是一个形式参数,约定必须叫self

    print(self)
只要是写在类名中的名字,不管是变量还是函数名,都不能在类的外部直接调用,只能通过类名来使用它。

#类名第一个功能:查看静态属性
# print(类名.静态属性)   # 查看静态属性
# 类名.静态属性 = 456 # 修改静态属性
# print(类名.静态属性)
# 类名.静态属性2 = 'abc'# 增加静态属性
# print(类名.静态属性2)
# # del 类名.静态属性2
# # print(类名.静态属性2)
print(类名.__dict__)   # 类中必要的默认值之外 还记录了程序员在类中定义的所有名字
执行结果:
{'__module__': '__main__', '静态属性': 123, '动态属性': <function 类名.动态属性 at 0x02174540>, '__dict__': <attribute '__dict__' of '类名' objects>, '__weakref__': <attribute '__weakref__' of '类名' objects>, '__doc__': None}
 
 
# 类名可以查看某个方法,但是一般情况下 我们不直接使用类名来调用方法
# print(类名.动态属性)
# 类名.动态属性(1)

# 类的第二个功能是 —— 实例化(创造对象)  类名+()就是实例化对象
class Person:pass

alex = Person()
# 对象 = 类名()
print(alex) # object
print(Person)

执行结果:

<__main__.Person object at 0x01DA15F0>
<class '__main__.Person'>

 

举例1:

class Person:pass

alex = Person()
# 对象 = 类名()
print(alex) # object
print(Person)
# alex name hp dps bag sex
print(alex.__dict__) #空字典
alex.__dict__['name'] = 'alex'
alex.__dict__['sex'] = '不详'
alex.__dict__['hp'] = 250
alex.__dict__['dps'] = 5
alex.__dict__['bag'] = []
print(alex.__dict__)

执行结果:

<__main__.Person object at 0x01DE16F0>
<class '__main__.Person'>
{}
{'name': 'alex', 'sex': '不详', 'hp': 250, 'dps': 5, 'bag': []}

举例2:举例1添加对象那里也可以写成:

alex.name = 'alex'   # 给alex对象添加属性
alex.hp = 250
alex.dps = 5
alex.sex = '不详'
alex.bag = []
print(alex.__dict__)
执行结果:

<__main__.Person object at 0x001FC430>
<class '__main__.Person'>
{}
{'name': 'alex', 'hp': 250, 'dps': 5, 'sex': '不详', 'bag': []}

举例3:

class Person:
def __init__(self,name,hp,dps,sex):
self.name = name
self.hp = hp
self.dps = dps
self.sex = sex
self.bag = []

alex = Person('alex',250,5,'N/A')
print('alex : ',alex)
print(alex.__dict__)
print(alex.name)

总结:
# 为什么会执行init中的内容?
# self到底是什么?
# 实例化的过程
# 类名()就是实例化
# 在实例化的过程中 发生了很多事情是外部看不到的
# 1.创建了一个对象
# 2.自动调用__init__方法
# 这个被创造的对象会被当做实际参数传到__init__方法中,并且传给第一个参数self
# 3.执行init方法中的内容
# 4.自动的把self作为返回值 返回给实例化的地方

 举例4:

# 对象名.方法名 相当于调用一个函数,默认把对象名作为第一个参数传入函数
# 剩余的其他参数根据我的需求可以随意传
class Person:
def __init__(self,name,hp,dps,sex):
self.name = name
self.hp = hp
self.dps = dps
self.sex = sex
self.bag = []
def attack(self,dog):
dog.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, dog.name, dog.name, self.dps, dog.hp))

class Dog:
def __init__(self,name,kind,hp,dps):
self.name = name
self.hp = hp
self.dps = dps
self.kind = kind

def bite(self,person):
person.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, person.name, person.name, self.dps, person.hp))

alex = Person('alex',250,5,'N/A')
ha2 = Dog('哈士奇','藏獒',15000,200)
ha2.bite(alex)

执行结果:

alex : <__main__.Person object at 0x005717B0>
{'name': 'alex', 'hp': 250, 'dps': 5, 'sex': 'N/A', 'bag': []}
alex
哈士奇打了alex,alex掉了200点血,剩余50点血

 

简化的方式:

class Person:
def __init__(self,name,hp,dps,sex):
self.name = name
self.hp = hp
self.dps = dps
self.sex = sex
self.bag = []
def attack(self,dog):
dog.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, dog.name, dog.name, self.dps, dog.hp))

class Dog:
def __init__(self,name,kind,hp,dps):
self.name = name
self.hp = hp
self.dps = dps
self.kind = kind

def bite(self,person):
person.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, person.name, person.name, self.dps, person.hp))
#
alex = Person('alex',250,5,'N/A')
ha2 = Dog('哈士奇','藏獒',15000,200)
# ha2.bite(alex)

# 简化的方式
alex.attack(ha2) 相当于# Person.attack(alex)
alex.attack(ha2) # Person.attack(alex)
print(alex.attack(ha2)) # Person.attack(alex)
print(ha2.hp)
print('alex : ',alex)
print(alex.__dict__)
print(alex.name)

执行结果:

alex : <__main__.Person object at 0x006D17D0>
{'name': 'alex', 'hp': 250, 'dps': 5, 'sex': 'N/A', 'bag': []}
alex
alex打了哈士奇,哈士奇掉了5点血,剩余14995点血
alex打了哈士奇,哈士奇掉了5点血,剩余14990点血
alex打了哈士奇,哈士奇掉了5点血,剩余14985点血
None
14985
alex : <__main__.Person object at 0x006D17B0>
{'name': 'alex', 'hp': 250, 'dps': 5, 'sex': 'N/A', 'bag': []}
alex

 
# 对象名.方法名 相当于调用一个函数,默认把对象名作为第一个参数传入函数
# 剩余的其他参数根据我的需求可以随意传
举例:
# 已知半径 计算圆形的面积和周长 面向对象的思想完成
# 类 圆
# 属性 半径
# 方法 计算面积 计算周长 计算直径
# pi * r ** 2
# 2*pi*r

from math import pi
class Circle:
def __init__(self,r):
self.r = r
def area(self):
return pi * self.r ** 2
def perimeter(self):
return self.r *pi * 2
def r2(self):pass
c1 = Circle(5)
print(c1.area())
print(c1.perimeter())
执行结果:

78.53981633974483
31.41592653589793

 执行顺序:

 

# 每一个角色都有属于自己的 属性 和 方法
# 高可扩展性 可读性 规范性
# 结局不可控

# 类有自己的命名空间
# 对象也有自己的命名空间
# 对象能访问类的命名空间? 可以
# 类不能访问对象的命名空间? 不可以
举例1:
class Person:
COUNTRY = '中国人' # 静态属性
def __init__(self,name):
self.name = name
def eat(self):
print('%s在吃泔水'%self.name)

alex = Person('alex')
egon = Person('egon')

print(alex.name)
print(egon.name)
print(alex.COUNTRY)
alex.eat() # Person.eat(alex)
# alex ---> Person

执行结果:

alex
egon
中国人
alex在吃泔水

 

总结:

(类对象指针通过对象找到对应的类)

# 当一个类在创建一个实例的时候 就产生了一个这个实例和类之间的联系
# 可以通过实例 对象 找到实例化它的类
# 但是 类不能找到它的实例化
 
举例2:
class Person:
COUNTRY = ['中国人'] # 静态属性
Country = '中国人' # 静态属性
def __init__(self,name):
self.name = name
def eat(self):
print('%s在吃泔水'%self.name)
alex = Person('alex')
egon = Person('egon')
print(alex.Country)
alex.Country = '印度人'
print(alex.Country)
print(egon.Country)
print(Person.Country)
执行结果:

中国人
印度人
中国人
中国人

执行的内存变化:

 

 

class Person:
COUNTRY = ['中国人'] # 静态属性
Country = '中国人' # 静态属性
def __init__(self,name):
self.name = name
def eat(self):
print('%s在吃泔水'%self.name)
alex = Person('alex')
egon = Person('egon')
# print(alex.Country)
# alex.Country = '印度人'
# print(alex.Country)
# print(egon.Country)
# print(Person.Country)
alex.COUNTRY[0] = '印度人'
print(alex.COUNTRY)
print(egon.COUNTRY)
print(Person.COUNTRY)
执行结果:

['印度人']
['印度人']
['印度人']

 

 

class Person:
COUNTRY = ['中国人'] # 静态属性
Country = '中国人' # 静态属性
def __init__(self,name):
self.name = name
def eat(self):
print('%s在吃泔水'%self.name)
alex = Person('alex')
egon = Person('egon')
# print(alex.Country)
# alex.Country = '印度人'
# print(alex.Country)
# print(egon.Country)
# print(Person.Country)
# alex.COUNTRY[0] = '印度人'
# print(alex.COUNTRY)
# print(egon.COUNTRY)
# print(Person.COUNTRY)
alex.COUNTRY = ['印度人']
print(egon.COUNTRY)
print(Person.COUNTRY)
执行结果:

['中国人']
['中国人']

 

 

 

# 在访问变量的时候,都先使用自己命名空间中的,如果自己的空间中没有,再到类的空间中去找
# 在使用对象修改静态变量的过程中,相当于在自己的空间中创建了一个新的变量
# 在类的静态变量的操作中 应该使用类名来直接进行操作 就不会出现乌龙问题


举例:
# 创建一个类 能够自动计算这个类有创建了多少个实例
class Foo:
count = 0
def __init__(self):
Foo.count += 1

f1 = Foo()
print(Foo.count)
[Foo() for i in range(10)]
print(Foo.count)
执行结果:
1
11
 

 2、组合

class Person:
def __init__(self,name,sex,hp,dps):
self.name = name
self.hp = hp
self.dps = dps
self.sex = sex
self.bag = []
def attack(self,dog):
dog.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, dog.name, dog.name, self.dps, dog.hp))

class Dog:
def __init__(self,name,kind,hp,dps):
self.name = name
self.hp = hp
self.dps = dps
self.kind = kind

def bite(self,person):
person.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, person.name, person.name, self.dps, person.hp))

class Weapon:
def __init__(self,name,price,dps):
self.name = name
self.price = price
self.dps = dps
def kill(self,dog):
dog.hp -= self.dps

alex = Person('alex','N/A',250,5)
ha2 = Dog('哈士奇','藏獒',15000,200)
# print(alex.name)
roubaozi = Weapon('肉包子',600000,10000)
alex.money = 1000000
if alex.money >= roubaozi.price:
alex.weapon = roubaozi
alex.weapon.kill(ha2)
print(ha2.hp)

执行结果:

5000

# 基础数据类型 都是类
# 'alex' : str的对象
# alex.name = 'alex'
# alex.name.startswith('a')

#给alex装备一个武器

from math import pi
class Circle:
def __init__(self,r):
self.r = r
def area(self):
return pi * self.r ** 2
def perimeter(self):
return self.r *pi * 2

class Ring:
def __init__(self,outside_r,inside_r):
self.out_circle = Circle(outside_r)
self.in_circle = Circle(inside_r)
def area(self):
return self.out_circle.area() - self.in_circle.area()
def perimeter(self):
return self.out_circle.perimeter() + self.in_circle.perimeter()

r = Ring(10,5)
print(r.area())
print(r.perimeter())
执行结果:

235.61944901923448
94.24777960769379

# 组合 是描述了 一种 什么有什么的关系  圆环有圆   人有武器
3、继承
# 为什么会有继承?  解决代码的冗余问题
class Person:
def __init__(self,name,hp,dps,sex):
self.name = name
self.hp = hp
self.dps = dps
self.sex = sex
self.bag = []
def attack(self,dog):
dog.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, dog.name, dog.name, self.dps, dog.hp))

class Dog:
def __init__(self,name,kind,hp,dps):
self.name = name
self.hp = hp
self.dps = dps
self.kind = kind

def bite(self,person):
person.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, person.name, person.name, self.dps, person.hp))

class Parent:pass
class Son(Parent):pass

# 单继承
# Son类 继承 Parent类
# 父类 基类 超类 —— Parent类
# 子类 派生类 —— Son类
# 多继承
class Parent1:pass
class Parent2:pass
#
class Son(Parent1,Parent2):pass
class Animal:
def __init__(self, name, hp, dps):
self.name = name
self.hp = hp
self.dps = dps
def eat(self):
print('%s吃药回血了'%self.name)
class Person(Animal):
def __init__(self, name, hp, dps,sex):
super().__init__(name,hp,dps) # Animal.__init__(self,name,hp,dps)
self.sex = sex # 派生属性
def attack(self,dog):
dog.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, dog.name, dog.name, self.dps, dog.hp))

class Dog(Animal):
def __init__(self,name,hp,dps,kind):
super().__init__(name, hp, dps) # Animal.__init__(self, name, hp, dps)
self.kind = kind # 派生属性
def bite(self,person):
person.hp -= self.dps
print('%s打了%s,%s掉了%s点血,剩余%s点血' % (self.name, person.name, person.name, self.dps, person.hp))
alex = Person('alex',250,5,'N/A')
ha2 = Dog('哈士奇',15000,200,'藏獒')
print(alex.__dict__)
print(ha2.__dict__)
ha2.eat()
alex.eat()
ha2.bite(alex)
alex.attack(ha2)
执行结果:

{'name': 'alex', 'hp': 250, 'dps': 5, 'sex': 'N/A'}
{'name': '哈士奇', 'hp': 15000, 'dps': 200, 'kind': '藏獒'}
哈士奇吃药回血了
alex吃药回血了
哈士奇打了alex,alex掉了200点血,剩余50点血
alex打了哈士奇,哈士奇掉了5点血,剩余14995点血

 

 

 

 

# 对象的内存空间 - 创建这个对象的类的内存空间 - 父类的
class Foo:
def __init__(self):
self.func()
def func(self):
print('in Foo')

class Son(Foo):
def func(self):
print('in Son')
Son()
执行结果:
in Son

 



4、多继承
# python两种类
# 经典类 py3已经灭绝了 在python2里还存在,在py2中只要程序员不主动继承object,这个类就是经典类 —— 深度优先
# 新式类 python3所有的类都是新式类,所有的新式类都继承自object —— 在多继承中遵循广度优先算法
# 钻石继承问题
# python3

举例1:
class A:
def f(self):
print('in A')

class B(A):
pass
def f(self):
print('in B')

class C(A):
pass
def f(self):
print('in C')


class D(B,C):
pass
def f(self):
print('in D')

class E(C):
pass
def f(self):
print('in B')

class F(D,E):
pass
def f(self):
print('in C')

d = D()
d.f()

print(F.mro())
执行结果:

in D
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

 

 

 

举例2:

class A:
def f(self):
print('in A')

class B(A):
def f(self):
print('in B')
super().f()

class C(A):
pass
def f(self):
print('in C')
super().f()

class D(B,C):
def f(self):
print('in D')
super().f()

d = D()
d.f()
执行结果:

in D
in B
in C
in A

# super和找父类这件事是两回事
# 在单继承中 super就是找父类
# 在多级承中 super的轨迹 是根据整个模型的起始点而展开的一个广度优先顺序 遵循mro规则



补充:深度优先算法

 

 
5、多态
# 在python中处处都是多态

# 多态
# java
class Person():pass
#
alex = Person()
print(type(alex)) # Person
print(type('123'))
print(type(123))
执行结果:

<class '__main__.Person'>
<class 'str'>
<class 'int'>

 

# 多态
# java
# class Person():pass
# # #
# alex = Person()
# print(type(alex)) # Person
# print(type('123'))
# print(type(123))
#
# def func(Dog person):
# pass
#
# func(ha2)

# class Animal:
# pass
#
# class Dog(Animal):pass
# class Person(Animal):pass
#
#
# def func(a):
# pass
#
# func(alex)
# func(ha2)

作业:http://www.cnblogs.com/Eva-J/articles/7747946.html

 

 
 
 















转载于:https://www.cnblogs.com/lucky-penguin/p/9043865.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值