美文网首页
类和对象

类和对象

作者: 葡萄柚子茶 | 来源:发表于2018-09-07 20:31 被阅读0次

    一.内置类属性

    内置类属性就是魔法属性,魔法属性:属性名的前面和后面都有两个下划线.魔法方法:方法的前后都有两个下划线

    class Person:
        """人类"""
        # 类的字段
        number = 61
    
        def __init__(self, name1, age1, height1):
            # 对象的属性
            self.name = name1
            self.age = age1
            self.height = height1
    
        # 对象方法
        def run(self):
            print('%s在跑步' % self.name)
    
        # 类方法
        @classmethod
        def show_number(cls):
            print('人类的数量为:%d亿' % cls.number)
    
        # 静态方法
        @staticmethod
        def destroy():
            print('人类在破坏环境!')
    
    #1.__name__属性----类的名字(是个字符串)
    #类的属性
    name = Person.__name__
    print(name, type(name), type(Person))
    #Person <class 'str'> <class 'type'>
    
    # 2.__class__属性  --- 获取对象对应类(是一个类)
    #对象的属性
    my_class=p1.__class__
    #my_class是一个类,之前类做的事他都能做
    p2 = my_class('小明',20,180)
    print(p2.name,my_class.__name__)
    #小明 Person
    
    #3.__dict__属性----将对象属性及其对应的值转换成键值对存到一个字典中
    print(p1.__dict__)
    # {'name': '张三', 'age': 28, 'height': 170}
    
    # 4.__doc__属性  --- 获取类的说明文档
    # 类的属性
    doc = Person.__doc__
    print(doc)
    #人类
    
    # 5.__module__属性 --- 获取类所在的模块对应的名字
    print(Person.__module__)
    #__main__
    
    # 6.__bases__属性 --- 获取当前类的父类
    # 类的属性
    print(Person.__bases__)
    #(<class 'object'>,)
    
    

    二.slots魔法

    通过slots中存的元素的属性的值来约束当前这个类的对象的属性.对象的属性只能比元祖中的元素少,不能多

    class Person:
      __slots__=('name','age','face')
      def __init__(self):
        self.name='张三'
        self.age=18
        self.face=70
    
    p1=Person()
    #p1.sex='girl'
    #print(p1.sex) 会报AttributeError
    
    

    注意:一旦在类中给slots属性赋了值,那么这个类的对象dict属性就不能使用了

    三.属性的私有化

    python中并没有真正的私有化,python的类中默认的属性和方法都是公开的

    1.私有化
    a.类中的属性和方法都可以通过在属性名和方法名前加两个下划线,来让属性和方法变成私有的.
    b.私有的属性和方法只能在当前的类中使用

    class Dog:
        # 字段
        number = 100
        __count = 200
    
        def __init__(self):
            # 对象的属性
            self.color = '黄色'
            self.age = 3
            self.name = '大黄'
            self.__sex = '公狗'
    
        # 对象方法
        def __eat(self):
            print('%s啃骨头~' % self.name)
    
        def eat(self):
            # 在类中可以使用私有的属性和方法
            self.__eat()
            print('%s在吃饭~' % self.name)
    
        # 类方法
        @classmethod
        def shout(cls):
            print('count:', cls.__count, Dog.__count)
            print('汪汪汪~~~')
    
        @classmethod
        def __shout(cls):
            print('count:', cls.__count, Dog.__count)
            print('汪汪汪~~~')
    
        # 静态方法
        @staticmethod
        def function():
            print('看家!!')
    
    # python的类中默认的属性和方法都是公开的
    dog1 = Dog
    print(Dog.number)
    #100
    print(dog1.name, dog1.color, dog1.age)
    #大黄 黄色 3
    dog1.eat()
    #大黄啃骨头~
    #大黄在吃饭~
    Dog.shout()
    #count: 200 200
    #汪汪汪~~~
    # 在类的外面不能直接使用私有的属性
    # print(Dog.__count)   
    # AttributeError: type object 'Dog' has no attribute '__count'
    
    

    2.私有化的原理:在前面有两个下划线的属性名和方法名前添加了'_类名'来阻止外部通过直接访问属性名来使用属性

    四.属性的getter和setter

    1.保护类型的属性:
    a.在声明对象属性的时候,在属性名前加一个下划线,表示这个属性是受保护的属性,以后访问这个属性要通过getter来获取属性的值和setter给属性赋值
    b.如果一个属性已经声明成保护类型的属性,我们需要给这个属性添加getter,而setter视需求添加

    2.添加getter
    添加getter其实就是声明一个没有参数有一个返回值的函数

    格式:@property
    def 去掉下划线的属性名(self):
    函数体中一定要有返回值

    可以使用getter的场景:
    a.获取对象某个属性值之前,想有额外处理,可以给属性添加getter
    b.想要拿到某个属性被使用的时刻
    def下加:count += 1 统计获取总共多少次

    3.添加setter(给属性赋值)
    添加setter就是声明一个有一个参数但是没有返回值的函数

    格式:@去掉下划线的属性名.setter
    def 去掉下划线的属性名(self,参数)
    可以使用setter的场景:
    在给属性赋值前想要再做其他的操作,就给属性添加setter

    class Car:
        def __init__(self):
            self.color = '黄色'
            self.type = '自行车'
            #_price属性是保护类型
            self._price = 2000
    
        #给_price属性添加getter
        @property
        def price(self):
            print('在使用_price属性')
            return self._price/1000
    
        #想要给一个属性添加setter,必须先给这个属性添加getter
        @price.setter
        def price(self,price):
            if isinstance(price,int) or isinstance(price,float):
                self._price = price
            else:
                self._price = 0
    
    car1 = Car()
    print(car1.color)
    
    # 添加完getter后就通过getter去获取属性的值
    # price就是属性_price的getter
    print(car1.price,'k')  # 实质是在调用getter对应的方法
    #在使用_price属性
    #2.0 k
    # 通过setter给_prince属性赋值。实质是在调用setter对应的方法
    car1.price = 1000#赋值
    print(car1.price)#通过getter获取值
    #在使用_price属性
    #1.0
    car1.price = 'abc'
    print(car1.price)
    #0.0
    

    练习:声明一个员工类,其中有一个属性是是否已婚(bool),获取值之前根据存的值返回'已婚'/'未婚'

    class Staff:
    
        def __init__(self, name, salary):
            self.name = name
            self.salary = salary
            self._is_marry = False
    
        @property
        def is_marry(self):
            if self._is_marry:
                return '已婚'
            return '未婚'
    
        @is_marry.setter
        def is_marry(self, marry):
            self._is_marry = marry
    
    
    staff1 = Staff('张三', 10000)
    print(staff1.is_marry)
    #未婚
    staff1.is_marry = True
    print(staff1.is_marry)
    #已婚
    
    

    五.继承

    python中类可以继承,并且支持多继承
    程序中的继承:就是让子类直接拥有父类的属性和方法(继承后父类中的内容不会因为被继承而减少)

    1.继承的语法
    class 子类(父类):
    类的内容

    注意:如果声明类的时候,没有加()写继承,那么这个类会自动继承python的基类object,相当于 class 类名(object):
    python中所有类都是直接或间接地继承自object

    2.能继承什么
    a.所有的属性和方法都能继承
    b.slots值不会继承,但是会影响子类对象的dict属性,不能获取到父类继承下来的属性

    class Person:
        """人类"""
        #字段
        number = 61
    
        #__slots__ = ('name','age')
        def __init__(self,name='张三',age=18):
            self.name = name
            self.age = age
            self.__height = 160
    
        def show_message(self):
            print('姓名:%s 年龄:%d'%(self.name,self.age))
    
        @classmethod
        def show_number(cls):
            print('人类的数量:%d'%cls.number)
    
        @staticmethod
        def complaint():
            print('人类殴打小动物!')
    class Student(Person):
        """学生类"""
        pass
    
    #创建Person类的对象
    p = Person()
    #类的字段可以继承
    print(Student.number)
    #61
    #创建Student类的对象
    stu1 = Student()
    stu1.name = '李四'
    print(stu1.name)
    #李四
    stu1.show_message()
    #姓名:李四 年龄:18
    Student.show_number()
    #人类的数量:61
    Student.complaint()
    #人类殴打小动物!
    stu1.sex = 'girl'
    print(stu1.__dict__)
    #{'name': '李四', 'age': 18, '_Person__height': 160, 'sex': 'girl'}
    

    六.方法的重写

    子类继承父类,拥有了父类的属性和方法以后,还可以再添加自己的方法和属性

    1.添加方法和类的字段
    直接在子类中声明相应的方法和字段

    2.添加对象属性
    对象的属性是通过继承父类的init方法而继承下来的
    如果想要在保留父类的对象的同时添加自己的对象属性,需要在子类的init方法中,
    通过super()去调用父类的init方法

    3.方法的重写
    在子类中重新实现父类的方法,就是重写
    方式一:直接覆盖父类的实现
    方式二:保留父类的功能,再添加其他的功能

    4.类中方法的调用过程(重点掌握)
    先在当前这个类中去找,没有去父类中找,找不到再去父类的父类中找,依次类推,
    如果在基类中没有找到,才崩溃,在第一次找到的位置去调用

    注意:使用super的时候必须是通过super()来代替父类或父类对象

    class Animal:
        """动物类"""
        number = 100
        def __init__(self):
            self.age = 0
            self.sex = '雌'
    
         def shout(self):
            print('嗷嗷叫')
    
        def eat(self):
            print('吃东西')
    
    
    class Cat(Animal):
        """猫类"""
        def __init__(self):
            # 调用父类的init方法
            super().__init__()
            self.name = '小花'
    
        food = '鱼'
    
        def shout(self):
            print(super())
            print('喵喵~')
    
    
    class Dog(Animal):
        """狗类"""
        def shout(self):
            # 通过super()调用父类的方法,保留父类的功能
            super().shout()
            print('汪汪!!')
     
    cat1 = Cat()
    print(cat1.age)
    #0
    print(cat1.name)
    #小花
    cat1.shout()
    #<super: <class 'Cat'>, <Cat object>>
    #喵喵~
    dog1 = Dog()
    dog1.shout()
    #嗷嗷叫
    #汪汪!!
    

    七.init方法的重写

    练习:写一个Person类,拥有属性name,age,sex。要求创建Person对象的时候必须给name和age赋值,sex可赋可不赋
    再写一个Staff类继承自Person类,要求保留Person中所有的属性,并且添加新的属性salary。
    要求创建Staff类的对象的时候,只能给name赋值(必须赋)

    class Person:
        def __init__(self, name1, age1, sex1='boy'):
            self.name = name1
            self.age = age1
            self.sex = sex1
    
    
    class Staff(Person):
        def __init__(self, name):
            super().__init__(name, 18)
            self.salary = 0
    

    八.运算符的重载

    如果希望类的对象支持相应的运算符操作(例如:+, -, *, /, >, <等),就必须实现相应的魔法方法。
    这个过程就叫运算符的重载
    +: add()

    : gt

    一般情况需要对>或者<进行重载,重载后可以通过sort方法直接对对象的列表进行排序

    class Student:
        def __init__(self, name='', age=0, score=0):
            self.name = name
            self.age = age
            self.score = score
    
        # self:+前面的对象
        # other: +后面的对象
        def __add__(self, other):
            return self.score + other.score
    
        # 重载 > 符号
        # 注意:重载>和<可以只重载一个,另外一个对应的功能自动取反
        def __gt__(self, other):
            return self.age > other.age
    
        # 重写魔法方法__str__,用来定制对象的打印样式
        def __str__(self):
            # return '<%s.%s object at 0x%x>' % (self.__module__, self.__class__.__name__, id(self))
            # return 'Student: %s %d %d' % (self.name, self.age, self.score)
            return str(self.__dict__)[1:-1]
    #'name': '小明', 'age': 18, 'score': 90
    
    class Schoolchild(Student):
        def __add__(self, other):
            return self.age + other.age
    stu1 = Student('小明', 18, 90)
    stu2 = Student('老王', 29, 84)
    stu3 = Student('小花', 20, 78)
    
    print(stu1)
    
    all_students = [stu1, stu2, stu3]
    all_students.sort(reverse=True)
    for stu in all_students:
      print(stu.name, stu.age, stu.score)
    
    #老王 29 84
    #小花 20 78
    #小明 18 90
    
    # 父类重载了运算符,子类也能用
        c1 = Schoolchild('小明明', 8, 70)
        c2 = Schoolchild('小花花', 10, 67)
        print(c1+c2)
    #18
    

    相关文章

      网友评论

          本文标题:类和对象

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