zoukankan      html  css  js  c++  java
  • Python之面向对象编程

    初识类

           类是用来描述具有相同属性和方法的对象的集合。对象是具体存在的,而类是一种抽象概念。在程序中遵循先定义类再调用类的顺序。类的名字是采用驼峰体的,类在定义阶段就会立刻执行类体内代码,将产生的名字存放在类的名称空间中,可以用__dict__查看类的名称空间,将以字典形式返回结果。

      类分为父类和子类。父类又称为基类或超类,子类又称为派生类。类有两种属性:数据属性和函数属性(函数是没有被任何装饰器装饰的)。类的数据属性是直接对象所有共享的,类的函数属性是绑定给对象用的,绑定给不同的对象就是不同的绑定方法。

    class Student:
      #定义私有属性,外部无法直接访问 n
    =0
    #__init__()构造方法
       #self代表类的实例
       #def定义方法,类方法的第一个参数必须是用来代表类的实例的
    def __init__(self,name,age,gender): self.name=name#类对象的属性引用 self.age=age self.gender=gender Student.n+=1 school='红太阳' def learn(self): return '%s is learning'%self.name
    #obj.class指向类 stu1
    =Student('aa',19,'female')#类对象的实例化 # print(stu1.n) # print(stu1.learn) # #<bound method Student.learn of <__main__.Student object at 0x000001BEFD188B38>> # print(stu1.learn()) stu2=Student('bb',23,'male') # print(stu2.n) # print(stu2.learn) # #<bound method Student.learn of <__main__.Student object at 0x000001BEFD188BA8>> # print(id(Student.n),Student.n) # print(id(stu1.n),stu1.n) # print(id(stu2.n),stu2.n) # #同id # Student.n=1 # print(id(Student.n),Student.n) # print(id(stu1.n),stu1.n) # print(id(stu2.n),stu2.n) #都随着Student.n变化而变 # stu1.n=1 # print(id(Student.n),Student.n) # print(id(stu1.n),stu1.n)#1345678816 1 # print(id(stu2.n),stu2.n) #只有stu1变化,其他都不变

    类的实例化就是调用类产生对象的过程,实例对象就是类的实例化的结果。对象除了共有的属性和方法之外,应该还有其特有的,这样类实例化结果的对象就不是一模一样的了。要使对象就有其特征,就要在类体内定义一个__init__函数,该函数在调用类时自动触发执行。

    调用类的过程将发生三件事:

      一是产生空对象;

      二是自动触发类体内的__init__函数;

      三是将空对象连同调用类时括号内的参数一起传给__init__函数。

    类的使用:

      1.必须遵循函数的参数规则

      2.类中定义的函数主要是给对象使用的,而且是绑定到对象的。虽然所有对象的指向都是相同的功能,但是绑定到不同对象就是不同的绑定方法。绑定到对象的特殊之处就在于绑定谁就由谁调用,谁调用就将谁本身当做第一个参数(self)传给方法,即自动传值。

    对象间的交互

    class Dog:
        def __init__(self,name,d_type,aggressivity,life_value):
            self.name=name
            self.d_type=d_type
            self.aggressivity=aggressivity
            self.life_value=life_value
    
        def bite(self,enemy):
            enemy.life_value-=self.aggressivity
            print('''
            狗[%s]咬人[%s]
            人掉血[%s]
            人的生命值还剩[%s]'''%(self.name,enemy.name,self.aggressivity,enemy.life_value))
    
    dog1 = Dog('旺财', '中华田园犬', 50, 60)
    
    class People:
        def __init__(self,name,aggressivity,life_value=100):
            self.name=name
            self.aggressivity=aggressivity
            self.life_value=life_value
    
        def bite(self,enemy):
            enemy.life_value -= self.aggressivity
            print('''
                    人[%s]咬狗[%s]
                    狗掉血[%s]
                    狗的生命值还剩[%s]''' % (self.name, enemy.name, self.aggressivity, enemy.life_value))
    
    
    
    people1=People('aa',30)
    people1.bite(dog1)

    继承和派生

    继承就是类与类之间的关系,是创建类的一种方式,继承的 目的就是减少代码冗余。子类会遗传父类的属性,子类可以继承一个或多个父类。

    寻找继承关系需要先抽象再继承。

    属性查找是现从子类自己查找,找不到再去父类查找。

    派生就是子类定义 自己的新属性,如果是与父类的属性同名,以子类 自己的为准。在子类派生的 新方法中重用父类功能的方式:一是指名道姓地调用,这种方式与继承关系是无关的 ,与调用普通函数是一样的;二是通过执行super()得到返回值,该返回值是一个 特殊对象,该对象专门用来调用mro()列表从当前的查找位置往后查找下一个类的属性或方法。第二种方法是严格遵循继承关系的。

     组合

    1.组合是什么?

    组合是用于描述一个对象拥有的属性,该属性来自于另一个类。

    2.组合怎么用?

    class School:
        school='red hair'
        def __init__(self,name,age,gender):
            self.name=name
            self.age=age
            self.gender=gender
    
    class Date:
        def __init__(self,year,mon,day):
            self.year = year
            self.mon = mon
            self.day = day
    
        def tell_birth(self):
            print('''
            ==========
            year  [%s]
            month [%s]
            day   [%s]
            '''%(self.year,self.mon,self.day))
    
    class Teacher(School):
        def __init__(self,name,age,gender,level,salary):
            super(Teacher,self).__init__(name,age,gender)#用super()重用父类
            self.level=level
            self.salary=salary
            self.courses=[]
    
        def change_score(self):
            print('teacher is changing score')
    
        def tell_course_info(self):
            print(('teacher [%s] has course:'%self.name).center(50,'='))
            for course_obj in  self.courses:
                course_obj.info()#组合
    
    class Student(School):
        def __init__(self,name,age,gender,grade):
            super(Student,self).__init__(name,age,gender)
            self.grade=grade
            self.courses=[]
    
        def choose(self):
            print('student [%s] choose course'%self.name)
    
        def tell_course_info(self):
            print(('student [%s] learn course:'%self.name).center(50,'='))
            for course_obj in self.courses:
                course_obj.info()
    
    class Course:
        def __init__(self,cname,period,price):
            self.cname=cname
            self.period=period
            self.price=price
    
        def info(self):
            print('''
            ========course info========
            course_name     <%s>
            course_period   <%s>
            course_price    <%s>
            '''%(self.cname,self.period,self.price))
    
    t1=Teacher('aa',20,'female',9,3.1)
    # t1.birth=Date(1998,12,12)
    # t1.birth.tell_birth()
    
    s1=Student('bb',16,'male','python')
    # s1.birth=Date(2002,12,12)
    # s1.birth.tell_birth()
    
    python=Course('python','5mons',20000)
    linux=Course('linux','5mons',20000)
    go=Course('Go','5mons',25000)
    
    # t1.course=python
    # s1.course=python
    # t1.course.tell_course_info()
    t1.courses.append(python)
    t1.courses.append(linux)
    print(t1.courses)
    for course_obj in t1.courses:
        course_obj.info()
    # t1.tell_course_info()
    s1.courses.append(go)
    s1.courses.append(python)
    s1.tell_course_info()

    封装

    1.封装是什么?

    封装从字面意思上看是隐藏,但是又与隐藏有所不同,封装是对外隐藏,对内公开。

    封装数据属性:把数据属性封装起来,将需要的开辟接口给外部使用者用。其好处是添加控制逻辑,从而控制访问者对属性的操作,起到隔离复杂性的效果。

    2.封装如何实现隐藏?

    在属性名前面加__开头,但是不是以__结尾的

    class ATM:
        def __insert_card(self):
            print('insert your card')
    
        def __transfer(self):
            print('transfer')
    
        def __with_draw(self):
            print('withdraw')
    
        def __repay(self):
            print('repay')
    
        def __check_flow(self):
            print('check your bank flow')
    
        def run(self):
           self.__insert_card()
           self.__transfer()
           self.__with_draw()
           self.__repay()
           self.__check_flow()
    
    obj=ATM()
    obj.run()
    

     3.封装要注意的三个点:

        (1)为一个属性加__开头会在属性定义阶段将属性名变形,是一种语法上的变形

        (2)这种语法上变形只在定义阶段发生一次,定义之后新增的属性即使是以__开头也不会变形

        (3)如果父类不想属性被子类的覆盖就可以给该属性加__开头

    多态

     1.多态是什么?

    多态就是同一属性的多种形态

    2.多态的特性?

    可以在不考虑对象具体类型的前提下直接使用对象下的方法

    3.使用多态的好处?

        (1)增加程序的灵活性

        (2)增加了程序的可扩展性

    import abc  #abstractclass抽象类
    
    class Animal(metaclass=abc.ABCMeta):#抽象基类,抽象基类本身不能再实例化
        @abc.abstractmethod
        def eat(self):
            pass
    
        @abc.abstractmethod
        def bark(self):
            pass
    
    class Cat(Animal):
        def eat(self):
            print('cat eatting')
    
        def bark(self):
            print('cat bark')
    
    class Dog(Animal):
        def eat(self):
            print('dog eatting')
    
        def bark(self):
            print('dog bark')
    
    dog=Dog()
    cat=Cat()
    cat.eat()
    def EAT(obj):
        obj.bark()
    
    EAT(cat)
    

      

    鸭子类型

      Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’

    python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象

    也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度。

    反射

    通过字符串来操作类与对象的属性,这种操作称为反射;反射也是内置函数
    下述四个函数是专门用来操作类与对象属性的
    class People:
        country="China"
        def __init__(self,name):
            self.name=name
        def tell(self):
            print('%s is aaa' %self.name)
     
    obj=People('egon')
    1、hasattr
    print(hasattr(People,'country')) #可用来操纵类 # print('country' in People.__dict__)
    print(hasattr(obj,'name'))     #可用来操纵对象
    print(hasattr(obj,'country'))
    print(hasattr(obj,'tell'))
    2、getattr
    print(getattr(People,'country1',None))  #如果没有返回None;若不写,没有报错
    f=getattr(obj,'tell',None)  #obj.tell
    f() #obj.tell()
     
    3、setattr
    setattr(People,'x',111)   #People.x=111
    print(People.x)
    setattr(obj,"age",18)     #obj.age=18
    print(obj.__dict__)
    4、delattr
    delattr(People,"country")   #del People.country
    print(People.__dict__)
    delattr(obj,"name")           #del obj.name
    print(obj.__dict__)
     
    #用户用input输入了字符串形式的指令,可以被反射以操纵类和对象的属性
    class Foo:
        def run(self):
            while True:
                cmd=input('cmd>>: ').strip()
                if hasattr(self,cmd):
                    func=getattr(self,cmd)
                    func()
     
        def download(self):
            print('download....')
     
        def upload(self):
            print('upload...')
     
    obj=Foo()
    obj.run()
    三、__str__方法
    __xxx__是满足一定条件时自动触发
    __str__ 当打印对象时自动触发,可用来定制打印格式
    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
     
        def __str__(self):
            return '<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex)
     
    obj=People('egon',18,'male')
    print(obj) #print(obj.__str__()),若没有__str__,返回一个内存地址(原生状态)
     
    l=list([1,2,3])
    print(l)   #[1, 2, 3], python帮忙优化的,否则返回一个内存地址
    四、__del__方法
    __del__在删除对象时自动触发
    import time
    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
     
        def __del__(self): #在对象被删除的条件下,自动执行
            print('__del__')
     
    obj=People('egon',18,'male')
    del obj #obj.__del__()  #若没有这一行,睡2s后会自动触发__del__,因为程序结束前会删除对象(清除资源)
    time.sleep(2)
    __del__的主要用途是回收系统资源
    class Mysql:
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
            self.conn=connect(ip,port) #申请系统资源, 此行为伪代码
        def __del__(self):
            self.conn.close()         #回收系统资源
     
    obj=Mysql('1.1.1.1',3306)
     
    class MyOpen:
        def __init__(self,filepath,mode="r",encoding="utf-8"):
            self.filepath=filepath
            self.mode=mode
            self.encoding=encoding
            self.fobj=open(filepath,mode=mode,encoding=encoding)
        def __str__(self):
            msg="""
            filepath:%s
            mode:%s
            encoding:%s
            """ %(self.filepath,self.mode,self.encoding)
            return msg
        def __del__(self):
            self.fobj.close()    #回收系统资源
     
    f=MyOpen('aaa.py',mode='r',encoding='utf-8')
    print(f.filepath,f.mode,f.encoding)
    print(f)
    print(f.fobj)
    res=f.fobj.read()
    print(res)
    以下四个皆为绑定对象的方法,在满足一定条件时,自动触发
    __init__
    __str__
    __del__
    __call__
     
  • 相关阅读:
    osg 自定义图元
    osg model
    Qt 获取键盘输入
    TensorFlow Object Detection API —— 测试自己的模型
    labelimg data
    Qt 自定义信号SIGNAL
    qt ui
    QPixmap QImage 相互转化
    QString std::string 相互转 含中文
    ubuntu 安装百度云客户端
  • 原文地址:https://www.cnblogs.com/qiaoqianshitou/p/8795426.html
Copyright © 2011-2022 走看看