美文网首页
面向对象2

面向对象2

作者: 文化银儿 | 来源:发表于2018-08-01 17:54 被阅读0次

    一、内置类属性

    内置类属性:在python中每个类都有内置的类属性
    __name__
    __doc__
    __dict__
    __module__
    __bases__

    class Animal:
        """动物类"""
        pass
    
    class Cat(Animal):
        """说明文档:猫类"""
        number=0
    
        #对象属性
        def __init__(self,name='',color=''):
            self.name=name
            self.color=color
    
        #对象方法
        def run(self):
            print('%s在跑'%(self.name))
    
        #静态方法
        @staticmethod
        def shout():
            print('喵')
    
        #类方法
        @classmethod
        def get_number(cls):
            print('猫的数量为:%s'%(cls.number))
    
    if __name__ == '__main__':
        cat1=Cat('小花','white')
        """
        1.类.__name__
        获取类的名字(字符串)
        """
        print(Cat.__name__)   #Cat
    
        """
        2.类.__doc__
        获取类的说明文档
        """
        print(Cat.__doc__)  #说明文档:猫类
    
        """
        3.
        (1)类.__dict__
        获取类中所有的类的属性以及对应的值,以键值对的形式存到字典里面
        (2)对象.__dict__
        将对象的属性和对应的值,转换成字典元素(常用,掌握)
        """
        print(Cat.__dict__)
        #{'__module__': '__main__', '__doc__': '说明文档:猫类',
        # 'number': 0, '__init__': <function Cat.__init__ at 0x02195300>,
        #  'run': <function Cat.run at 0x021952B8>, 'shout': <staticmethod object at 0x005DD310>,
        #  'get_number': <classmethod object at 0x02193490>,
        # '__dict__': <attribute '__dict__' of 'Cat' objects>,
        # '__weakref__': <attribute '__weakref__' of 'Cat' objects>}
    
        print(cat1.__dict__)   #{'name': '小花', 'color': 'white'}
    
        """
        4.类.__module__
        获取当前类所在的模块的名字
        """
        print(Cat.__module__)   #__main__(正在执行时是__main__,使用外部导入的文件时是文件名)
    
    
        """
        5.类.__base__
        获取当前类的父类
        """
        print(Cat.__bases__)   #(<class '__main__.Animal'>,)
    
    

    二、私有化

    python中,类中的属性和方法的私有化:直接在属性名或者方法名前加两个下划线(命名时以__开头)
    属性或者方法私有:在外部不能直接使用,可以在类的内部使用

    import random
    
    class Person:
    
        私有的类字段
        __number=61
    
        def __init__(self,name='',age=0):
            self.name=name
            self.__age=age
    
        def show_age(self):
            print(self.__age-10)
            self.__run()   #李四在跑
    
        私有的对象方法只能在类的内部调用
        def __run(self):
            print('%s在跑'%self.name)
    
        私有的类方法
        @classmethod
        def __get_number(cls):
            print(cls.__number)
    
        静态方法私有化
    
    
    if __name__ == '__main__':
        p1=Person('张三',30)
        p1.name='李四'
        #print(p1.name,p1.__age)   #AttributeError: 'Person' object has no attribute '__age'(age私有化了,外部不能使用)
    
        p1.show_age()   #20  
    (可以在类的内部使用后,再在外面调用)
    
        # Person.__get_number()
    
        **私有化原理:在内部私有化的名字前加前缀'_类名'**
        print(p1.__dict__['_Person__age'])
    
    
    class Student:
        def __init__(self,name=''):
            self.name=name
            self.study_id=''
    
        def __creat_id(self):
            'py1805'+str(random.randint(1,50)).rjust(3,'0')
    
        def creat(self,name):
            stu= Student(name)
            stu.study_id=self.__creat_id()
            return stu
    
    

    三、getter和setter

    属性假的私有化:声明对象属性的时候,在属性名前加一个'_',来告诉别人这个属性不可以直接使用要通过getter和setter来获取属性的和修改属性的值

    1.getter:获取属性的值
    如果在获取对象的某个属性前,需要再干点其他事,就添加getter

    @property
    def 属性名(去掉下划线)(self):
        return 返回值
    

    2.setter:给属性赋值
    一个属性必须要要有getter,才能添加setter
    如果在给对象的某个属性赋值前,需要再干点儿别的事情,就给属性添加setter

    @属性名(去掉下划线).setter
    def 属性名去掉下划线(self,变量名):
        给带下划线的属性赋值
    
    class Student:
        """学生类"""
        def __init__(self):
            声明属性的时候,前面加一个"_"是为了告诉别人这些属性不能直接使用
            self._name=''
            self._score=0
            self._age=0
    
        给属性_name添加getter
        @property
        def name(self):
            return self._name
    
        给属性_name添加setter
        @name.setter
        def name(self,value):
            self._name=value
    
    
        @property
        def score(self):
            return self._score
    
        @score.setter
        def score(self,score):
            self.__score=score
    
        @property
        def age(self):
            return str(self._age) + '岁'
    
        @age.setter
        def age(self, age):
            if age >= 150 or age < 0:
                print('赋值有误,age要求是0-150的值')
                # raise 抛出异常: raise 错误类型
                # raise ValueError
                self._age = None
                return
            self._age = age
    
    
    if __name__ == '__main__':
        stu1=Student()
        不添加getter和setter
        stu1._name='李四'
        print(stu1._name)  #李四
    
        添加getter
        stu1._name = '张三'
        print(stu1.name)  #张三
    
        添加setter
        stu1.name='王五'
        print(stu1.name)  #王五
    
        stu1.age = 20
        print(stu1.age)
    

    四、类的继承

    子类:继承者
    父类(超类):被继承者

    1.如何继承
    python中类是可以继承的,并且支持多继承
    说明:python中所有的类默认继承python的基类:object

    class 类名(父类):
        '''类的说明文档'''
        属性
        方法
    

    2.继承哪些内容
    继承:直接拥有父类的属性和方法(继承后父类的属性和方法还是存在的)

    (1)对象的属性和方法,类的字段和方法,静态方法都可以继承(私有的继承无意义--->不能继承)
    (2)slots的值不会被继承
    (3)getter和setter会被继承

    class Person:
        """人类"""
        __slots__ = ('name','age','sex','__lenght','_face')
    
    
        def __init__(self):
            self.name=''
            self.age=0
            self.sex='男'
            self.__lenght=0
            self._face=0
    
        @property
        def face(self):
            return self._face
    
        @face.setter
        def face(self, face):
            self._face = face
    
        def eat(self):
    
            print('%s在吃饭'%self.name)
    
        类字段
        number=61
    
        类方法
        @classmethod
        def get_number(cls):
            print('人类数量:%d'%cls.number)
        静态方法
        @staticmethod
        def hurt_earth():
            print('人类破坏环境')
    
    
    class Student(Person):
        """学生类"""
        def study(self):
            pass
    
    
    
    
    if __name__ == '__main__':
        stu=Student()
        stu.name='晓晓'
        对象的属性
        print(stu.name,stu.age,stu.sex)  #晓晓 0 男
    
        对象的方法
        print(stu.eat())   #晓晓在吃饭
    
        类的字段
        print(Student.number)   #61
    
        类的方法
        Student.get_number()  # 人类数量:61
    
        静态方法
        Student.hurt_earth()  #人类破坏环境
    
        stu.face = 100
        print(stu.face)  #100
    
        print(stu.__dict__)  #{}
    

    五、练习-获取数据

    要求:将width,height的内容变为数字类型,并且将null变为‘无’


    image.png
    
    #获取数据
    import json
    
    def download_data():
        with open('./data.json','r',encoding='utf-8') as f:
            content=json.load(f)
            return content['data']
    
    class Data:
        """数据类"""
        def __init__(self):
            self.type=''
            self.text=''
            self.user_id=''
            self.name=''
            self.screen_name=''
            self._width=0
            self._height=0
            self._themes=None
    
        #_width的getter和setter
        @property
        def width(self):
            return self._width
        @width.setter
        def width(self,width):
            self._width=int(width)
    
    
        @property
        def height(self):
            return self._height
        @height.setter
        def height(self,height):
            self._height=int(height)
    
    
        @property
        def themes(self):
            if not self._themes:
                return '无'
            return self._themes
    
        #根据字典创建对象
        @classmethod
        def creat_data(cls,dict1):
            data=cls()
            for key in dict1:
                if key=='width':
                    data.width=dict1[key]
                    continue
                if key=='height':
                    data.height=dict1[key]
                    continue
                if key=='themes':
                    data._themes=dict1[key]
                    continue
                data.__setattr__(key,dict1[key])
            return data
    
    
    if __name__ == '__main__':
        print(download_data())
        datas=[]
        for dict1 in download_data():
            #通过字典创建对象
            data=Data.creat_data(dict1)
            #将创建的对象存起来
            datas.append(data)
        print(datas[0].themes)
    
    

    六、重写

    (1)在子类中可以直接添加其他的方法
    (2)重写:
    <1>完全重写:重新实现从父类继承下来的方法,重写后,子类再调用这个方法的时候,就调用子类的
    <2>保留父类实现的功能,再添加新的功能

    对象和类调用方法的过程:先看当前类是否存在这个方法,没有才看父类有没有这个方法,如果父类没有就看父类的父类有没有,直到找到基类(object)为止

    class Animal(object):
        """动物类"""
        def __init__(self):
            self.age=0
            self.color=''
    
        def eat(self):
            print('吃东西')
    
        def shout(self):
            print('叫唤')
    
        @classmethod
        def get_number(cls):
            return 100
    
    class Dog(Animal):
        def look_after(self):
            print('看家')
    
        重写父类的shout
        def shout(self):
            print('汪汪汪')
    
        重写父类的eat方法
        def eat(self):
            保留父类eat的功能
            super().eat()
            print('吃骨头')
    
    
        @classmethod
        def get_number(cls):
            保留父类的类方法,的功能的时候,还是super().类方法
            print(super().get_number())
    
    
    if __name__ == '__main__':
        dog=Dog()
        dog.age=3
        print(dog.color)
        dog.shout()   #汪汪汪
        dog.look_after()   #看家
        dog.eat()
        '''
        吃东西  
        吃骨头
        '''
    
        an=Animal()
        继承后,父类不能使用在子类中添加的属性和方法
        an.eat()   #吃东西
    

    七、添加属性

    对象属性的继承:是通过继承init方法来继承的父类方法

    给当前类添加对象属性:重写init方法

    注意:如果要保留父类的对象属性,需要使用super()调用父类的init方法

    多态:同一个事物有多种形态
    方法的多态:同一个事物有多重形态,子类继承父类的方法,可以对方法进行重写,一个方法就有多种形态(多态的表现)
    类的多:继承产生多态

    class Person(object):
        """人类"""
        def __init__(self, name, age=0, sex=''):
            self.name = name
            self.age = age
            self.sex = sex
    
        def eat(self):
            print('人在吃饭')
    
    
    class Staff(Person):
         (init方法的参数:保证在创建对象的时候就可以给某些属性赋值)
        def __init__(self, name='', age=0, salary=0):
            super().__init__(name, age)
            self.salary = salary
    
        def eat(self):
            print('员工在吃饭')
    
    class Scientist(Person):
        def eat(self):
            print('科学家在吃饭')
    
    
    if __name__ == '__main__':
        p1 = Person('李四',sex='女')
        p1.eat()
    
        s1 = Staff(age=18)
        s1.sex = '男'
        print(s1.name)
        s1.salary = 10000
        print(s1.salary)
        s1.eat()
    

    练习:
    声明人类,有属性,名字,年龄,性别,身高,
    要求:创建人的对象的时候,可以给名字,性别,年龄赋初值

    再创建学生类继承自人类,拥有人类的所有的属性,再添加学号,成绩,电话属性
    要求:创建学生对象的时候可以给名字,年龄和电话赋初值

    class Person2:
        """人类"""
        a = 10
    
        def __init__(self, name, sex, age):
            self.name = name
            self.age = age
            self.sex = sex
            self.height = 0
    
    
    class Student(Person2):
        """学生类"""
        b = 100
    
        def __init__(self, name='', age=0, tel='00'):
            super().__init__(name, age=age, sex='女')
            self.study_id = '00'
            self.score = 0
            self.tel = tel
    
    
    stu = Student('李四')
    stu.sex = '男'
    print(stu.age)
    
    p1 = Person2('张三', '男', 18)
    

    八、运算符的重载

    1.重载:一个类中可以有多个名字相同的方法,但是参数(个数)不一样,就叫重载,python中不支持重载

    2.运算符重载
    (作用:重新定义运算符运算的过程)
    (1)> 和 < :大于和小于符号,只需要重载其中一个,另外一个的结果,直接是重载的结果取反
    (2)+ 和 - :同上

    class Student:
    
        def __init__(self,name='',age=0,height=0):
            self.name=name
            self.age=age
            self.height=height
        """
        重载:>
        
        self>other
        """
        def __gt__(self, other):
            #比较对象1>对象2的时候是比较的他们的height属性
            return self.height>other.height
    
        """
        重载:<
        
        """
        def __lt__(self, other):
            return self.age<other.age
    
    
        """
        重载:+
        
        """
        def __add__(self, other):
            return self.age+other.age
    
        """
            重载:-
    
        """
        def __sub__(self, other):
            return self.height-other.height
    
        #python不支持方法的重载
        # def run(self):
        #     print('人在跑')
    
        def run(self,name):
    
            print('%s再跑'%name)
    
    
    if __name__ == '__main__':
    
        stu1=Student('AA',18,height=190)
        stu2=Student('BB',19,height=180)
    
        if stu1>stu2:
            print('学生1大于学生2哦哦哦')   #学生1大于学生2哦哦哦
    
        if stu1<stu2:
            print('学生1小于学生2')
        else:
            print('学生2小于学生1')   #学生1小于学生2
    
        print(stu1+stu2)   #37
    
        print(stu1-stu2)  #10
    
    
        stu=Student()
        stu.run('驾考')  #驾考再跑
    
    

    九、python中的内存管理

    python内存管理原理

    内存中有两个特殊的区域:栈、堆
    栈:栈中的内存是系统自动管理(内存的开辟和内存的释放)--->作用域结束,内存就释放
    堆:堆中的内存都需要写程序去开辟和释放的(python中这个过程也已经自动化)

    堆中的数据到底是什么时候释放的?
    看一个值有几个引用,当一个值没有应用的时候,值对应的内存空间就会被释放

    (引用计数机制)

    引用:存储对象地址的变量

    注意:将对象添加到容器中,对象的引用会加1

    class Person:
        def __init__(self, name):
            self.name = name
        def run(self):
            print(self.name,'人在跑')
    
    
    if __name__ == '__main__':
        # 声明了一个Person对象,存到p中的
        p = Person('p')
        p.run()
        # 删除对象的唯一的引用,对象就会被销毁
        del p
        # p.run()
    
        # Person对象(0),name='p1'  0+1+1-1-1
        p1 = Person('p1')
        p2 = p1
        del p2
        p1.run()
        p1 = 'a'
    
        # 注意:将对象添加到容器中,对象的引用会加1
        p3 = Person('p3')
        lists = [p3, 100]
        del p3
    
        lists[0].run()
    
        # del lists[0]
        # del lists
        lists[0] = None
    

    十、包的使用

    封装:
    对一个功能的封装--->用函数
    对多个功能的封装--->模块和类
    对多个数据进行封装--->类,字典
    对多个类进行封装--->模块
    对多个模块进行封装--->包(文件夹里面有个init.py文件)

    导入包
    import package1

    导入某个包中的某个模块
    from package1 import my_math

    导入某个包的某个模块中的某个函数和类
    from package1.my_math import sum,Math

    总结

    """
    1.内置属性
    __name__:获取当前类的
    __doc__:类的说明
    类.___dict__:获取类的所有属性   
    对象.__dict__:获取对象的所有属性
    注意:当我们通过__slots__去约束对象属性后,对象__dict__属性不
          能使用,如果父类设置了__slots__,子类对象也不能使用__dict__
    __module__:获取模块名
    __bases__:获取当前类的父类
    
    
    
    2.私有化
    命名时前加'__',变私有的,不能在类的外面去使用,不能被继承
    
    3.假的私有:getter 和 setter
    对象属性
    
    (1)在给对象属性赋值前,或者获取属性前,要干点别的事情,我们就给属性添加getter或者setter
    (2)命名属性时,名字前加一个人下划线'_',添加关键字@property
    
    @property
    def 属性名去掉下划线(self):
        返回值
        
    @属性名去掉下划线.setter
    def 属性名去掉下划线(self,value):
        给属性赋值
        
    (3)调用
    
    
    4.继承
    让子类直接拥有父类的属性和方法
    
    class 子类(父类):
        属性
        方法
    
    能继承什么:所有的属性和方法都可以继承,但是除了私有的,__slots__的值不能继承
    """
    
    5.添加属性和方法,以及对方法的重写
    重写:(1)完全覆盖   (2)保留父类的功能(super().父类方法)
    
    添加对象属性:
    def __init__(self):
        super().__init__()
        self.属性名=值
        
    6.运算符重载
    __add__:+
    __sub__:-
    __gt__:>
    __lt__:<
    
    7.内存管理
    一个对象没有引用,内存就释放
    
    引用类型:变量存的是地址
    值类型:变量存的是值(数字。字符串)
    
    8.包
    封装功能:函数
    封装数据:容器类型、对象的属性
    多个功能封装:类、模块
    多个类封装:模块
    多个模块:包
    
    from 包 import 模块
    
    from 包.模块 import 函数、类、变量
    
    

    相关文章

      网友评论

          本文标题:面向对象2

          本文链接:https://www.haomeiwen.com/subject/qvvrvftx.html