美文网首页
Python面向对象

Python面向对象

作者: Recalcitrant | 来源:发表于2019-05-27 17:06 被阅读0次

    目录:
    一、类与对象
    二、访问限制
    三、类属性
    四、类方法
    五、静态方法
    六、继承
    七、组合
    八、单例模式(详细阐述见设计模式)

    Python OPP

    一、类与对象

    1.类的定义

    class ClassName:
        def __new__(cls, *args, **kwargs):
            """
            系统自动调用,无需显式定义
            为对象分配内存,#一、先于构造方法被调用
            :param args:
            :param kwargs:
            :return:
            """
            print("__new__")
            return super().__new__(cls)
    
        def __init__(self, 参数列表):
            """
            构造方法
            :param 参数1: 
            :param 参数2: 
            .........
            """
            print("__init__")
            self.成员变量1 = 参数1
            self.成员变量2 = 参数2
            .........
            
        def 成员方法1(self, 参数列表):
              print("__new__")
               pass
                
        def 成员方法2(self, 参数列表):
              pass
        
        .........
    

    2.生成对象

    当一个类定义完成之后,可以使用这个类来创建对象。

    对象名 = 类名(参数列表)
    

    参数列表中的参数会被传入构造方法。

    创建对象时,系统先后自动调用__new__方法和__init__方法。
    __new__方法为生成的实例对象分配内存。
    __init__方法为生成的实例对象完成初始化。

    3.isinstance()方法

    isinstance(对象,类)
    

    子类的实例对象也是父类的实例。

    二、访问限制

    _var:变量名前一个下划线来定义,此变量为保护成员protected。只有类及其子类可以访问。此变量不能通过from XXX import xxx 导入
    __var:变量名前两个下划线来定义,此变量为私有成员private。只允许类本身访问,连子类都不可以访问。
    __var__:系统定义的特殊成员。

    1.私有成员

    定义方式

    在定义属性或方法时,在属性名或者方法名前增加两个下划线__即可。
    双下划线开头的属性名或者方法名会被转换为:_类名__属性名(方法名)

    访问方式

    • 1.通过自定义get,set方法提供私有属性的访问接口
      示例:
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.__age = age
    
        # 定义对私有属性获取的get方法,获取私有属性
        def get_age(self):
            return self.__age
    
        # 定义对私有属性重新赋值的set方法,重置私有属性
        def set_age(self, age):
            self.__age = age
    

    通过set方法可以实现对属性赋值的规范化。

    • 2.调用property方法提供私有属性的访问

    property()方法:

    property(fget=None, fset=None, fdel=None, doc=None)
    

    fget :用于获取属性值的函数
    fset :用于设置属性值的函数
    fdel :用于删除属性值的函数
    doc :属性对象创建文档字符串

    示例:

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.__age = age
    
        # 定义对私有属性的get方法,获取私有属性
        def getAge(self):
            return self.__age
    
        # 定义对私有属性的重新赋值的set方法,重置私有属性
        def setAge(self, age):
            self.__age = age
    
        p = property(getAge, setAge)       # 注意里面getAge,setAge不能带()
    
    
    s1 = Person("jack", 22)
    s1.p = 23       # 如果使用=,则会判断为赋值,调用setAge方法。
    print(s1.name, s1.p)     # jack 23   ,直接使用s1.p会自动判断会取值,调用getAge
    
    运行结果
    • 3.使用@property标注提供私有属性的访问

    在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把变量随便改。
    使用@property装饰器使得变量既可以通过getter和setter方法来获取和设置,又可以使得操作与直接暴露一致。

    @property           # get方法装饰器
    @变量名.setter       # set方法装饰器
    

    示例:

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.__age = age
    
        @property           # @proterty下面默认跟的是get方法,如果设置成set会报错。
        def age(self):
            return self.__age
    
        @age.setter         # set方法
        def age(self, age):
            self.__age = age
    
    
    s1 = Person("jack", 22)
    s1.age = 23
    print(s1.name, s1.age)
    
    运行结果

    2.保护成员

    定义方式

    在定义属性或方法时,在属性名或者方法名前增加一个下划线_即可。
    单下划线开头的属性名或者方法名会被转换为:_属性名(方法名)

    访问方式

    本类及其子类可直接访问。

    三、类属性

    类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,与C++、Java中类的静态成员变量类似。
    示例:

    class Person:
        count = 0
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
            Person.count += 1
    
    
    s1 = Person("Zhangsan", 20)
    s2 = Person("Lisi", 22)
    s3 = Person("Wangwu", 25)
    print(s1.__dict__)
    print(s2.__dict__)
    print(s3.__dict__)
    print(Person.count)
    
    运行结果

    对象的__dict__属性查看不到类属性。

    四、类方法

    通过@classmethod装饰器修饰的方法即为类方法。

    类方法的第一个参数必须是类对象,一般以cls作为第一个参数(当然也可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字),通过类对象或实例对象去访问。
    示例:

    class Person:
        country = "China"
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        @classmethod
        def creat_person(cls, name, age):
            print(cls)
            person = cls(name, age)
            person.name = name
            person.age = age
            return person
    
        @classmethod
        def get_country(cls):
            return cls.country
    
        @classmethod
        def set_country(cls, country):
            cls.country = country
    
    
    s1 = Person.creat_person("Zhangsan", 20)
    print(s1.get_country())         # 实例对象调用类方法
    print(Person.get_country())     # 类对象调用类方法
    
    Person.set_country("USA")
    print(s1.get_country())         # 实例对象调用类方法
    print(Person.get_country())     # 类对象调用类方法
    
    运行结果

    类方法的一个用途就是用于对类属性进行获取与设置。

    五、静态方法

    通过@staticmethod装饰器修饰的方法即为静态方法。

    静态方法的参数无规定,可当作普通函数,一般用于写工具类,通过类对象或实例对象调用。
    示例:

    class Person:
        country = "China"
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        @staticmethod
        def sum_age(age1, age2):
            return age1 + age2
    
        @staticmethod
        def get_country():
            return Person.country
    
    
    s1 = Person("Zhangsan", 20)
    s2 = Person("Lisi", 22)
    print(Person.sum_age(s1.age, s2.age))
    print(Person.get_country())
    
    运行结果

    六、继承

    1.继承语法

    class 类名(父类名1, 父类名2, ......):
        pass
    

    子类 继承自 父类,可以直接享受父类中已经封装好的方法,无需再次开发。
    父类 的方法实现不能满足 子类 需求时,可以对方法进行 重写(override)
    子类 中应该根据 职责,封装子类特有的 属性和方法

    2.继承顺序

    父类的继承顺序与继承书写顺序有关。

    3.类的__mro__属性

    返回一个类元组,在方法解析查找基类时将考虑的类的顺序。
    示例:

    class A:
        def __init__(self):
            pass
    
    
    class B:
        def __init__(self):
            pass
    
    
    class C(A, B):
        def __init__(self):
            super().__init__()
    
    
    print(C.__mro__)
    
    运行结果

    object类是所有类的父类。

    七、组合

    类的组合:在一个类中以另外一个类的对象作为属性。
    示例:

    class A:
        def __init__(self):
            self.name = 'A'
    
    
    class B:
        def __init__(self):
            self.name = 'B'
    
    
    class C:
        def __init__(self):
            self.a = A()
            self.b = B()
            self.name = 'C'
    
    
    c = C()
    print(c.a.name)
    print(c.b.name)
    print(c.name)
    
    运行结果

    组合优于继承:多重继承时,只能继承一个同名属性(第一个父类的属性)。

    八、单例模式

    单例模式:一个类只能生成一个实例对象。即先创建一个类的实例对象,之后不管创建多少个,返回的永远都是第一个实例对象的内存地址。
    示例:

    class S:
        instance = None
    
        def __new__(cls, *args, **kwargs):
            if S.instance is None:
                S.instance = super().__new__(cls)
    
        def __init__(self):
            pass
    
    
    s1 = S()
    print(id(s1))
    s2 = S()
    print(id(s2))
    
    运行结果

    相关文章

      网友评论

          本文标题:Python面向对象

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