zoukankan      html  css  js  c++  java
  • Python面向对象的编程

    在上一章节中,看书自学python-socket编程里面发现很多问题,一个重点是不知道python的class是什么,总是在百度每一句代码是什么意思,发现好像问题挺大的,万一后面还出现了class怎么办,难道每一句百度???,果断百度“python面向对象编程”,以下是学习python面向对象编程的一些心得,原文来自武沛齐,很多地方自己改了一下

    大纲

    1、创建类和对象

    2、面向对象的三大特性

     

    创建类和对象

    面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。

      类就是一个模板,模板里可以包含多个函数,函数里实现一些功能

      对象则是根据模板创建的实例,通过实例对象可以执行类中的函数

      从知乎上面看到这样一句话,不知道是对是错,反正我理解不了,感觉太高深

    实例就是对象在内存中开辟了空间。
    父母口中的女朋友(对象),怀里搂着的她(实例)。

    创建一个类:

    # 创建类
    class Foo:
      #类中定义的函数叫方法 def Bar(self):  #类中的函数第一个参数必须是self print("bar") def Hello(self, name): print("i am %s" % name) # 根据类Foo创建对象obj obj = Foo() # 相当于拿到类里面的所有方法(函数),当然,这是我自己得理解 # Foo().Bar() obj.Bar() # 执行Bar方法 obj.Hello("smelond") # 执行Hello方法

    # 面向对象:【创建对象】【通过对象执行方法】
    # 函数编程:【执行函数】

    面向对象三大特性

    一、封装

    封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

    所以,在使用面向对象的封装特性时,需要:

    • 将内容封装到某处
    • 从某处调用被封装的内容

    第一步:将内容封装到某处

    # 创建类
    class Foo:
        def __init__(self, name, age):  # 称为构造方法,根据类创建对象时自动执行
            self.name = name
            self.age = age
    
    
    # 根据类Foo创建对象
    #  自动执行Foo类的__init__方法
    obj1 = Foo("wupeiqi", 18)  # 将wupeiqi和16分别封装到(obj1、self)的name和age属性中
    
    # 根据类Foo创建对象
    #  自动执行Foo类的__init__方法
    obj2 = Foo("smelond", 16)  # 将smelond和16分别封装到(obj2、self)的name和age属性中
    

     self 是一个形式参数,当执行 obj1 = Foo('wupeiqi', 18 ) 时,self 等于 obj1

                                  当执行 obj2 = Foo('alex', 78 ) 时,self 等于 obj2

    所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存。

     第二步:从某处调用被封装的内容

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

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

    1、通过对象直接调用被封装的内容

    调用方式:对象.属性名

    通过上面的代码直接调用封装的内容
    print(obj1.name)
    print(obj1.age)
    print(obj2.name)
    print(obj2.age)
    
    输出
    wupeiqi
    18
    smelond
    16
    

     2、通过self间接调用被封装的内容

    # 通过self间接调用
    class Foo:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def detail(self):
            print(self.name)
            print(self.age)
    
    
    obj1 = Foo('wupeiqi', 18)
    obj1.detail()  # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18
    
    obj2 = Foo('smelond', 16)
    obj2.detail()  # Python默认会将obj2传给self参数,即:obj2.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 smelond ; self.age 是 17
    
    输出:
    wupeiqi
    18
    smelond
    16
    

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

    练习

    在终端输出如下信息

    • 小明,10岁,男,上山去砍柴
    • 小明,10岁,男,开车去东北
    • 小明,10岁,男,最爱大保健
    • 老李,90岁,男,上山去砍柴
    • 老李,90岁,男,开车去东北
    • 老李,90岁,男,最爱大保健
    • 老张...
    def kanchai(name, age, gender):
        print "%s,%s岁,%s,上山去砍柴" %(name, age, gender)
    
    
    def qudongbei(name, age, gender):
        print "%s,%s岁,%s,开车去东北" %(name, age, gender)
    
    
    def dabaojian(name, age, gender):
        print "%s,%s岁,%s,最爱大保健" %(name, age, gender)
    
    
    kanchai('小明', 10, '')
    qudongbei('小明', 10, '')
    dabaojian('小明', 10, '')
    
    
    kanchai('老李', 90, '')
    qudongbei('老李', 90, '')
    dabaojian('老李', 90, '')
    函数式编程
    class Foo:
        
        def __init__(self, name, age ,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def kanchai(self):
            print "%s,%s岁,%s,上山去砍柴" %(self.name, self.age, self.gender)
    
        def qudongbei(self):
            print "%s,%s岁,%s,开车去东北" %(self.name, self.age, self.gender)
    
        def dabaojian(self):
            print "%s,%s岁,%s,最爱大保健" %(self.name, self.age, self.gender)
    
    
    xiaoming = Foo('小明', 10, '')
    xiaoming.kanchai()
    xiaoming.qudongbei()
    xiaoming.dabaojian()
    
    laoli = Foo('老李', 90, '')
    laoli.kanchai()
    laoli.qudongbei()
    laoli.dabaojian()
    面向对象

    从上可以看出如果是函数式编程,会复制很多代码,而通过面向对象,只需要将参数封装到当前对象中,通过self去间接调用取值即可。

    二、继承

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

    例如:

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

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

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

    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("汪汪叫 %s" % self.breed)
    
    
    c1 = Cat("小白家的小黑猫")
    c1.eat()
    c2 = Cat("小黑家的小白猫")
    c2.drink()
    c3 = Dog("胖子家的小瘦狗")
    c3.eat()
    
    
    输出:
    小白家的小黑猫 吃
    小黑家的小白猫 喝
    胖子家的小瘦狗 吃
    代码实例

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

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

    三、多态 

     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#的多态
    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 “鸭子类型”
    作者:smelond
             
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Salesforce LWC学习(三十七) Promise解决progressindicator的小问题
    Salesforce Consumer Goods Cloud 浅谈篇三之 行动计划(Action Plan)相关配置
    python 3.7环境安装并使用csv
    分享数据库优化文章
    php 5.4 var_export的改进
    CentOS7 启动 firewalld 防火墙失败,查看日志提示超时
    使用 SSL 加密的 JDBC 连接 SAP HANA 数据库
    CAS学习笔记一:CAS 授权服务器简易搭建
    202110期自考总结
    自定义 OpenShift s2i 镜像与模板——OracleJDK8
  • 原文地址:https://www.cnblogs.com/smelond/p/8321658.html
Copyright © 2011-2022 走看看