zoukankan      html  css  js  c++  java
  • python 面向对象

    面向过程 和 面向对象

    面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤
    优点:极大降低写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
    缺点是:一套代码解决一个问题,牵一发而动全身。
    应用:一旦完成基本很少改变的场景,Linux內核,git等。

    面向对象的程序设计的核心是对象(上帝式思维)。
    优点:对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
    缺点:可控性差,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。
    应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等。

    类和对象
    python中一切皆为对象,类型的本质就是类。

    >>> dict #类型dict就是类dict
    <class 'dict'>
    >>> d={name:'eva'} #实例化
    >>> d.pop('name') #向d发一条消息,执行d的方法pop    'eva'

    在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象是则是这一类事物中具体的一个。

    def functionName(args):
         '函数文档字符串'
          函数体 
    
    
    
    
    '''
    class 类名:
        '类的文档字符串'
        类体
    '''
    
    #我们创建一个类
    class Data:
        pass
    
    
    
    
    
    class Person:   #定义一个人类
        role = 'person'  #人的角色属性都是人
        def walk(self):  #人都可以走路,也就是有一个走路方法,也叫动态属性
            print("person is walking...")
    类的声明
    对象 = 类名()
    过程:
        类名() 首先 会创造出一个对象,创建了一个self变量
        调用init方法,类名括号里的参数会被这里接收
        执行init方法
        返回self
    对象能做的事:
        查看属性
        调用方法
        __dict__ 对于对象的增删改查操作都可以通过字典的语法进行
    类名能做的事:
        实例化
        调用方法 : 只不过要自己传递self参数
        调用类中的属性,也就是调用静态属性
        __dict__ 对于类中的名字只能看 不能操作

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

    class Person:                 # 类名
        country = 'China'         # 创造了一个只要是这个类就一定有的属性
                                   # 类属性 静态属性
        def __init__(self,*args):  # 初始化方法,self是对象,是一个必须传的参数
            # self就是一个可以存储很多属性的大字典
            self.name = args[0]   # 往字典里添加属性的方式发生了一些变化
            self.hp = args[1]
            self.aggr = args[2]
            self.sex = args[3]
    
        def walk(self,n):         # 方法,一般情况下必须传self参数,且必须写在第一个
                                  # 后面还可以传其他参数,是自由的
            print('%s走走走,走了%s步'%(self.name,n))
    
    # print(Person.country)        # 类名 可以查看类中的属性,不需要实例化就可以查看
    alex = Person('狗剩儿',100,1,'不详')  # 类名还可以实例化对象,alex对象   # 实例化
    # print(alex.__dict__) # 查看所有属性
    print(alex.name)  # 查看属性值
    # print(alex.hp)  # 查看属性值
    alex.walk(5)    # Person.walk(alex,5)  # 调用方法 类名.方法名(对象名)
    一:我们定义的类的属性到底存到哪里了?有两种方式查看
    dir(类名):查出的是一个名字列表
    类名.__dict__:查出的是一个字典,key为属性名,value为属性值
    
    二:特殊的类属性
    类名.__name__# 类的名字(字符串)
    类名.__doc__# 类的文档字符串
    类名.__base__# 类的第一个父类(在讲继承时会讲)
    类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
    类名.__dict__# 类的字典属性
    类名.__module__# 类定义所在的模块
    类名.__class__# 实例对应的类(仅新式类中)
    类属性的补充

    面向对象小结——定义及调用的固定模式

    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岁,男,最爱大保健
    
    
    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def ss(self):
            print('%s,%s岁,%s,%s'%(self.name,self.age,self.sex,'上山去砍柴'))
        def kc(self):
            print('%s,%s岁,%s,%s'%(self.name, self.age, self.sex, '开车去东北'))
        def maj(self):
            print('%s,%s岁,%s,%s'%(self.name, self.age, self.sex, '最爱大保健'))
    p1 = Person('小明',10,'')
    p2 = Person('老李',90,'')
    print(p1.__dict__)
    p1.ss()
    p1.kc()
    p1.maj()
    p2.ss()
    p2.kc()
    p2.maj()
    练习
    包 —— __init__
    import package —— 类的实例化的过程
    import time
    time.time()
    包也是类

    对象之间的交互

    class Dog:
        def __init__(self,name,blood,aggr,kind):
            self.name = name
            self.hp = blood
            self.aggr = aggr
            self.kind = kind
        def bite(self,person):
            # 狗咬人,人掉血
            person.blood -= self.aggr
    
    class 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.hp -= self.aggr
            if dog.hp <= 0:
                print('%s打了%s,%s被打死了,扑街~~~'%(self.name,dog.name,dog.name))
            else:
                print('%s打了%s,掉了%s血'%(self.name,dog.name,self.aggr))
    
    jin = Dog('金老板',100,20,'teddy')
    alex = Person('alex',999,998,'不详')
    jin.bite(alex)   # Dog.bite(jin,alex)
    print(alex.blood)
    alex.attack(jin)  # Person.attack(alex,jin)
    print(jin.hp)
    通过例子来了解
    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) #打印圆面积和周长
    View Code

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

    创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性

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

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

      静态属性就是直接在类中定义的变量,类的数据属性是共享给所有对象的

      动态属性就是定义在类中的方法,类的动态属性是绑定到所有对象的

    类里的名字有 类变量(静态属性量)+ 方法名(动态属性)
    对象里的名字 对象属性
    对象 —— > 类
    对象找名字 : 先找自己的 找类的 再找不到就报错
    对象修改静态属性的值
        对于不可变数据类型来说,类变量最好用类名操作
              (类可对其直接更改,对象对其直接更改则类中不变,在对象自己的空间中生成一个新属性)
        对于可变数据类型来说,对象名的修改是共享的,重新赋值是独立的
              (对列表之类,对象不可改变列表,但对列表内元素可以修改)
    创建一个类,每实例化一个对象就计数
    最终所有的对象共享这个数据
    class Foo:
        count = 0
        def __init__(self):
            Foo.count += 1
    
    f1 = Foo()
    f2 = Foo()
    print(f1.count)
    print(f2.count)
    f3 = Foo()
    print(f1.count)
    示例

    认识绑定关系

    class Foo:
        def func(self):
            print('func')
        def fun1(self):
            pass
    f1 = Foo()
    print(Foo.func)
    print(f1.func)
    print(f1.fun1)
    <bound method Foo.func of f1>
    f1.func 时,形成绑定关系,f1成为Foo里面的self,操作才能进行。
    View Code

    面向对象的组合用法

    软件重用的重要方式除了继承之外还有另外一种方式,即:组合

    组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

    (什么时候用组合:什么有什么的时候)当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好

    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,njd,price):
            self.name = name
            self.aggr = aggr
            self.njd = njd
            self.price = price
    
        def hand18(self,person):
            if self.njd > 0:
                person.hp -= self.aggr * 2
                self.njd -= 1
    
    alex = Person('alex',0.5,100,'不详')
    jin = Dog('金老板',100,500,'teddy')
    w = Weapon('打狗棒',100,3,998)
    # alex装备打狗棒
    alex.money += 1000
    alex.get_weapon(w)
    print(alex.weapon)
    print(alex.aggr)
    alex.attack(jin)
    print(jin.hp)
    alex.weapon.hand18(jin)
    print(jin.hp)
    例子1 人狗大战

    圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。
    这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用。

    from math import pi
    class Circle:
        def __init__(self,r):
            self.r = r
        def area(self):
            return self.r**2 * pi
        def perimeter(self):
            return 2*pi*self.r
    
    class Ring:
        def __init__(self,outside_r,inside_r):
            self.outside_c = Circle(outside_r)
            self.inside_c = Circle(inside_r)
        def area(self):
            return self.outside_c.area() - self.inside_c.area()
        def perimeter(self):
            return self.outside_c.perimeter()+self.inside_c.perimeter()
    
    # ring = Ring(20,10)
    # print(ring.area())
    # print(ring.perimeter())
    View Code

    用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教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)
    ''' 
    运行结果: 
    27 
    python 28000 4 months 
    '''
    View Code

     总结: 当类的对象作为 值 存在时,就是 组合。

  • 相关阅读:
    RabbitMQ 安装
    字符串转换
    sqlserver 远程链接
    力软框架 接口映射的时候不能修改添加接口原因
    json串处理2
    版本比较,数据库存储
    各种分页方法推荐
    生成数据库编号重复问题
    从统计局抓取2016年最新的全国区县数据!!
    “集群和负载均衡”等的通俗解释
  • 原文地址:https://www.cnblogs.com/olivia2018/p/8289550.html
Copyright © 2011-2022 走看看