zoukankan      html  css  js  c++  java
  • Python基础-类与对象

    类的基本使用

    class Person():
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def info(self):
            print(f'大家好,我是{self.name},我今年{self.age}岁了')
    
    
    xiaohua = Person('小花',21)
    xiaohua.info()

    打印结果:

    大家好,我是小花,我今年21岁了

    python里面的类,架子大概就是这个样子,__init__就是构造函数,所有的方法的第一个形参都是self,这个不是关键字,命名为self是行业默认写法,你把self改成abc也行,重点是第一个形参,进来的都是当前实例对象,对标其他编程语言的this。

    属性的存取

    正常存取

    python里面没有私有属性这个东西,默认全部都是public

    class Person():
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def info(self):
            print(f'大家好,我是{self.name},我今年{self.age}岁了')
    
    
    xiaohua = Person('小花',21)
    print(f'年龄是:{xiaohua.age}')
    xiaohua.age = 22
    print(f'改变后的年龄是:{xiaohua.age}')

    打印结果:

    年龄是:21
    改变后的年龄是:22

    存取器

    python的存取器实际上是用了小花招,它允许你定义属性或者方法的名字前面加上两个下划线,它会对这种格式的名称进行转换,转换后名称也就变了,外部就访问不到该属性,所以就有了私有属性的效果。

    class Person():
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def info(self):
            print(f'大家好,我是{self.__name},我今年{self.__age}岁了')
    
    
    xiaohua = Person('小花',21)
    xiaohua.info()
    print(f'年龄是:{xiaohua.__age}')

    xiaohua.info()这一行是可以正常打印出信息,但是下面一行就会报错,报错原因是没有__age这个属性。

    我们鉴于这种玩法,就可以做出存取器方法

    class Person():
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def info(self):
            print(f'大家好,我是{self.__name},我今年{self.__age}岁了')
    
        def get_age(self):
            return self.__age
    
        def set_age(self,age):
            self.__age = age
    
    xiaohua = Person('小花',21)
    xiaohua.info()
    xiaohua.set_age(23)
    xiaohua.info()

    打印结果:

    大家好,我是小花,我今年21岁了
    大家好,我是小花,我今年23岁了

    但是事实上,私有属性只能成为一种程序员之间的约定,它是拦不住人的,因为python把带两个下划线打头的属性转换后的结果是有规则的,它会转换成一个下划线+类名+原属性名。

    class Person():
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def info(self):
            print(f'大家好,我是{self.__name},我今年{self.__age}岁了')
    
        def get_age(self):
            return self.__age
    
        def set_age(self,age):
            self.__age = age
    
    
    xiaohua = Person('小花',21)
    xiaohua.info()
    xiaohua._Person__age = 22
    xiaohua.info()

    打印结果:

    大家好,我是小花,我今年21岁了
    大家好,我是小花,我今年22岁了

    特性

    在新版的python3中,提供了property函数,可以关联到存取方法,实际上它是一个类,只不过我们用起来是函数的用法。

    class Person():
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def info(self):
            print(f'大家好,我是{self.__name},我今年{self.__age}岁了')
    
        def get_age(self):
            print(f'这是类里面-我正在读取age的值:{self.__age}')
            return self.__age
    
        def set_age(self,age):
            print(f'这是类里面-我正在设置age的值:{age}')
            self.__age = age
    
        def del_age(self):
            print(f'这是类里面-我正在删除age:{self.__age}')
            del self.__age
    
        age = property(get_age,set_age,del_age)
    
    xiaohua = Person('小花',21)
    xiaohua.info()
    xiaohua.age = 18
    xiaohua.info()
    print(f'我在外面读取age的值:{xiaohua.age}')
    del xiaohua.age

    打印结果:

    大家好,我是小花,我今年21岁了
    这是类里面-我正在设置age的值:18
    大家好,我是小花,我今年18岁了
    这是类里面-我正在读取age的值:18
    我在外面读取age的值:18
    这是类里面-我正在删除age:18

    示例中property传入了三个参数,顺序分别是读取方法,设置方法,删除方法,如果都不传,那么该特性将不可读也不可写,传了哪个方法就拥有哪个功能,有第四个可选参数,传入一个文档字符串。

    property也可以当成装饰器用

    class Person():
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def info(self):
            print(f'大家好,我是{self.__name},我今年{self.__age}岁了')
    
        @property
        def age(self):
            print(f'这是类里面-我正在读取age的值:{self.__age}')
            return self.__age
    
        @age.setter
        def age(self,age):
            print(f'这是类里面-我正在设置age的值:{age}')
            self.__age = age
    
    xiaohua = Person('小花',21)
    xiaohua.info()
    xiaohua.age = 18
    xiaohua.info()
    print(f'我在外面读取age的值:{xiaohua.age}')

    打印结果:

    大家好,我是小花,我今年21岁了
    这是类里面-我正在设置age的值:18
    大家好,我是小花,我今年18岁了
    这是类里面-我正在读取age的值:18
    我在外面读取age的值:18

    继承

    常规继承

    继承的写法是在类定义的时候类名后面的括号里传入父类名称

    class Person():
        def info(self):
            print('人类正在统治世界')
    
    class student(Person):
        def __init__(self):
            print('我是一名小学生')
    
    p = student()
    p.info()

    打印结果:

    我是一名小学生
    人类正在统治世界

    访问父类方法

    在python中访问父类方法用一个特殊的函数 : super()

    class Person():
        def info(self):
            print('人类正在统治世界')
    
    class student(Person):
        def __init__(self):
            super().info()
            print('我是一名小学生')
    
    p = student()

    打印结果:

    人类正在统治世界
    我是一名小学生

    如果是初始化类的时候要调用父类的构造函数,也是一样的调用方式:

    class Person():
        def __init__(self,name):
            self.__name = name
    
        def info(self):
            print(f'人类正在统治世界:{self.__name}')
    
    class student(Person):
        def __init__(self,name):
            super().__init__(name)
    
    p = student('阿西吧')
    p.info()

    打印结果:

    人类正在统治世界:阿西吧

    方法重写

    子类将父类的方法进行重写覆盖

    class Person():
        def info(self):
            print('人类正在统治世界')
    
    class student(Person):
        def info(self):
            print('小学生正在统治世界')
    
    p = student()
    p.info()

    打印结果:

    小学生正在统治世界

    多重继承

    多重继承虽然很强大,也很容易成为车祸现场,多个父类中如果有构造函数如果有同名方法都将搞得你头晕脑胀,正常情况下,应该避免使用多重继承,除非忍不住。。。

    class Person():
        def info(self):
            print('人类正在统治世界')
    
    class Young():
        def young_info(self):
            print('年轻人太天真')
    
    class student(Person,Young):
        def __init__(self):
            print('小学生正在统治世界')
    
    p = student()
    p.info()
    p.young_info()

    打印结果:

    小学生正在统治世界
    人类正在统治世界
    年轻人太天真

    类型校验

    class Person():
        def info(self):
            print('人类正在统治世界')
    
    class Young():
        def young_info(self):
            print('年轻人太天真')
    
    class student(Person,Young):
        def __init__(self):
            print('小学生正在统治世界')
    
    
    a = issubclass(student,Person)
    print(f'是不是子类:{a}')
    
    x = student.__bases__
    print(f'父类是:{x}')
    
    s = student()
    z = isinstance(s,student)
    print(f'是不是实例:{z}')

    打印结果:

    是不是子类:True
    父类是:(<class '__main__.Person'>, <class '__main__.Young'>)
    小学生正在统治世界
    是不是实例:True

    是不是实例判断  如果和父类进行判断也算是实例。

    抽象接口

    面向接口编程的时候都是先定义接口,然后子类去实现接口实现方法,在python3中引入了abc模块,可以帮助我们定义抽象接口

    import abc
    
    class Person(metaclass=abc.ABCMeta):
    
        @abc.abstractmethod
        def eat(self):
            pass
    
    
    class student(Person):
    
        def eat(self):
            print('小学生也可以吃饭')
    
    
    x = student()
    x.eat()

    打印结果:

    小学生也可以吃饭

    抽象类中定义的接口在子类中必须实现

    静态方法

    class student():
    
        remark = '我是祖国的花朵'
    
        @classmethod
        def sing(cls):
            print('小学生也可以唱歌 ' + cls.remark)
    
        @staticmethod
        def eat():
            print('小学生也可以吃饭')
    
    student.eat()
    student.sing()

    打印结果:

    小学生也可以吃饭
    小学生也可以唱歌 我是祖国的花朵

    两种装饰器可以定义静态方法,注意区别,@classmethod装饰的方法有默认参数cls,表示当前类,可以取到属性。

  • 相关阅读:
    EXT性能优化(转载)
    xampp 下配置mail()函数发邮件
    从存储过程中返回结果 (转载)
    HDU1394 Minimum Inversion Number
    HDU4414 Finding crosses
    POJ1328 Radar Installation
    HDU3308 LCIS
    POJ2352 Stars
    POJ2513 Colored Sticks
    HDU4027 Can you answer these queries?
  • 原文地址:https://www.cnblogs.com/fengyumeng/p/13292014.html
Copyright © 2011-2022 走看看