• python 面向对象


    面向对象技术简介

    • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
    • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
    • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
    • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
    • 实例变量:定义在方法中的变量,只作用于当前实例的类。
    • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
    • 实例化:创建一个类的实例,类的具体对象。
    • 方法:类中定义的函数。
    • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

    一、类

      用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

    二、对象

      对象是类的实例,比如字符串的基类是str(),那么可以以下的操作来实例化这个类,从而获取对象

        name = str()

      这样就得到了一个那么对象,它具有str类所拥有的的所有属性和方法

      例如:  peple是一个类,x就是这个类的对象

        class peple():
        def __init__(self, name):
        self.Name = name
        def chi(self):
        print(self.Name)
        x = peple("yangyongming")

    三、类对象

    类对象支持两种操作:字段引用和实例化。

    字段引用使用和 Python 中所有的属性(字段)引用一样的标准语法:obj.name:如下:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    # !/usr/bin/python3
    
    class MyClass:
        """一个简单的类实例"""
        # 这是一个静态字段
        i = 12345
    
        # 这是一个静态方法
        def f(self):
            return 'hello world'
    
    # 实例化类,得到一个类对象x
    x = MyClass()
    
    # 访问类的属性和方法
    print("MyClass 类的属性 i 为:", x.i)
    print("MyClass 类的方法 f 输出为:", x.f())
    View Code
    MyClass 类的属性 i 为: 12345
    MyClass 类的方法 f 输出为: hello world
    
    Process finished with exit code 0
    View Code

    四、构造方法

    用于初始化类的内容属性的,Python提供的构造函数式 __init__()。

    __init__()方法是可选的。

    当该类被实例化的时候就会执行该函数,我们可以把要先初始化的属性放到这个函数里面,如下程序:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    class Complex:
    
        # 这是一个构造方法
        def __init__(self, realpart, imagpart):
            # 这是一个普通字段
            self.r = realpart
            self.i = imagpart
    
    
    # 实例化类
    x = Complex(3.0, -4.5)  # 在这个过程中构造函数就会被自动执行
    print(x.r, x.i)  # 输出结果:3.0 -4.5
    实例:
    3.0 -4.5
    
    Process finished with exit code 0
    运行结果 

    五、类中的self参数

    类中出现的self字样代表类的实例(对象),而非类本身

    类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self,当然写成其他的名称也可以,但是还是写成官方的好一些o(* ̄︶ ̄*)o,如下代码:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    
    class Test:
        def prt(self):
            print(self)
            print(self.__class__)
    
    
    t = Test()
    t.prt()
    代码
    <__main__.Test object at 0x000001AA1763C9B0>
    <class '__main__.Test'>
    
    Process finished with exit code 0
    运行结果

    从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。

    self 不是 python 关键字,我们把他换成 其他字符也是可以正常执行的:

    在类中,任何加了self的字段或者方法,在类中的任何地方都可以调用,如下:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    class Complex:
    
        # 这是一个构造方法
        def __init__(self, arg1, arg2):
            # 这是一个普通字段
            self.r = arg1
            self.i = arg2
        def one(self):
            print(self.r)
        def two(self):
            self.one()
    
    a = Complex(100, 200)
    
    a.one()
    a.two()
    实例:self调用字段和方法,在任何地方
    100
    100
    
    Process finished with exit code 0
    运行结果

    六、类的成员

    类的成员可以分为三大类:字段、方法和属性

    注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。

    (1)、类的字段

    类的字段有两种,一个是普通字段,一个是静态字段:

    静态字段:在类中,方法之外,通过类名来调用。

    普通字段:常出现在构造方法内,通过对象来调用。

    • 普通字段属于对象
    • 静态字段属于
    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    class Foo:
        # 这是一个静态字段
        i = "123456"
    
        # 这是一个构造方法
        def __init__(self, name):
            # 这是一个普通字段
            self.Name = name
    
    
    # 实例化类
    r = Foo("MING")
    
    # 访问静态字段
    print(Foo.i)
    
    # 访问普通字段
    print(r.Name)
    代码实例
    123456
    MING
    
    Process finished with exit code 0
    运行结果

    通过以上代码可以看出对于静态字段的调用,通过类调用(也可以通过对象调用,但是不推荐使用对象来调用),因为在其他的语言中是不支持这种调用方式。

    • 静态字段在内存中只保存一份
    • 普通字段在每个对象中都要保存一份

    应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段

    (2)、类的方法

    在类地内部,使用 def 关键字来定义一个方法。

    方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

    • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
    • 类方法:由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls;使用@classmethod标注。
    • 静态方法:由调用;无默认参数;使用@staticmethod标注。
    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    class peple():
    
        live = "yes"
    
        def __init__(self, name):
            self.Name = name
    
        def chi(self):
            print(self.live)
            print(self.Name)
    
    x = peple("ming")
    
    x.chi()
    普通方法
    yes
    ming
    
    Process finished with exit code 0
    运行结果

    普通方法可以使用类中的任何属性

    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    class peple():
    
        live = "yes"
    
        def __init__(self, name):
            self.Name = name
    
        @staticmethod
        def chi():
            print(live)
            print(self.Name)
    
    peple.chi()
    静态方法
    Traceback (most recent call last):
      File "C:/Users/Administrator/PycharmProjects/untitled2/Practice/11/1.py", line 17, in <module>
        peple.chi()
      File "C:/Users/Administrator/PycharmProjects/untitled2/Practice/11/1.py", line 15, in chi
        print(live)
    NameError: name 'live' is not defined
    
    Process finished with exit code 1
    运行结果

    静态方法不能使用类中的任何属性

    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    class peple():
    
        live = "yes"
    
        def __init__(self, name):
            self.Name = name
    
        @classmethod
        def chi(cls):
            print(cls.live)
    
        @classmethod
        def he(cls):
            print(cls.Name)
    
    peple.chi()
    peple.he()
    静态方法
    Traceback (most recent call last):
    yes
      File "C:/Users/Administrator/PycharmProjects/untitled2/Practice/11/1.py", line 22, in <module>
        peple.he()
      File "C:/Users/Administrator/PycharmProjects/untitled2/Practice/11/1.py", line 19, in he
        print(cls.Name)
    AttributeError: type object 'peple' has no attribute 'Name'
    
    Process finished with exit code 1
    运行结果

    类方法只能使用类的静态属性(不带self的),类不能使用方法属性(带self的)

    相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。

    不同点:方法调用者不同、调用方法时自动传入的参数不同。

     (3)、类的属性

    。。。。。。

    七、类成员修饰符

    对于每一个类的成员而言都有两种形式:

    • 公有成员,在任何地方都能访问
    • 私有成员,只有在类的内部才能方法

    私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)

    #!/usr/bin/env python
    # -*- coding: utf-8 -*
    # Created by YangYongming at 2018/11/26 12:27
    # FileName: 1.py
    
    class ming:
    
        chi = "这是公有静态字段"
        __he = "这是私有静态字段"
    
        def __init__(self):
            self.name = "这是公有普通字段"
            self.__foo = "这是私有普通字段"
        def one(self):
            return "这是公有普通方法"
        def __two(self):
            return "这是私有普通方法"
    
    x = ming()
    
    print(ming.chi)
    print(x.name)
    print(x.one())
    示例代码:类外访问公有成员
    这是公有静态字段
    这是公有普通字段
    这是公有普通方法
    
    Process finished with exit code 0
    运行结果

    类外访问私有成员:报错

    • 公有成员:对象可以访问;类内部可以访问;派生类中可以访问
    • 私有成员:仅类内部可以访问;

    通过以上代码可以看出,普通方法、静态方法使用成员修饰符后,该方法在类外部是无法访问的,在类内部是可以访问的,该种方法是不可以被继承的

    私有的成员也不是绝对不可以访问,我们可以通过下面这种方式访问:

    class Mo():
        def __one(self):
            print("one")
    obj = Mo()
    obj._Mo__one()  # 特殊的访问方式,但是不建议使用
    
    # 运行结果
    # one

    八、类的特殊成员

    (1). __doc__

      表示类的描述信息

    (2). __init__

      构造方法,通过类创建对象时,自动触发执行。

    (3). __del__

      析构方法,当对象在内存中被释放时,自动触发执行。

      注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

    (4). __call__

      对象后面加括号,触发执行。

      注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    (5). __dict__

      类或对象中的所有成员

    (6) . __str__

      如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。

    (7) . __class__    

      表示当前操作的对象的类是什么

    (8) . __module__

      表示当前操作的对象在那个模块

     九、面向对象三大特性

    面向对象的三大特性是指:封装、继承和多态。

    (1)封装

      对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

      调用被封装的内容时,有两种情况:

    • 通过对象直接调用
    • 通过self间接调用

    (2)继承

      继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

      例如:

        猫可以:喵喵叫、吃、喝、拉、撒

        狗可以:汪汪叫、吃、喝、拉、撒

      如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,如下所示:

    class 猫:
    
        def 喵喵叫(self):
            print '喵喵叫'
    
        def 吃(self):
            # do something
    
        def 喝(self):
            # do something
    
        def 拉(self):
            # do something
    
        def 撒(self):
            # do something
    
    class 狗:
    
        def 汪汪叫(self):
            print '喵喵叫'
    
        def 吃(self):
            # do something
    
        def 喝(self):
            # do something
    
        def 拉(self):
            # do something
    
        def 撒(self):
            # do something
    
    伪代码
    代码

    上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:

      动物:吃、喝、拉、撒

         猫:喵喵叫(猫继承动物的功能)

         狗:汪汪叫(狗继承动物的功能)

    class 动物:
    
        def 吃(self):
            # do something
    
        def 喝(self):
            # do something
    
        def 拉(self):
            # do something
    
        def 撒(self):
            # do something
    
    # 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
    class 猫(动物):
    
        def 喵喵叫(self):
            print '喵喵叫'
            
    # 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
    class 狗(动物):
    
        def 汪汪叫(self):
            print '喵喵叫'
    
    伪代码
    代码

     所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

    注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。

     

    学习了继承的写法之后,我们用代码来是上述阿猫阿狗的功能:

    class Animal:
    
        def eat(self):
            print "%s 吃 " %self.name
    
        def drink(self):
            print "%s 喝 " %self.name
    
        def shit(self):
            print "%s 拉 " %self.name
    
        def pee(self):
            print "%s 撒 " %self.name
    
    
    class Cat(Animal):
    
        def __init__(self, name):
            self.name = name
            self.breed = ''
    
        def cry(self):
            print '喵喵叫'
    
    class Dog(Animal):
        
        def __init__(self, name):
            self.name = name
            self.breed = ''
            
        def cry(self):
            print '汪汪叫'
            
    
    # ######### 执行 #########
    
    c1 = Cat('小白家的小黑猫')
    c1.eat()
    
    c2 = Cat('小黑的小白猫')
    c2.drink()
    
    d1 = Dog('胖子家的小瘦狗')
    d1.eat()
    
    代码实例
    代码实例

    那么问题又来了,多继承呢?

    • 是否可以继承多个类
    • 如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?

    1、Python的类可以继承多个类,Java和C#中则只能继承一个类

    2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先广度优先

     

    • 当类是经典类时,多继承情况下,会按照深度优先方式查找
    • 当类是新式类时,多继承情况下,会按照广度优先方式查找

    经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。

     

    class D:
    
        def bar(self):
            print 'D.bar'
    
    
    class C(D):
    
        def bar(self):
            print 'C.bar'
    
    
    class B(D):
    
        def bar(self):
            print 'B.bar'
    
    
    class A(B, C):
    
        def bar(self):
            print 'A.bar'
    
    a = A()
    # 执行bar方法时
    # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
    # 所以,查找顺序:A --> B --> D --> C
    # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    a.bar()
    
    经典类多继承
    经典类多继承
    class D(object):
    
        def bar(self):
            print 'D.bar'
    
    
    class C(D):
    
        def bar(self):
            print 'C.bar'
    
    
    class B(D):
    
        def bar(self):
            print 'B.bar'
    
    
    class A(B, C):
    
        def bar(self):
            print 'A.bar'
    
    a = A()
    # 执行bar方法时
    # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
    # 所以,查找顺序:A --> B --> C --> D
    # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    a.bar()
    
    新式类多继承
    新式类多继承

    经典类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错

    新式类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错

    注意:在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了

    派生类执行基类构造方法的两种方式

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Author  : Jack.Ming
    class Annimal:
        def __init__(self, weight,hight):
            self.Weight = weight
            self.Hight = hight
    
    class Cat(Annimal):
        def __init__(self, name, weight, hight):
            self.Name = name
            super(Cat, self).__init__(weight ,hight)   #方式1
        def pri(self):
            print(self.Name,self.Weight,self.Hight)
    
    class Dog(Annimal):
        def __init__(self, name, weight, hight):
            self.Name = name
            Annimal.__init__(self, weight,hight)  #方式2
        def pri(self):
            print(self.Name,self.Weight,self.Hight)
    
    A = Cat("cat", 100,200)
    A.pri()
    
    A = Dog("dog", 100,200)
    A.pri()
    View Code

    (3)多态

      Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。

    class F1:
        pass
    
    
    class S1(F1):
    
        def show(self):
            print 'S1.show'
    
    
    class S2(F1):
    
        def show(self):
            print 'S2.show'
    
    
    # 由于在Java或C#中定义函数参数时,必须指定参数的类型
    # 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
    # 而实际传入的参数是:S1对象和S2对象
    
    def Func(F1 obj):
        """Func函数需要接收一个F1类型或者F1子类的类型"""
        
        print obj.show()
        
    s1_obj = S1()
    Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
    
    s2_obj = S2()
    Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
    
    Python伪代码实现Java或C#的多态
    Python伪代码实现Java或C#的多态
    class F1:
        pass
    
    
    class S1(F1):
    
        def show(self):
            print 'S1.show'
    
    
    class S2(F1):
    
        def show(self):
            print 'S2.show'
    
    def Func(obj):
        print obj.show()
    
    s1_obj = S1()
    Func(s1_obj) 
    
    s2_obj = S2()
    Func(s2_obj) 
    
    Python “鸭子类型”
    Python “鸭子类型”

    参考:http://www.cnblogs.com/wupeiqi/articles/5017742.html

  • 相关阅读:
    《学技术练英语》PPT分享
    某网站漏洞排查经验
    【原创】如何写一个框架:模式
    【原创】如何写一个框架:步骤(下)
    【原创】如何写一个框架:步骤(上)
    CentOS 6.5 x64相关安全,优化配置
    CentOS 6.5 x64下查看服务版本
    Xshell设置密钥登录CentOS6.5_64位(文字命令版)
    CentOS 6.5 x64下安装宝塔面板、阿里安骑士
    CentOS 6.5 x64下查找依赖包,或用YUM安装
  • 原文地址:https://www.cnblogs.com/ming5218/p/8136826.html
Copyright © 2020-2023  润新知