Python - - 面向对象 - - 初始面向对象

目录

  • 面向过程vs面向对象
  • 初识面向对象
    • 类的相关知识
    • 对象的相关知识
    • 对象之间的交互
    • 类命名空间与对象、实例的命名空间
    • 类的组合用法
    • 初识面向对象小结
  • 面向对象的三大特性
    • 继承
    • 多态
    • 封装
  • 面向对象的更多说明
    • 面向对象的软件开发
    • 几个概念的说明
    • 面向对象常用术语

1,面向过程vs面向对象

1.1 面向过程

  • 面向过程:核心就是过程(流水线式思维),过程即解决问题的步骤,需要你自己去一步一步的执行完善
    • 优点是:将复杂的问题流程化,进而简单化,极大的降低了写程序的复杂度,只需要顺着执行的步骤,堆叠代码即可
    • 缺点是:扩展性差,一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身

1.2 面向对象

  • 面向对象:面向对象是将事物高度抽象化,必须先建立抽象模型,之后直接使用模型
    • 优点是:可扩展性高,解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中。
    • 缺点是:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。
  • 面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

1.3 名词

类:具有相同特征的一类事物

对象/实例:具体的某一个事物

实例化:类——>对象的过程

2, 初识面向对象

  • python中一切皆为对象,类型的本质就是类
print(dict)        #类型dict就是类dic
d = dict(name = "abc")    #实例化
print(d)
print(d.pop("name"))       #向d发一条消息,执行d的方法pop

# 结果呈现
<class 'dict'>
{'name': 'abc'}
abc
  • 在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象是则是这一类事物中具体的一个。

2.1 类的相关知识

2.1.1 初始类

  • 声明函数
def functionName(args):
     '函数文档字符串'
      函数体 
  • 声明类
'''
class 类名:
    '类的文档字符串'
    类体
'''

#我们创建一个类
class Data:
    pass
class Person:   #定义一个人类
    role = 'person'  #人的角色属性都是人
    def walk(self):  #人都可以走路,也就是有一个走路方法,也叫动态属性
        print("person is walking...")

2.1.2 类有两种作用:属性引用和实例化

  • 属性引用(类名.属性)
class Person:   #定义一个人类
    role = 'person'  #人的角色属性都是人
    def walk(self):  #人都可以走路,也就是有一个走路方法
        print("person is walking...")


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

# 结果呈现
person
<function Person.walk at 0x000000DCE5772BF8>
  • 实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
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)  #引用人的走路方法,注意,这里不是在调用
  • 实例化的过程就是类——>对象的过程
  • 原本我们只有一个Person类,在这个过程中,产生了一个egg对象,有自己具体的名字、攻击力和生命值。
  • 语法:对象名 = 类名(参数)
egg = Person('egon')  #类名()就等于在执行Person.__init__()
#执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。
  • 查看属性&调用方法
print(egg.name)     #查看属性直接 对象名.属性名
print(egg.walk())   #调用方法,对象名.方法名()
  • self:在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给他起个别的名字,但是正常人都不会这么做。

  • 类属性的补充

一:我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值

二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)

2.2 对象的相关知识

# 人狗大战
class Person:    # 定义一个人类 
    role = "person"    # 人的角色属性都是人
    def __init__(self, name, blood, aggr, sex):
        self.name = name    # 角色的名称
        self.blood = blood    # 角色的血量
        self.aggr = aggr        # 角色的攻击力
        self.sex = sex            # 角色的性别

    def attack(self, dog):        # 定义技能函数
        # 人可以攻击狗,这里的狗也是一个对象。
        # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
        dog.blood -= self.aggr
        if dog.blood <= 0:
            print("%s 打了 %s, %s 被打死了,扑街~~~" % (self.name, dog.name, dog.name))
        else:
            print("%s 打了 %s, %s 掉了 %d 的血~~~" % (self.name, dog.name, dog.name, self.aggr))
  • 对象是关于类而实际存在的一个例子,即实例
  • 对象/实例只有一种作用:属性引用
ming = Person("小明", 100, 10, "None")
print(ming.name)
print(ming.blood)
print(ming.aggr)
print(ming.sex)

# 结果呈现
小明
100
10
None
  • 当然了,你也可以引用一个方法,因为方法也是一个属性,只不过是一个类似函数的属性,我们也管它叫动态属性。
  • 引用动态属性并不是执行这个方法,要想调用方法和调用函数是一样的,都需要在后面加上括号
print(ming.attack)
  • 面向对象小结——定义及调用的固定模式
class 类名:
    def __init__(self,参数1,参数2):
        self.对象的属性1 = 参数1
        self.对象的属性2 = 参数2

    def 方法名(self):pass

    def 方法名2(self):pass

对象名 = 类名(1,2)  #对象就是实例,代表一个具体的东西
                  #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
                  #括号里传参数,参数不需要传self,其他与init中的形参一一对应
                  #结果返回一个对象
对象名.对象的属性1   #查看对象的属性,直接用 对象名.属性名 即可
对象名.方法名()     #调用类中的方法,直接用 对象名.方法名() 即可
  • 练习一:在终端输出如下信息
小明,10岁,男,上山去砍柴
小明,10岁,男,开车去东北
小明,10岁,男,最爱大保健
老李,90岁,男,上山去砍柴
老李,90岁,男,开车去东北
老李,90岁,男,最爱大保健
老张…
def shangshan():
    print("%s, %s 岁, %s, 上山去砍柴")

def drive():
    print("%s, %s 岁, %s, 开车去东北")

def favor():
    print("%s, %s 岁, %s, 最爱大保健")


class Person:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def shangshan(self):
        print("%s, %s 岁, %s, 上山去砍柴" % (self.name, self.age, self.sex))

    def drive(self):
        print("%s, %s 岁, %s, 开车去东北" % (self.name, self.age, self.sex))

    def favor(self):
        print("%s, %s 岁, %s, 最爱大保健" % (self.name, self.age, self.sex))

ming = Person("小明", "10", "男")
ming.shangshan()
ming.drive()
ming.favor()
zhang = Person("老张", "100", "男")
zhang.shangshan()
zhang.drive()
zhang.favor()

# 结果呈现
小明, 10 岁, 男, 上山去砍柴
小明, 10 岁, 男, 开车去东北
小明, 10 岁, 男, 最爱大保健
老张, 100 岁, 男, 上山去砍柴
老张, 100 岁, 男, 开车去东北
老张, 100 岁, 男, 最爱大保健
  • 非常明显的处理一类事物,这些事物都具有相似的属性和功能
  • 当有几个函数 需要反反复复传入相同的参数的时候,就可以 考虑面向对象
  • 这些参数都是对象的属性

2.3 对象之间的交互

# 创建一个狗类
class Dog:     # 定义一个狗类
    role = 'dog'  # 狗的角色属性都是狗
    def __init__(self, name, blood, aggr, kind):
        self.name = name    # 狗的名称
        self.blood = blood    # 狗的血量
        self.aggr = aggr        # 狗的伤害
        self.kind = kind        # 狗的类型

    def bite(self, person):
        # 狗可以咬人,这里的狗也是一个对象。
        # 狗咬人,那么人的生命值就会根据狗的攻击力而下降
        person.blood -= self.aggr
        if person.blood <= 0:
            print("%s 咬了 %s, %s 被咬死了,扑街~~~" % (self.name, person.name, person.name))
        else:
            print("%s 咬了 %s, %s 掉了 %d 的血~~~" % (self.name, person.name, person.name, self.aggr))
  • 实例化一只实实在在的二哈
ha2 = Dog('二愣子',10,1000,'哈士奇')
ming = Person("小明", 100, 10, "None")
print(ha2.blood)         #看看ha2的生命值
ming.attack(ha2)               #ming打了ha2一下
print(ha2.blood)         #ha2掉了10点血

# 结果呈现
10
小明 打了 二愣子, 二愣子 被打死了,扑街~~~
0
  • 完整代码
class Person:    # 定义一个人类 
    role = "person"    # 人的角色属性都是人
    def __init__(self, name, blood, aggr, sex):
        self.name = name    # 角色的名称
        self.blood = blood    # 角色的血量
        self.aggr = aggr        # 角色的攻击力
        self.sex = sex            # 角色的性别

    def attack(self, dog):        # 定义技能函数
        # 人可以攻击狗,这里的狗也是一个对象。
        # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
        dog.blood -= self.aggr
        if dog.blood <= 0:
            print("%s 打了 %s, %s 被打死了,扑街~~~" % (self.name, dog.name, dog.name))
        else:
            print("%s 打了 %s, %s 掉了 %d 的血~~~" % (self.name, dog.name, dog.name, self.aggr))

class Dog:     # 定义一个狗类
    role = 'dog'  # 狗的角色属性都是狗
    def __init__(self, name, blood, aggr, kind):
        self.name = name    # 狗的名称
        self.blood = blood    # 狗的血量
        self.aggr = aggr        # 狗的伤害
        self.kind = kind        # 狗的类型

    def bite(self, person):
        # 狗可以咬人,这里的狗也是一个对象。
        # 狗咬人,那么人的生命值就会根据狗的攻击力而下降
        person.blood -= self.aggr
        if person.blood <= 0:
            print("%s 咬了 %s, %s 被咬死了,扑街~~~" % (self.name, person.name, person.name))
        else:
            print("%s 咬了 %s, %s 掉了 %d 的血~~~" % (self.name, person.name, person.name, self.aggr))

ha2 = Dog('二愣子',10,1000,'哈士奇')
ming = Person("小明", 100, 10, "None")
print(ha2.blood)         #看看ha2的生命值
ming.attack(ha2)               #ming打了ha2一下
print(ha2.blood)         #ha2掉了10点血

# 结果呈现
10
小明 打了 二愣子, 二愣子 被打死了,扑街~~~
0
  • circle 属性 半径, 两个方法:求周长和面积 # 2pir pir**2
from math import pi

class Circle:
    '''
    定义了一个圆形类;
    提供计算面积(area)和周长(perimeter)的方法
    '''
    def __init__(self,radius):
        self.radius = radius

    def area(self):
         return pi * self.radius * self.radius

    def perimeter(self):
        return 2 * pi *self.radius


circle =  Circle(10) #实例化一个圆
area1 = circle.area() #计算圆面积
per1 = circle.perimeter() #计算圆周长
print(area1,per1) #打印圆面积和周长

# 结果呈现
314.1592653589793 62.83185307179586

2.4 类命名空间与对象、实例的命名空间

  • 创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性
  • 而类有两种属性:静态属性和动态属性
    • 静态属性就是直接在类中定义的变量
    • 动态属性就是定义在类中的方法
  • 其中类的数据属性是共享给所有对象的
>>>id(egg.role)
4341594072
>>>id(Person.role)
4341594072
  • 而类的动态属性是绑定到所有对象的
>>>egg.attack
<bound method Person.attack of <__main__.Person object at 0x101285860>>
>>>Person.attack
<function Person.attack at 0x10127abf8> 
  • 创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
  • 在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

2.5 面向对象的组合用法

  • 软件重用的重要方式除了继承之外还有另外一种方式,即:组合
  • 组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
  • 组合: 一个对象的属性值是另外一个类的对象
class Dog:
    def __init__(self, name, aggr , hp, kind):
        self.name = name
        self.aggr = aggr
        self.hp = hp
        self.kind = kind

    def bite(self, person):
        person.hp -= self.aggr


class Person:
    def __init__(self, name, aggr, hp, sex):
        self.name = name
        self.aggr = aggr
        self.hp = hp
        self.sex = sex
        self.money = 0

    def attack(self, dog):
        dog.hp -= self.aggr

    def get_weapon(self, weapon):
        if self.money >= weapon.price:
            self.money -= weapon.price
            self.weapon = weapon            # 给角色绑定武器
            self.aggr += weapon.aggr
        else:
            print("余额不足,请充值")


class Weapon:        # 定义武器
    def __init__(self, name, aggr, durability, price):
        self.name = name
        self.aggr = aggr
        self.durability = durability
        self.price = price

    def hand18(self, person):        # 降龙十八掌
        if self.durability > 0:
            person.hp -= self.aggr * 2
            self.durability -= 1

ming = Person("小明", 0.5, 100, "不详")
jin = Dog("金毛", 100, 500, "不详")
w = Weapon("打狗棒", 100 , 3, 998)

# ming 装备打狗棒
ming.money += 1000
ming.get_weapon(w)
print(ming.weapon)
print(ming.aggr)
ming.attack(jin)
print(jin.hp)
ming.weapon.hand18(jin)
print(jin.hp)

# 结果呈现
<__main__.Weapon object at 0x000000457A50EB00>
100.5
399.5
199.5
  • 圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。
  • 这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用
from math import pi

class Circle:
    '''
    定义了一个圆形类;
    提供计算面积(area)和周长(perimeter)的方法
    '''
    def __init__(self,radius):
        self.radius = radius

    def area(self):
         return pi * self.radius * self.radius

    def perimeter(self):
        return 2 * pi *self.radius


circle =  Circle(10) #实例化一个圆
area1 = circle.area() #计算圆面积
per1 = circle.perimeter() #计算圆周长
print(area1,per1) #打印圆面积和周长

class Ring:
    '''
    定义了一个圆环类
    提供圆环的面积和周长的方法
    '''
    def __init__(self,radius_outside,radius_inside):
        self.outsid_circle = Circle(radius_outside)
        self.inside_circle = Circle(radius_inside)

    def area(self):
        return self.outsid_circle.area() - self.inside_circle.area()

    def perimeter(self):
        return  self.outsid_circle.perimeter() + self.inside_circle.perimeter()


ring = Ring(10,5) #实例化一个环形
print(ring.perimeter()) #计算环形的周长
print(ring.area()) #计算环形的面积

# 结果呈现
314.1592653589793 62.83185307179586
94.24777960769379
235.61944901923448
  • 用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程
class BirthDate:
    def __init__(self,year,month,day):
        self.year=year
        self.month=month
        self.day=day

class Couse:
    def __init__(self,name,price,period):
        self.name=name
        self.price=price
        self.period=period

class Teacher:
    def __init__(self,name,gender,birth,course):
        self.name=name 
        self.gender=gender
        self.birth=birth
        self.course=course
    def teach(self): 
        print('teaching')

p1=Teacher('egon','male', 
            BirthDate('1995','1','27'), 
            Couse('python','28000','4 months')
           ) 

print(p1.birth.year,p1.birth.month,p1.birth.day) 

print(p1.course.name,p1.course.price,p1.course.period)

# 结果呈现
1995 1 27
python 28000 4 months
  • 当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好

2.6 初识面向对象小结

# 定义一个人类

class Person:  # 定义一个人类
    role = 'person'  # 人的角色属性都是人

    def __init__(self, name, aggressivity, life_value, money):
        self.name = name  # 每一个角色都有自己的昵称;
        self.aggressivity = aggressivity  # 每一个角色都有自己的攻击力;
        self.life_value = life_value  # 每一个角色都有自己的生命值;
        self.money = money

    def attack(self,dog):
        # 人可以攻击狗,这里的狗也是一个对象。
        # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
        dog.life_value -= self.aggressivity
 

# 定义一个狗类

class Dog:  # 定义一个狗类
    role = 'dog'  # 狗的角色属性都是狗

    def __init__(self, name, breed, aggressivity, life_value):
        self.name = name  # 每一只狗都有自己的昵称;
        self.breed = breed  # 每一只狗都有自己的品种;
        self.aggressivity = aggressivity  # 每一只狗都有自己的攻击力;
        self.life_value = life_value  # 每一只狗都有自己的生命值;

    def bite(self,people):
        # 狗可以咬人,这里的狗也是一个对象。
        # 狗咬人,那么人的生命值就会根据狗的攻击力而下降
        people.life_value -= self.aggressivity 

# 创建一个新的兵器类。

class Weapon:
    def __init__(self,name, price, aggrev, life_value):
        self.name = name
        self.price = price
        self.aggrev = aggrev
        self.life_value = life_value

    def update(self, obj):  #obj就是要带这个装备的人
        obj.money -= self.price  # 用这个武器的人花钱买所以对应的钱要减少
        obj.aggressivity += self.aggrev  # 带上这个装备可以让人增加攻击
        obj.life_value += self.life_value  # 带上这个装备可以让人增加生命值

    def prick(self, obj):  # 这是该装备的主动技能,扎死对方
        obj.life_value -= 500  # 假设攻击力是500

# 测试交互 

lance = Weapon('长矛',200,6,100)
egg = Person('egon',10,1000,600)  #创造了一个实实在在的人egg
ha2 = Dog('二愣子','哈士奇',10,1000)  #创造了一只实实在在的狗ha2

#egg独自力战"二愣子"深感吃力,决定穷毕生积蓄买一把武器
if egg.money > lance.price: #如果egg的钱比装备的价格多,可以买一把长矛
    lance.update(egg) #egg花钱买了一个长矛防身,且自身属性得到了提高
    egg.weapon = lance #egg装备上了长矛

print(egg.money,egg.life_value,egg.aggressivity)

print(ha2.life_value)
egg.attack(ha2)   #egg打了ha2一下
print(ha2.life_value)
egg.weapon.prick(ha2) #发动武器技能
print(ha2.life_value) #ha2不敌狡猾的人类用武器取胜,血槽空了一半
  • 按照这种思路一点一点的设计类和对象,最终你完全可以实现一个对战类游戏。
  • 角色的抽象 ,创建类,创建角色(实例化),操作这些实例

3,面向对象的三大特性

猜你喜欢

转载自www.cnblogs.com/xiaoqshuo/p/9756988.html
今日推荐