zoukankan      html  css  js  c++  java
  • 面向对象--初始面向对象

    一、初始面向对象

    1.面向过程

         核心:过程(流水线式思维)

         优点:极大的降低了写程序的复杂度,只需顺着要执行的步骤,堆叠代码就可

          缺点:代码牵一发而动全身

    2.面向对象:

          核心:对象

           对象:特征(变量)和技能(函数)的结合体

          优点:可扩展强,基于面向对象设计游戏

          缺点:可控性差,一旦建立就是对象和对象之间的交互,我们无法预测,一个很好的例子就是打游戏

    3.初始类和对象
              python中一切皆对象,类型的本质就是类

             在Python中,用变量表示特征,用函数表示技能,所以具有相同特征和技能的一类事物就是‘ 类’,(一系列对象共同的特征与技能的结合体)

             

    class Chinese:#会执行里面的代码  特征与技能
        country = 'China'
    #技能
        def __init__(self,name,color,age): #__init__初始化,只干初始化的活
             # __init__方法一定不能有返回值
             # if not isinstance(name,str):
             #   raise TypeError#触发异常 认为的造问题
    
               self.name=name
               self.color=color
               self.age=age
        def talk(self):
                print('is talking')
        def eat(self):
                print('is eating')
    
        def sleep(self):
                print('is sleeping')
        #程序中的对象
    p1=Chinese('lb','red',21) #第一个对象
    p2=Chinese('xiaoma','green',21) #实例化 触发__init__的执行
    #p1:可以称为Chiese类的一个实例或对象
    print(p1.name,p1.color,p1.age)
    print(p2.name,p2.color,p2.age)
    类的举例

    4.对象相关知识的总结

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

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

           括号里传参数,不许要传self,其他与__init__中的形参一一对应

           结果返回一个对象

            查看对象的属性,直接用对象名,属性名即可

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

    5.对象之间的交互     

    用这个例子具体实现

      6.面向对象的组合

          

    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)
    ''' 
    运行结果: 
    1 27 
    python 28000 4 months 
    '''
    复制代码
    组合举例一
    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()) #计算环形的面积
    组合举例二圆环

    二、面向对象三大特征

       1.继承

           继承是一种创建新类的方式,在Python中新建的类可以继承一个或多个类

             父类:又称为基类或超类
             新建的类:又称为派生类或子类

             类的继承分为:单继承和多继承

        

    class Animal:  #父类,基类,超类
        def __init__(self, name, life_value, aggr):
            self.name = name
            self.life_value = life_value
            self.aggr = aggr
        def eat(self):
            self.life_value+=10
    class Person(Animal):#子类、派生类,会继承父类所有的方法
        def __init__(self,name, life_value, aggr,money):
            super().__init__(name, life_value, aggr)
            self.money=money
        def attrack(self,enemy):#人的派生方法
           enemy.life_value-=self.aggr
    class Dog(Animal):
        def __init__(self,breed,name,life_value,aggr):
           #Animal.__init__(self,name,life_value,aggr)#让子类执行父类的方法,就是父类名,方法名(参数),连self也得传
         super().__init__(name, life_value, aggr)
         super(Dog,self).__init__(name,life_value,aggr) #super关键字,新式类中的
         self.breed=breed
    
        def bite(self,peron):#狗的派生方法
            peron.life_value-=self.aggr
        def eat(self): #父类方法的重写
            super().eat() #在实现父类的方法的基础上实现自己的一些方法
            print('dog is eating')
    
    h2=Dog('牛头梗','旺财',1000,500)
    # h2=Dog('旺财',1000,500,)
    h2.eat()
    print(h2.life_value)
    super(Dog,h2).eat()#调用父类的
    print(h2.life_value)
    egg=Person('egon',200,1500,400)
    print('人的攻击力',egg.aggr)
    print('狗的攻击力',h2.aggr)
    egg.eat()
    print('吃了回血丸的人',egg.life_value)
    h2.eat()
    print('吃了回血丸的狗',h2.life_value)
    
    print('之前',egg.life_value)
    h2.bite(egg)
    print('之后',egg.life_value)
    继承举例
    继承总结:
    继承语法:class类名
    想在子类中实现调用父类的方法
    在类内----super(子类名,self)
    在外面----super(子类名,对象名).方法名(0)
    如果不指定继承的父类,默认继承object
    子类可以使用父类的所有属性和方法
    如果子类有自己的方法就执行自己的
    如果是子类没有的方法名就执行自己父类的
    继承 大范围到小范围
    抽象:小范围到大范围
    派生: 父类的基础上又产生了子类----派生类
    派生方法:父类里没有的,但子类有的
    派生属性:父类没有的,子类有
    方法的重新;父类有的方法,在子类里重新实现
    减少代码重用性
    提高代码可读性
    规范编程模式
    2.接口类和抽象类
    多继承:我们应该尽量避免多继承问题
    接口类
    from abc import ABCMeta,abstractclassmethod
    class Payment(metaclass=ABCMeta):
        #接口类,不能被实例化,规范所有支付功能必须实现pay方法
        @abstractclassmethod
        def pay(self,money):
            pass
    class Wxpay(Payment):#微信支付功能
        def pay(self,money):
            print('微信支付了%s元'%money)
    class QQpay(Payment):
        def pay(self,money):
            print('QQ支付了%s元'%money)
    #接口归一化,简化使用pay功能的成本,支付函数,总体负责支付,对应支付的对象的对象和金额
    def pay(payment,money):
        payment.pay(money)
    l=Wxpay()
    pay(l,300)
    接口类
    
    
    抽象类
    from abc import ABCMeta,abstractclassmethod
    class Animal:
        @abstractclassmethod
        def eat(self):
            print('拿起来')
            print('打开')    #将猫和狗能做的事抽象出来
            print('倒在碗里')
    
        @abstractclassmethod
        def sleep(self):
            pass
    class Dog(Animal):
        def eat(self):
            print('dog is eating')
    class Cat(Animal):
        def sleep(self):
            print('cat is sleeping')
    抽象类
    3.钻石继承
    深度优先 经典类 py3中
    广度优先 新式类 py2中

     2.多态

          多态指的是一类事物的多种状态

          python自带多态       

    import abc
    class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
        @abc.abstractmethod
        def talk(self):
            pass
    
    class People(Animal): #动物的形态之一:人
        def talk(self):
            print('say hello')
    
    class Dog(Animal): #动物的形态之二:狗
        def talk(self):
            print('say wangwang')
    
    class Pig(Animal): #动物的形态之三:猪
        def talk(self):
            print('say aoao')
    多态举例

         文件有多种形态:文本文件,可执行文件

    import abc
    class File(metaclass=abc.ABCMeta): #同一类事物:文件
        @abc.abstractmethod
        def click(self):
            pass
    
    class Text(File): #文件的形态之一:文本文件
        def click(self):
            print('open file')
    
    class ExeFile(File): #文件的形态之二:可执行文件
        def click(self):
            print('execute file')
    View Code


      多态性

         分为静态多态性和动态多态性

       静态多态性:任何类型都可以用运算符进行运算符

       动态多态性

         

    peo=People()
    dog=Dog()
    pig=Pig()
    
    #peo、dog、pig都是动物,只要是动物肯定有talk方法
    #于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
    peo.talk()
    dog.talk()
    pig.talk()
    
    #更进一步,我们可以定义一个统一的接口来使用
    def func(obj):
        obj.talk()
    动态多态性

      Python中处处多态,Python中一切皆对象

        就是在传递参数的时候,不需要知道参数的数据类型

         因此,可以随意传递任意数据类型、y鸭子类型:对于某一些方法来说,可以无差别的对待的几个类型,就是鸭子类型

    python不崇尚相似类型之间的继承关系

       数据类型之间减少依赖关系,解耦

       

    3.封装

            隐藏对象的属性和实现细节,仅对外提供公共访问方式

          好处:

             a.将变化隔离;

              b.便于使用

              c.提高复用性 

               d.提高安全性

           封装原则:

              a.将不需要对外提供的内容都隐藏起来

               b.把属性都隐藏,提高公共方法对其访问

      私有变量和私有方法

            在Python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

    a.  私有变量

           

    #其实这仅仅这是一种变形操作
    #类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:
    
    class A:
        __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
        def __init__(self):
            self.__X=10 #变形为self._A__X
        def __foo(self): #变形为_A__foo
            print('from A')
        def bar(self):
            self.__foo() #只有在类内部才可以通过__foo的形式访问到.
    
    #A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形
    View Code

    这种自动变形的特点:

    1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果

    2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。

    3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

    这种变形需要注意的问题是:

    1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

    2.变形的过程只在类的定义是发生一次,在定义后的赋值操作,不会变形

    b.私有方法

           在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

    >>> class A:
    ...     def fa(self):
    ...         print('from A')
    ...     def test(self):
    ...         self.fa()
    ... 
    >>> class B(A):
    ...     def fa(self):
    ...         print('from B')
    ... 
    >>> b=B()
    >>> b.test()
    from B
    
    
    
    
    
    
    #把fa定义成私有的,即__fa
    >>> class A:
    ...     def __fa(self): #在定义时就变形为_A__fa
    ...         print('from A')
    ...     def test(self):
    ...         self.__fa() #只会与自己所在的类为准,即调用_A__fa
    ... 
    >>> class B(A):
    ...     def __fa(self):
    ...         print('from B')
    ... 
    >>> b=B()
    >>> b.test()
    from A
    View Code

     

     property属性

        property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

         

    import math
    class Circle:
        def __init__(self,radius): #圆的半径radius
            self.radius=radius
    
        @property
        def area(self):
            return math.pi * self.radius**2 #计算面积
    
        @property
        def perimeter(self):
            return 2*math.pi*self.radius #计算周长
    
    c=Circle(10)
    print(c.radius)
    
    print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
    print(c.perimeter) #同上
    '''
    输出结果:
    314.1592653589793
    62.83185307179586
    '''
    圆的周长和面积
    BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)
    
    成人的BMI数值:
    过轻:低于18.5
    正常:18.5-23.9
    过重:24-27
    肥胖:28-32
    非常肥胖, 高于32
      体质指数(BMI)=体重(kg)÷身高^2(m)
      EX:70kg÷(1.75×1.75)=22.86
    
    
    import math
    class Circle:
        def __init__(self,radius): #圆的半径radius
            self.radius=radius
    
        @property
        def area(self):
            return math.pi * self.radius**2 #计算面积
    
        @property
        def perimeter(self):
            return 2*math.pi*self.radius #计算周长
    
    c=Circle(10)
    print(c.radius)
    print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
    print(c.perimeter) #同上
    '''
    输出结果:
    314.1592653589793
    62.83185307179586
    '''
    View Code

    python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现

      

    class Foo:
        def __init__(self,val):
            self.__NAME=val #将所有的数据属性都隐藏起来
    
        @property
        def name(self):
            return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)
    
        @name.setter
        def name(self,value):
            if not isinstance(value,str):  #在设定值之前进行类型检查
                raise TypeError('%s must be str' %value)
            self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
    
        @name.deleter
        def name(self):
            raise TypeError('Can not delete')
    
    f=Foo('egon')
    print(f.name)
    # f.name=10 #抛出异常'TypeError: 10 must be str'
    del f.name #抛出异常'TypeError: Can not delete'
    View Code

    一个静态属性property本质就是实现了get,set,delete三种方法

    class Foo:
        @property
        def AAA(self):
            print('get的时候运行我啊')
    
        @AAA.setter
        def AAA(self,value):
            print('set的时候运行我啊')
    
        @AAA.deleter
        def AAA(self):
            print('delete的时候运行我啊')
    
    #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
    f1=Foo()
    f1.AAA
    f1.AAA='aaa'
    del f1.AAA
    View Code
    class Goods:
    
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        @property
        def price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
    
        @price.setter
        def price(self, value):
            self.original_price = value
    
        @price.deleter
        def price(self):
            del self.original_price
    
    
    obj = Goods()
    obj.price         # 获取商品价格
    obj.price = 200   # 修改商品原价
    print(obj.price)
    del obj.price     # 删除商品原价
    用法


    classmethod

    staticmethod

    class Classmethod_Demo():
        role = 'dog'
    
        @classmethod
        def func(cls):
            print(cls.role)
    
    Classmethod_Demo.func()
    classmethod
    class Staticmethod_Demo():
        role = 'dog'
    
        @staticmethod
        def func():
            print("当普通方法用")
    
    Staticmethod_Demo.func()
    staticmethod
    class Student:
    
        f = open('student', encoding='utf-8')
        def __init__(self):pass
    
        @classmethod  #类方法,默认参数cls,直接可以用类名调用
        def show_student_info(cls):
             for line in cls.f:
                 name,sex = line.strip().split(',')
                 print(name,sex)
    
    
        # @staticmethod# 静态方法:让类里的方法直接被类调用,就像正常的函数
        # def show_student_info():#这里本来需要传值,但是加上@staticmethod就不需要了
        #     f = open('student', encoding='utf-8')  #文件句柄
        #     for line in f:
        #         name,sex=line.strip().split(',')
        #         print(name,sex)
    # 海娇 =Student()
    # 海娇.show_student_info()    #
    Student.show_student_info()
    
    
    
    
    
    
    
    # @classmethod和@staticmethod
    # 相同:直接被类调用,不同实例化
    #
    # 不同:
    # classmethod必须有cls参数表示类,可以使用类属性
    # @staticmethod不需要,不能直接使用类属性
    
    # 绑定方法
    # 非绑定方法
    #
    # 普通方法:默认有一个self方法穿进来,并且只能被对象调用---绑定到对象
    # 类方法 默认有一个cls传进来表示本类,并且可以被类和对象调用-----绑定到类
    # 静态方法:没有默认参数,并且可以被类和对象调用--没有绑定----非绑定
    上课举例

     

  • 相关阅读:
    正则表达式分组替换注意
    L2 正则化的直观理解
    git版本控制
    callbacks
    validation_data作用
    pandas 对某一列添加过滤
    py-redis 设置过期时间
    什么情况下要做预算会计
    超过一年的一个营业周期是什么意思?
    无形资产为什么属于非流动资产
  • 原文地址:https://www.cnblogs.com/1996-11-01-614lb/p/7391418.html
Copyright © 2011-2022 走看看