zoukankan      html  css  js  c++  java
  • Python之面向对象基础

    1.面向对象编程与面向过程编程

      面向对象编程,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。通过把真实的物体抽象成对象,然后赋予对象属性、方法等特性,然后去解决问题。

      面向过程编程,本质是面向结果编程,通过函数解决问题。

    2. 面向对象基础

      a. 类:具有相同竖向和方法的一类事物

      b. 对象:具有具体属性的事物

      c. 静态属性:所有的对象共有的属性,可以直接调用

      d. 对象属性/方法:是属于某一个对象的,只能在实例化之后对象调用

    class 类名:    # 类名首字母大写
        属性 = "功能"    # 类的属性:静态属性,不是必须要定义的,当多有的对象都用的时候去定义
        def __init__(self,参数):    # self是不需要传的
            #__init__这里是定义了一个该类对象共有的属性
            # 这里的属性是对象属性,
            self.key = 参数    # 这里self.key就相当于字典的key,参数就相当于value
        def 方法(self):  # 类里面的方法本质上就是函数--函数必须要传一个参数self
            pass
    
    print(类名.属性)
    # 实例化一个对象,对象就是实例
    对象 = 类名("参数")    # 参数是传到__init__函数里
    
    对象.函数名()    # 调用成功,传入的self就是对象,当用一个对象去调用对他的方法的时候,自动传入的一个参数,这个参数就是对象本身
    

       示例1:计算长方形的面积

    class Rectangle:
        role = "retangle"
        def __init__(self,long,wide):
            self.long = long
            self.wide = wide
        def length(self):
            return 2*(self.long+self.wide)
        def area(self):
            return self.long*self.wide
    
    rect = Rectangle(3,4)
    ret_l = rect.length()
    print(ret_l)
    ret_a = rect.area()
    print(ret_a)
    

       示例2:计算圆的面积

    from math import pi
    class Circle:
        rloe = "circle"
        def __init__(self,r):
            self.r = r
        def length(self):
            return 2*pi*self.r
        def area(self):
            return pi*self.r*self.r
    
    
    val = Circle(10)
    val_l = val.length()
    print(val_l)
    val_s = val.area()
    print(val_s)
    

     

    3. 命名空间

      a. 类的命名空间和对象的命名空间是分开的,且每个对象都有独立的命名空间,公用一个类的命名空间

      b. 调用静态属性:调用的就是类中的属性

      c. 调用动态属性:对象和类去调用的时候,表现出来的地址是不一样的,但实际是一样的

      d. 调用类的静态属性:类调用的就是类中的属性,对象调用先从自己内存空间里找名字,找到了就用自己的,没有找到就用类的,类中也没有的话就报错

      e. 调用类的动态属性:这个方法本身就存在类中,并不会存在对象的内存中,但是在对象调用类中的方法的时候,要依赖于一个地址薄去类中寻找对应的方法

      f. 类的外面可以添加静态属性或对象属性,动态属性(方法)不可以添加

      g. 关于对象的属性:
        *. 对象的属性就存在类的命名空间中
        *. 只能被对象调用修改
        *. 不能被类调用

    class Birthday:    # 定义一个生日类,
        role = "birthday"   # 静态属性
        def __init__(self,year,month,day):  # 定义一些生日共有的属性
            self.year = year    # 对象属性
            self.month = month
            self.day = day
    
    class Course:   # 定义一个课程类
        role = "course"     # 静态属性
        def __init__(self,name,period,teacher,price):
            self.name = name       # 对象属性
            self.period = period
            self.teacher = teacher
            self.price = price
    
    class Person:   # 定义一个人类
        role = "person"     # 静态属性
        def __init__(self,name,haijiao_birth):
            self.name = name    # 静态属性
            self.birth = haijiao_birth
    
    python = Course("python",5,"Teacher Li",200000)   # 实例化python到Course类中
    john_birth = Birthday(1999,2,22)     # 实例化john_birth到Birthday类中
    john = Person("john",john_birth)   # 实例化john到Person类中
    print(john.birth.month)      # john.birth等价于Person类中的self.birth,而self.birth 等于 john_birth,所以就等价于john_birth.month
    print(john_birth.month)    # 从类的外部去调用类内的对象属性
    john_class = python      # 在外部添加对象属性,在john的小空间里
    print(john_class.name)
    print(john_birth.day)
    

    4. 组合

      组合:一个类的对象是另一个类的属性,增强了代码的重用性

    from math import pi
    class Circle:
        def __init__(self,r):
            self.r = r
    
        def perimeter(self):
            return 2*pi*self.r
    
        def area(self):
            return pi*self.r*self.r
    
    class Ring:
        def __init__(self,r_out,r_in):
            self.r_out = Circle(r_out)    # 组合
            self.r_in = Circle(r_in)
    
        def perimeter(self):
            return self.r_out.perimeter() + self.r_in.perimeter()
    
        def area(self):
            return self.r_out.area() - self.r_in.area()
    
    
    val = Ring(10,5)
    perimter = val.perimeter()
    print(perimter)
    area = val.area()
    print(area)
    

    5. 面向对象特性之封装

      a. 封装:将同一类方法属性封装到类中,通过构造方法,将数据封装到对象中

      b. 私有属性,私有方法(双下划线+属性名/方法名

    class Teacher:
        __identifier = "Teacher"    # 私有静态属性
        def __init__(self,name,pwd):
            self.name = name
            self.__pwd = pwd    # 私有属性
            self.__p()  # 调用私有方法
    
        def pwd(self):
            print(self.__pwd)
    
        def __p(self):  # 私有方法
            print(self.__pwd)
    
    
    wu = Teacher("Wu","3714")
    wu.pwd()
    print(wu.__dict__)    # 打印属于wu的属性
    
    # 类外调用私有属性(_类名__私有属性名)--不要去使用这个方法
    print(wu._Teacher__pwd)
    
    # 类外调用私有方法
    wu._Teacher__p()
    
    # 类外调用私有静态属性
    print(Teacher._Teacher__identifier)
    
    # 类外定义私有属性形式的属性,没有任何意义,就跟普通属性一样的
    

      c. 私有方法的意义:

        *. 有一些方法的返回值只是用来作为中间结果

        *. 父类的方法不希望子类继承

    class Teacher:
        __identifier = "Teacher"
        def __init__(self,name,pwd):
            self.name = name
            self.__pwd = pwd
            self.__p()
    
        def __p(self):
            return hash(self.__pwd)
    
        def judge(self,password):
            return hash(password) == self.__p()
    
    
    wu = Teacher("wu","3714")
    ret = wu.judge("3417")
    print(ret)
    

       d. 私有属性

    class Person:
        def __init__(self,name,height,weight):
            self.name = name
            self.__height = height
            self.__weight = weight
    
        def get_bmi(self):
            return self.__weight /(self.__height * self.__height)
    
        def change_weigth(self,new_weight):
            if new_weight > 20:
                self.__weight = new_weight
            else:
                print("体重过轻")
    
    ha = Person("ha",1.81,94)
    print(ha.get_bmi())
    ha.change_weigth(80)
    print(ha.get_bmi())
    

      示例

    class Host:
        def __init__(self,owner,length,width):
            self.owner = owner
            self.__length = length
            self.__width = width
        def area(self):
            return self.__length * self.__width
    
    host = Host("lu",50,30)
    print(host.area())
    

       e. property方法:把类中的方法假装成一个属性

    class Person:
        def __init__(self,name,height,weight):
            self.name = name
            self.__height = height
            self.__weight = weight
    
        @property
        def bmi(self):
            return self.__weight /(self.__height * self.__height)
    
    
    lu= Person("lu",1.81,94)
    print(lu.name,lu.bmi)    # 这里去调用的时候,就是相当于调用一个属性
    

         *. @要伪装的方法名.setter,这样就更加像属性

    class Shop:
        discount = 0.75
        def __init__(self,name,price):
            self.name = name
            self.__price = price
    
        @property
        def price(self):
            return self.__price * Shop.discount
    
        @price.setter
        def price(self,new_price):
            self.__price = new_price
    
        @price.deleter  # 一般不会用到
        def price(self,):
            del self.__price
    
    apple = Shop("apple",5)
    print(apple.price)
    apple.price = 6     # @price.setter,用了这个方法之后,就可以修改了
    print(apple.price)
    print(apple.__dict__)
    del apple.price
    print(apple.__dict__)
    

       f. staticmethod:静态方法,函数不需要依赖对象的属性和类的属性,就可以使用staticmethod装饰

    class A:
        def __init__(self,name):
            self.name = name
    
        def ah(self):   # self就是形式参数,ah就是普通方法,绑定(对象)方法
            print("ah")
    
        @staticmethod   # 静态方法
        def func():
            print("func")
    
    # a = A("a")
    # A.func(a)   #和a.func()一样
    A.func()
    

       g. 类方法:对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

    class A:
        role = "a"
        @classmethod
        def class_metood(cls):  #这里必须叫cls,默认的
            print(cls.role)
    
    A.class_metood()
    # A.role
    

       h. 小结

        *. 静态方法--没有必须传的参数,不需要用对象的属性和类的属性

        *. 类方法--必须传一个类,不能使用对象属性,但可以使用类属性

        *. 普通方法--必须传一个参数,可以使用对象的属性和类的属性

     

    6. 面向对象特性之继承

      a. 继承:当两个类有相同的方法或属性的时候,把这些相同的方法属性封装到基类类中,只实现一次,其它类去继承

      b. 继承是A类是B类子类的关系,而组合是A类中有B类的关系

        *. 父类/超类/基类,子类/派生类

        *. object是所有类的基类,type是所有类的类型,metaclass可以指定类的类型

        *. 对象可以调用自己本类和父类所有的方法和属性,先调用自己的.

        *. 先抽象在继承
          抽象---从小类到大类
          继承---从大类到小类

      c. 单继承,多继承

    class Animal:   # 父类
        def eat(self):
            pass
        def drink(self):
            pass
        def sleep(self):
            pass
    
    class Bnimal:   # 父类
        def eat(self):
            pass
    
        def drink(self):
            pass
    
        def sleep(self):
            pass
    
    class Dog(Animal):   # 单继承
        pass
    
    class Cat(Animal,Bnimal):   # 多继承
        pass
    
    print(Dog.__bases__)    # (查看所有父类)
    print(Cat.__base__)     # (查看从左到右的第一个父类)
    

       d. super()方法

        *. 在继承中,子类可以继承父类所有的属性和方法,当父类和子类中有同名方法的时候,一定调用子类的。如果想使用父类的该方法的功能,需要借助super方法。

    class A:
        def hahaha(self):
            print("A")
    
    class C:
        def hahaha(self):
            print("C")
    
    class B(A,C):
        def hahaha(self):
            # B.hahaha(self)    # 经典类的调用父类中方法的方式
    
            # super--新式类,当多个父类有同名方法时,先从前面找,优先使用第一个找到的
            # super(B,self).hahaha()   # 里面这里可以传,或者不传,
            super().hahaha()    # 一般不传,因为在子类里边,很容易就知道是哪个类
            print("B")
    
    b = B()
    b.hahaha()  # 调用了自己的hahaha()
    super(B,b).hahaha()    # 相当于A.hahaha(),外部的时候,必须传参

      示例

    class Animal:   #---父类
        def __init__(self,name):
            self.name = name
        def eat(self):
            print("%s is eating %s"%(self.name,self.food))
        def drink(self):
            print("%s is drinking %s" % (self.name, self.food))
        def sleep(self):
            print("%s is sleeping %s" % (self.name))
    
    
    class Dog(Animal):#---单继承
        def __init__(self,name):
            self.food = "狗粮"
            super().__init__(name)
        def say(self):
            print("汪汪汪")
    
    class Cat(Animal):
        def __init__(self,name):
            self.food = "猫粮"
            super().__init__(name)
        def say(self):
            print("喵喵喵")
    
    wang = Dog("wang")
    wang.eat()A
    
    c = Cat("egon")
    c.eat()
    
    class Animal:
        def __init__(self,name,food):
            self.name = name
            self.food = food
            self.family = "大森林"
        def eat(self):
            print("%s is eating %s"%(self.name,self.food))
        def drink(self):
            print("%s is drinking"%(self.name))
        def sleep(self):
            print("%s is sleeping"%(self.name))
        def call(self):
            print("%s is calling %s" % (self.name,self.calling))
    
    class Dog(Animal):#游泳
        def __init__(self,name):
            super().__init__(name, "骨头")
            self.calling = "汪汪汪"
            self.family = "小破屋"
        def swim(self):
            print("%s swimming"%self.name)
    
    class Bird(Animal): #飞
        def __init__(self,name):
            super().__init__(name,"虫子")
            self.calling = "布谷"
        def fly(self):
            print("%s flying"%self.name)
    
    
    erha = Dog("erha")
    erha.call() #调用父类的方法
    erha.swim() #调用自己的方法
    print(erha.family)  #优先使用自己的
    print("******************************")
    cuckoo  = Bird("cuckoo")
    cuckoo.call()
    print(cuckoo.family)#因为他本身没有,所以直接用父类的
    

      e. 派生属性和派生方法

        *. 派生属性--在父类没有的基础上,子类自己有的属性

        *. 派生方法--在父类没有的基础上,子类自己的方法

    class Animal:   #父类,人和动物都有的一些属性
        def __init__(self,name,blood,aggr):
            self.name = name
            self.blood = blood
            self.aggr = aggr
    
    class Person(Animal):   #继承的语法,Person是子类,继承了父类Animal的属性
        def __init__(self,name,blood,aggr,money):
            super(Person,self).__init__(name,blood,aggr)    #在子类执行父类的方法
            self.money = money      #派生属性
        def attack(self,dog):   #派生方法
            dog.blood -= self.aggr
    
    class Dog(Animal):  #继承的语法,Dog是子类,继承了父类Animal的属性
        def __init__(self,name,blood,aggr,breed):
            super().__init__(name,blood,aggr)
            self.breed = breed
        def attack(self, person):
            person.blood -= self.aggr
    
    
    
    alex = Person("alex",2000,250,1000000)
    erha = Dog("erha",2000,250,"金毛")
    

      f. 经典类,新式类

        *. 经典类和新式类的区别:

          1. 定义顺序

          2. 子类执行父类中的同名方法

          3. 继承问题
        *. python2里有经典类和新式类之分

          经典类--深度优先

          新式类--广度优先 

    class A:  # 经典类
        pass
    class B(object):  # 新式类
        pass
    

         *. 在python3中,object是所有类的基类 

      g. 钻石继承:python的新式类和经典类在继承顺序上的不同

    class F:
        def test(self):
            print("F")
    
    class E(F):
        pass
        def test(self):
            print("E")
    
    class D(F):
        pass
        def test(self):
            print("D")
    
    class C(E):
        pass
        def test(self):
            print("C")
    
    class B(D):
        pass
        def test(self):
            print("B")
    
    class A(B,C):
        pass
        def test(self):
            print("A")
    
    a = A()
    a.test()
    A-B-D-C-E-F
    
    class D():
        pass
        def test(self):
            print("D")
    
    class C():
        pass
        def test(self):
            print("C")
    
    class B(D):
        pass
        def test(self):
            print("B")
    
    class A(B,C):
        pass
        def test(self):
            print("A")
    
    a = A()
    a.test()
    
    # 这个的继承是A-B/C,B-D,C没有父类
    # 这种情况下,A中没有时,先找B,B中没有时先找D,D里边没有的时候,就找C
    

    7. 多态

      a. 多态指的是一类事物有多种形态,python天生支持多态,不同的类可以有一样的方法,但是功能是不一样。
      b. 鸭子模型
        对于一个对象来说,只要它能鸭子叫,就是鸭子,不管它是什么形态,这就是多态
        对于一个对象来说,只要能使用一个方法,就不管他是什么形态的

    8. 抽象类和接口类

      a. 接口类:归一化设计

    from abc import abstractmethod,ABCMeta

    class Payment(metaclass=ABCMeta): # 接口类/抽象类,子类的规范(约束子类必须要有这个里的方法,不然就抛异常) @abstractmethod # 加了一个装饰器 def payment(self,money): raise NotImplemented class Applepay(Payment): def payment(self,money): print("apple 支付了 %d元"%money) class Alipay(Payment): def payment(self,money): print("支付宝 支付了 %d元"%money) class Wechatpay(Payment): def huaqian(self,money): print("微信 支付了 %d元"%money) def payment(pay_obj,money): pay_obj.payment(money) apple = Applepay() ali = Alipay() payment(apple,200) payment(ali,100) wechat = Wechatpay() wechat.payment(wechat,100) # 因为他没有payment方法,所以会报错 # TypeError: Can't instantiate abstract class Wechatpay with abstract methods payment

       b. 抽象类:抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。

    from abc import abstractmethod,ABCMeta

    class Foo(metaclass=ABCMeta): # 抽象类 @abstractmethod def read(self): # 抽象类去实现了方法 f = open() f.read() f.close() def write(self): f = open() f.write() f.close() class File(Foo): def read(self): super().read() def write(self): super().write() class Disk(Foo): def read(self): super().read() def write(self): super().write()

      c. 对比

        a. 接口类不实现具体的方法,并且可以多继承;抽象类可以做一些基础实现,并且不推荐多继承

        b. 在抽象类中,我们可以对一些抽象方法做出基础实现;而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现

      d. 小结

        *. 编程思想:为子类做规范
          归一化设计:几个类都实现了相同的方法
          抽象类:最好单继承,且可以简单的实现功能
          接口类:最好多继承,且最好不实现具体功能

        *. 开放封闭原则:扩展是开放的,修改是封闭的

        *. 依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程

        *. 接口隔离原则:使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。

      

  • 相关阅读:
    两个List集合过滤出不同集合
    TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
    sql server 查询某个表被哪些存储过程调用
    SQL server字符分割
    oracle 结果集合并
    tree与GridView交互
    oracle job相关
    ImportFileHandler 附件上传
    dt转换List CovertListHelper
    node版本管理mac版
  • 原文地址:https://www.cnblogs.com/chitalu/p/12357580.html
Copyright © 2011-2022 走看看