分享

Python基础

 YANG158798 2022-07-14 发布于北京

第 1/1 

Python语言的诞生

  • Python的作者,Guido von Rossum(吉多·范·罗苏姆,中国Python程序员都叫他 龟叔),荷兰人。1982年,龟叔从阿姆斯特丹大学获得了数学和计算机硕士学位。然而,尽管他算得上是一位数学家,但他更加享受计算机带来的乐趣。用他的话说,虽然拥有数学和计算机双料资质,他总趋向于做计算机相关的工作,并热衷于做任何和编程相关的事情。

  • 1989年,为了打发圣诞节假期,龟叔开始写Python语言的编译器。Python这个名字,来自龟叔所挚爱的电视剧Monty Python's Flying Circus。他希望这个新的叫做Python的语言,能符合他的理想:创造一种C和shell之间,功能全面,易学易用,可拓展的语言。龟叔作为一个语言设计爱好者,已经有过设计语言的尝试。这一次,也不过是一次纯粹的hacking行为。


Python发展

  • 1991年,第一个Python编译器诞生。它是用C语言实现的,并能够调用C语言的库文件。从一出生,Python已经具有了 :类,函数,异常处理,包含表和词典在内的核心数据类型,以及模块为基础的拓展系统。最初的Python完全由龟叔本人开发。Python得到龟叔同事的欢迎。他们迅速的反馈使用意见,并参与到Python的改进。龟叔和一些同事构成Python的核心团队。他们将自己大部分的业余时间用于hack Python。随后,Python拓 展到研究所之外。Python将许多机器层面上的细节隐藏,交给编译器处理,并凸显出逻辑层面的编程思考。Python程 序员可以花更多的时间用于思考程序的逻辑,而不是具体的实现细节。这一特征吸引了广大的程序员。Python开始流行。


Python 简介

  • Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。

  • Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。

  • Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。

  • Python 是交互式语言: 这意味着,您可以在一个 Python 提示符 >>> 后直接执行代码。

  • Python 是面向对象语言: 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。

  • Python 是初学者的语言:Python 对初级程序员而言,是一种伟大的语言,它支持广泛的应用程序开发,从简单的文字处理到 WWW 浏览器再到游戏。


Python 发展历史

Python 是由 Guido van Rossum 在八十年代末和九十年代初,在荷兰国家数学和计算机科学研究所设计出来的。

Python 本身也是由诸多其他语言发展而来的,这包括 ABC、Modula-3、C、C++、Algol-68、SmallTalk、Unix shell 和其他的脚本语言等等。

像 Perl 语言一样,Python 源代码同样遵循 GPL(GNU General Public License)协议。

现在 Python 是由一个核心开发团队在维护,Guido van Rossum 仍然占据着至关重要的作用,指导其进展。

Python 2.7 被确定为最后一个 Python 2.x 版本,它除了支持 Python 2.x 语法外,还支持部分 Python 3.1 语法。


Python 优点

  • 1.易于学习:Python有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单。

  • 2.易于阅读:Python代码定义的更清晰。

  • 3.易于维护:Python的成功在于它的源代码是相当容易维护的。

  • 4.一个广泛的标准库:Python的最大的优势之一是丰富的库,跨平台的,在UNIX,Windows和Macintosh兼容很好。

  • 5.互动模式:互动模式的支持,您可以从终端输入执行代码并获得结果的语言,互动的测试和调试代码片断。

  • 6.可移植:基于其开放源代码的特性,Python已经被移植(也就是使其工作)到许多平台。

  • 7.可扩展:如果你需要一段运行很快的关键代码,或者是想要编写一些不愿开放的算法,你可以使用C或C++完成那部分程序,然后从你的Python程序中调用。

  • 8.数据库:Python提供所有主要的商业数据库的接口。

  • 9.GUI编程:Python支持GUI可以创建和移植到许多系统调用。

  • 10.可嵌入: 你可以将Python嵌入到C/C++程序,让你的程序的用户获得"脚本化"的能力。

Python语言缺点

  • Python语言非常完善,没有明显的短板和缺点,唯一的缺点就是执行效率慢,这个是解释型语言所通有的,同时这个缺点也将被计算机越来越强大的性能所弥补。

Python基础-面向对象(一)

Python基础-面向对象(一)

  • 面向对象编程介绍

    如今主流的软件开发思想有两种:一个是面向过程,另一个是面向对象。面向过程出现得较早,典型代表为C语言,开发中小型项目的效率很高,但是很难适用于如今主流的大中型项目开发场景。面向对象则出现得更晚一些,典型代表为Java或C++等语言,更加适合用于大型开发场景。两种开发思想各有长短。

    对于面向过程的思想: 需要实现一个功能的时候,看重的是开发的步骤和过程,每一个步骤都需要自己亲力亲为,需要自己编写代码(自己来做)

    对于面向对象的思想:当需要实现一个功能的时候,看重的并不是过程和步骤,而是关心谁帮我做这件事(偷懒,找人帮我做)

    面向对象的三大特征有:封装性、继承性、多态性。

  • 类和对象

    面向对象编程的2个非常重要的概念:类和对象

    对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类

    1. 类

    我们学习编程语言,就是为了模拟现实世界中的事物,实现信息化来提高工作效率。例如银行的业务系统、超市的结账系统等,都是如此。

    面向对象的语言当中,“类”就是用来模拟现实事物的。

    那么模拟现实世界的事物通常从两方面模拟:

    1.1,属性:事物的特征描述信息,用于描述某个特征“是什么”。 静

    1.2,行为:事物的能力行动方案,用于说明事物“能做什么”。

    2. 对象,某一个具体事物的存在就是对象,在现实世界中可以是看得见摸得着的。

    3. 类和对象之间的关系:类就是创建对象的模板

    4. 练习:区分类和对象
    奔驰汽车 类
    奔驰smart 类
    张三的那辆奔驰smart 对象
    狗 类
    大黄狗 类
    李四家那只大黄狗 对象
    水果 类
    苹果 类
    红苹果 类
    红富士苹果 类
    我嘴里吃了一半的苹果 对象

    5. 类的构成

    类(Class) 由3个部分构成:
    类的名称:类名
    类的属性:一组数据
    类的方法:允许对进行操作的方法 (行为)

    举例:

    1)人类设计,只关心3样东西:
    事物名称(类名):人(Person)
    属性:身高(height)、年龄(age)...
    方法(行为/功能):跑(run)、打架(fight)...

    狗类的设计
    类名:狗(Dog)
    属性:品种 、毛色、性别、名字、 腿儿的数量...
    方法(行为/功能):叫 、跑、咬人、吃、摇尾巴...

    6. 类的抽象

    如何把日常生活中的事物抽象成程序中的类?

    拥有相同(或者类似)属性和行为的对象都可以抽像出一个类

    方法:一般名词都是类(名词提炼法)

    <1>坦克发射3颗炮弹轰掉了2架飞机:
    坦克--》可以抽象成 类
    炮弹--》可以抽象成类
    飞机-》可以抽象成类

    <2>小明在公车上牵着一条叼着热狗的狗

    小明--》 人类
    公车--》 交通工具类
    热狗--》 食物类
    狗--》 狗类

  • 定义类

    定义一个类,格式如下:

    1
    2
    3
    4
    # class Hero: # 经典类(旧式类)定义形式
    class Hero(object):   # 新式类定义形式
        def info(self):
            print("英雄不问出处。")

    说明:object 是Python 里所有类的最顶级父类;

    info是一个实例方法,第一个参数一般是self,表示实例对象本身,当然了可以将self换为其它的名字,其作用是一个变量 这个变量指向了实例对象

  • 创建对象

    python中,可以根据已经定义的类去创建出一个或多个对象。

    对象名1 = 类名()
       对象名2 = 类名()
       对象名3 = 类名()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class Hero(object):
        """info 是一个实例方法,类对象可以调用实例方法,实例方法的第一个参数一定是self"""
        def info(self):
            """当对象调用实例方法时,Python会自动将对象本身的引用做为参数,
                传递到实例方法的第一个参数self里"""
            print(self)
            print("self各不同,对象是出处。")
     
    # Hero这个类 实例化了一个对象  taidamier(泰达米尔)
    taidamier = Hero()
    # 对象调用实例方法info(),执行info()里的代码
    # . 表示选择属性或者方法
    taidamier.info()
     
    print(taidamier)  # 打印对象,则默认打印对象在内存的地址,结果等同于info里的print(self)
    print(id(taidamier))  # id(taidamier) 则是内存地址的十进制形式表示
     
    '''输出结果
    <__main__.Hero object at 0x7f96ea060e48>
    self各不同,对象是出处。
    <__main__.Hero object at 0x7f96ea060e48>
    140286148087368
    '''
  • 添加和获取对象的属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    class Hero(object):
        """定义了一个英雄类,可以移动和攻击"""
        def move(self):
            """实例方法"""
            print("正在前往事发地点...")
     
        def attack(self):
            """实例方法"""
            print("发出了一招强力的普通攻击...")
     
    # 实例化了一个英雄对象 泰达米尔
    taidamier = Hero()
     
    # 给对象添加属性,以及对应的属性值
    taidamier.name = "泰达米尔"  # 姓名
    taidamier.hp = 2600  # 生命值
    taidamier.atk = 450  # 攻击力
    taidamier.armor = 200  # 护甲值
     
    # 通过.成员选择运算符,获取对象的属性值
    print("英雄 %s 的生命值 :%d" % (taidamier.name, taidamier.hp))
    print("英雄 %s 的攻击力 :%d" % (taidamier.name, taidamier.atk))
    print("英雄 %s 的护甲值 :%d" % (taidamier.name, taidamier.armor))
     
    # 通过.成员选择运算符,获取对象的实例方法
    taidamier.move()
    taidamier.attack()
     
    '''输出结果
    英雄 泰达米尔 的生命值 :2600
    英雄 泰达米尔 的攻击力 :450
    英雄 泰达米尔 的护甲值 :200
    正在前往事发地点...
    发出了一招强力的普通攻击...
    '''
  • 在方法内通过self获取对象属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    class Hero(object):
        """定义了一个英雄类,可以移动和攻击"""
        def move(self):
            """实例方法"""
            print("正在前往事发地点...")
     
        def attack(self):
            """实例方法"""
            print("发出了一招强力的普通攻击...")
     
        def info(self):
            """在类的实例方法中,通过self获取该对象的属性"""
            print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
            print("英雄 %s 的攻击力 :%d" % (self.name, self.atk))
            print("英雄 %s 的护甲值 :%d" % (self.name, self.armor))
      
    # 实例化了一个英雄对象 泰达米尔
    taidamier = Hero()
     
    # 给对象添加属性,以及对应的属性值
    taidamier.name = "泰达米尔"  # 姓名
    taidamier.hp = 2600  # 生命值
    taidamier.atk = 450  # 攻击力
    taidamier.armor = 200  # 护甲值
     
    # 通过.成员选择运算符,获取对象的实例方法
    taidamier.info()  # 只需要调用实例方法info(),即可获取英雄的属性
    taidamier.move()
    taidamier.attack()
     
    '''输出结果
    英雄 泰达米尔 的生命值 :2600
    英雄 泰达米尔 的攻击力 :450
    英雄 泰达米尔 的护甲值 :200
    正在前往事发地点...
    发出了一招强力的普通攻击...
    '''

    创建对象后再去添加属性有点不合适,有没有简单的办法,可以在创建对象的时候,就已经拥有这些属性?

  • __init__()方法

    Python的类里提供的,两个下划线开始,两个下划线结束的方法,就是魔法方法,__init__()就是一个魔法方法,通常用来做属性初始化 或 赋值 操作。

    如果类面没有写__init__方法,Python会自动创建,但是不执行任何操作,如果为了能够在完成自己想要的功能,可以自己定义__init__方法,所以一个类里无论自己是否编写__init__方法,一定有__init__方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    class Hero(object):
        def __init__(self):
            """ 方法,用来做变量初始化 或 赋值 操作,在类实例化对象的时候,会被自动调用"""
            self.name = "泰达米尔"  # 姓名
            self.hp = 2600  # 生命值
            self.atk = 450  # 攻击力
            self.armor = 200  # 护甲值
      
        def move(self):
            """实例方法"""
            print("正在前往事发地点...")
      
        def attack(self):
            """实例方法"""
            print("发出了一招强力的普通攻击...")
      
    taidamier = Hero()
    # 实例化了一个英雄对象,并自动调用__init__()方法
    print('姓名:%s,生命值:%d,攻击力:%d,护甲值:%d' % (taidamier.name,taidamier.hp,taidamier.atk,taidamier.armor, ))
    # 通过.成员选择运算符,获取对象的实例方法
    taidamier.move()
    taidamier.attack()
    '''运行结果
    姓名:泰达米尔,生命值:2600,攻击力:450,护甲值:200
    正在前往事发地点...
    发出了一招强力的普通攻击...
    '''

    __init__()方法,在创建一个对象时默认被调用,不需要手动调用

    __init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。

    在类的方法里定义属性的固定值,则每个对象实例变量的属性值都是相同的。

    一个游戏里往往有很多不同的英雄,能否让实例化的每个对象,都有不同的属性值呢?

  • 有参数的__init__()方法

    通过一个类,可以创建多个对象,就好比 通过一个模具创建多个实体一样

    __init__(self)中,默认有1个参数名字为self,假如在创建对象时传递了2个实参,那么__init__(self)中除了self作为第一个形参外还需要2个形参,例如__init__(self,x,y)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    class Hero(object):
        """定义了一个英雄类,可以移动和攻击"""
     
        def __init__(self, name, skill, hp, atk, armor):
            """ __init__() 方法,用来做变量初始化 或 赋值 操作"""
            # 英雄名
            self.name = name
            # 技能
            self.skill = skill
            # 生命值:
            self.hp = hp
            # 攻击力
            self.atk = atk
            # 护甲值
            self.armor = armor
     
        def move(self):
            """实例方法"""
            print("%s 正在前往事发地点..." % self.name)
     
        def attack(self):
            """实例方法"""
            print("发出了一招强力的%s..." % self.skill)
     
        def info(self):
            print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
            print("英雄 %s 的攻击力 :%d" % (self.name, self.atk))
            print("英雄 %s 的护甲值 :%d" % (self.name, self.armor))
      
    # 实例化英雄对象时,参数会传递到对象的__init__()方法里
    taidamier = Hero("泰达米尔""旋风斩"2600450200)
    gailun = Hero("盖伦""大宝剑"4200260400)
      
    print(gailun)
    print(taidamier)
     
    # 不同对象的属性值的单独保存
    print(id(taidamier.name))
    print(id(gailun.name))
     
    # 同一个类的不同对象,实例方法共享
    print(id(taidamier.move()))
    print(id(gailun.move()))
     
    '''结果
    <__main__.Hero object at 0x7f5681bde128>
    <__main__.Hero object at 0x7f5681bd9ac8>
    140009521155040
    140009521270576
    泰达米尔 正在前往事发地点...
    10722752
    盖伦 正在前往事发地点...
    10722752
    '''

    1,在类内部获取 属性 和 实例方法,通过self获取;

    2,在类外部获取 属性 和 实例方法,通过对象名获取。

    3,如果一个类有多个对象,每个对象的属性是各自保存的,都有各自独立的地址;

    4,但是实例方法是所有对象共享的,只占用一份内存空间。类会通过self来判断是哪个对象调用了实例方法。

最后修改:2020年3月1日 16:39

Python基础-面向对象(二)

  • __str__()方法

    这个方法是一个魔法方法 (Magic Method) ,用来显示信息

    该方法需要 return 一个数据,并且只有self一个参数,当在类的外部 print(对象) 则打印这个数据

    当类的实例化对象如果没有__str__ 则默认打印 对象在内存的地址。如果拥有 __str__ 方法后,那么打印对象则打印 __str__ 的返回值。

    查看类的文档说明,也就是类的注释:print(Hero.__doc__)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    class Hero(object):
        """定义了一个英雄类,可以移动和攻击"""
     
        def __init__(self, name, skill, hp, atk, armor):
            """ __init__() 方法,用来做变量初始化 或 赋值 操作"""
            # 英雄名
            self.name = name  # 实例变量
            # 技能
            self.skill = skill
            # 生命值:
            self.hp = hp   # 实例变量
            # 攻击力
            self.atk = atk
            # 护甲值
            self.armor = armor
     
        def move(self):
            """实例方法"""
            print("%s 正在前往事发地点..." % self.name)
     
        def attack(self):
            """实例方法"""
            print("发出了一招强力的%s..." % self.skill)
      
        def __str__(self):
            """
                这个方法是一个魔法方法 (Magic Method) ,用来显示信息
                该方法需要 return 一个数据,并且只有self一个参数,当在类的外部 print(对象) 则打印这个数据
            """
            return "英雄【%s】的数据: 生命值 %d, 攻击力 %d, 护甲值 %d" % (self.name, self.hp, self.atk, self.armor)
      
    taidamier = Hero("泰达米尔""旋风斩"2600450200)
    gailun = Hero("盖伦""大宝剑"4200260400)
     
    # 如果没有__str__ 则默认打印 对象在内存的地址。
    # 当类的实例化对象 拥有 __str__ 方法后,那么打印对象则打印 __str__ 的返回值。
    print(taidamier) # 英雄【泰达米尔】的数据: 生命值 2600, 攻击力 450, 护甲值 200
    print(gailun) # 英雄【盖伦】的数据: 生命值 4200, 攻击力 260, 护甲值 400
     
    # 查看类的文档说明,也就是类的注释
    print(Hero.__doc__) # 定义了一个英雄类,可以移动和攻击

    在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法。

    当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__(self)方法,那么就会打印从在这个方法中 return 的数据。

    __str__方法通常返回一个字符串,作为这个对象的描述信息

  • __del__()方法

    创建对象后,python解释器默认调用__init__()方法;

    当删除对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    class Hero(object):
     
        # 初始化方法
        # 创建完对象后会自动被调用
        def __init__(self, name):
            print('__init__方法被调用')
            self.name = name
     
        # 当对象被删除时,会自动被调用
        def __del__(self):
            print("__del__方法被调用")
            print("%s 被 GM 干掉了..." % self.name)
      
    # 创建对象
    taidamier = Hero("泰达米尔")
     
    # 删除对象
    print("%d 被删除1次" % id(taidamier))
    del(taidamier)
     
    print("--" * 10)
      
    gailun = Hero("盖伦")
    gailun1 = gailun
    gailun2 = gailun
     
    print("%d 被删除1次" % id(gailun))
    del(gailun)
     
    print("%d 被删除1次" % id(gailun1))
    del(gailun1)
     
    print("%d 被删除1次" % id(gailun2))
    del(gailun2)
    '''
    输出结果
    __init__方法被调用
    139881105243440 被删除1次
    __del__方法被调用  
    泰达米尔 被 GM 干掉了...
    --------------------
    __init__方法被调用
    139881105242488 被删除1次
    139881105242488 被删除1次
    139881105242488 被删除1次
    __del__方法被调用
    盖伦 被 GM 干掉了...
    '''

    当有变量保存了一个对象的引用时,此对象的引用计数就会加1;

    当使用del() 删除变量指向的对象时,则会减少对象的引用计数。如果对象的引用计数不为1,那么会让这个对象的引用计数减1,当对象的引用计数为0的时候,则对象才会被真正删除(内存被回收)。

  • 面向对象实例:烤地瓜

    目标
    强化面向对象编程的设计能力,进一步理解类、属性、方法的构建场景
    强化对self的理解,方法中使用self可以获取和修改属性

    烤地瓜规则:
    1.地瓜有自己的状态,默认是生的,地瓜可以进行烧烤
    2地瓜有自己烧烤的总时间,由每次烧烤的时间累加得出
    3.地瓜烧烤时,需要提供本次烧烤的时间
    4.地瓜烧烤时,地瓜状态随着烧烤总时间的变化而改变: [0, 3)生的、[3, 6)半生不熟、[6, 8)熟了、>=8烤糊了
    5.输出地瓜信息时,可以显示地瓜的状态和烧烤的总时间

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    # 新型一个新型类SweetPotato
    class SweetPotato(object):
        '''
        烤地瓜的文档说明
        '''
        # 初始化属性CookeLevel(一共烤的时间),CookedString(地瓜状态),Condiments(调料列表)
        def __init__(self):
            self.CookedLevel = 0
            self.CookedString = '生的'
            self.Condiments = []
        # 烤地瓜的方法
        def cook(self,time):
            self.CookedLevel += time
            if self.CookedLevel > 8:
                self.CookedString = '烤糊了'
            elif self.CookedLevel > 5:
                self.CookedString = '烤好了'
            elif self.CookedLevel > 3:
                self.CookedString = '烤的半生不熟'
            else:
                self.CookedString = '生的'
        # 添加调料的方法
        def add_condiments(self,condiments):
            self.Condiments.append(condiments)
        # print的输出信息
        def __str__(self):
            if len(self.Condiments) > 0:
                str_Condiments = ','.join(self.Condiments) # 列表转字符串
                return '地瓜烤了%d分钟,%s,调料是%s' % (self.CookedLevel,self.CookedString,str_Condiments)
            else:
                return '地瓜烤了%d分钟,%s,没有调料' % (self.CookedLevel, self.CookedString)
     
    print(SweetPotato.__doc__) # 查看类的文档说明:烤地瓜的文档说明
    mysweetpotao = SweetPotato() # 实例化一个对象
    mysweetpotao.cook(2)
    print(mysweetpotao) # 地瓜烤了2分钟,生的,没有调料
     
    mysweetpotao.cook(2)
    mysweetpotao.add_condiments('番茄酱')
    print(mysweetpotao)# 地瓜烤了4分钟,烤的半生不熟,调料是番茄酱
     
    mysweetpotao.cook(3)
    mysweetpotao.add_condiments('辣椒酱')
    print(mysweetpotao) # 地瓜烤了7分钟,烤好了,调料是番茄酱,辣椒酱
     
    mysweetpotao.cook(2)
    mysweetpotao.add_condiments('芥末')
    print(mysweetpotao) #地瓜烤了9分钟,烤糊了,调料是番茄酱,辣椒酱,芥末

最后修改:2020年3月1日 22:21

Python基础-面向对象(三)

  • 继承的概念

    在程序中,继承描述的是多个类之间的所属关系。

    如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。

    那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 父类
    class A(object):
        def __init__(self):
            self.num = 10
        def sum(self):
            return self.num + 10
     
    # 子类
    class B(A):
        pass
     
    = B()
    print(b.num) # 10
    print(b.sum()) # 20
  • 单继承:子类只继承一个父类

    故事情节:煎饼果子老师傅在煎饼果子界摸爬滚打几十年,拥有一身精湛的煎饼果子技术,并总结了一套"古法煎饼果子配方"。可是老师傅年迈已久,在去世之前希望把自己的配方传承下去,于是老师傅把配方传给他的徒弟大猫...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # 定义一个Master父类
    class Master(object):
        def __init__(self):
            # 属性
            self.gufa = '古法煎饼果子配方'
        # 方法
        def make_cake(self):
            print('按照%s制作古法煎饼果子' % self.gufa)
     
    # 定义一个Prentice子类,继承父类Master
    class Prentice(Master):
        # 子类可以继承父类所有的属性和方法,哪怕子类没有自己的属性和方法,也可以使用父类的属性和方法。
        pass
     
    # 创建子类实例对象
    = Prentice()
    # 子类对象可以直接使用父类的属性
    print(p.gufa) # 古法煎饼果子配方
    # 子类对象可以直接使用父类的方法
    p.make_cake() # 按照古法煎饼果子配方制作古法煎饼果子

    虽然子类没有定义__init__方法初始化属性,也没有定义实例方法,但是父类有。所以只要创建子类的对象,就默认执行了那个继承过来的__init__方法

    子类在继承的时候,在定义类时,小括号()中为父类的名字

    父类的属性、方法,会被继承给子类

  • 多继承:子类继承多个父类

    剧情发展:大猫掌握了师傅的配方,可以制作古法煎饼果子。但是大猫是个爱学习的好孩子,他希望学到更多的煎饼果子的做法,于是通过百度搜索,找到了一家煎饼果子培训学校。(多继承)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    # 定义一个Master父类
    class Master(object):
        def __init__(self):
            # 属性
            self.gufa = '古法煎饼果子配方'
        # 方法
        def make_cake(self):
            print('按照%s制作古法煎饼果子' % self.gufa)
        def eat_master(self):
            print('在师傅家吃饭')
      
    # 定义一个School父类
    class School(object):
        def __init__(self):
            self.gufa = '现代煎饼果子配方'
        def make_cake(self):
            print('按照%s制作现代煎饼果子' % self.gufa)
        def eat_school(self):
            print('在学校吃饭')
     
    # 定义一个Prentice子类,继承父类Master,School
    class Prentice(Master,School):
        # 子类可以继承两个父类所有的属性和方法,哪怕子类没有自己的属性和方法,也可以使用两个父类的属性和方法。
        pass
     
    # 创建子类实例对象
    = Prentice()
    # 子类对象可以直接使用父类的属性,两个父类的属性名相同,默认调用第一个父类
    print(p.gufa) # 古法煎饼果子配方
    # 子类对象可以直接使用父类的方法
    p.make_cake() # 按照古法煎饼果子配方制作古法煎饼果子,两个父类的属性名相同时,根据类的魔法属性mro的顺序来查找
     
    # 两个父类方法不相同时,两个都可以调用出来
    p.eat_master() # 在师傅家吃饭
    p.eat_school() # 在学校吃饭
     
    # 注意:如果多个父类中有同名的 属性和方法,则根据类的魔法属性mro的顺序来查找
    print(Prentice.__mro__)
    # 结果(<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)

    多继承可以继承多个父类,也继承了所有父类的属性和方法

    注意:如果多个父类中有同名的 属性和方法,则根据类的魔法属性mro的顺序来查找

    多个父类中,不重名的属性和方法,不会有任何影响。

  • 子类重写父类的同名属性和方法

    剧情发展:大猫掌握了 师傅的配方 和 学校的配方,通过研究,大猫在两个配方的基础上,创建了一种全新的煎饼果子配方,称之为 "猫氏煎饼果子配方"。(子类重写父类同名属性和方法)

    如果子类和父类的方法名或属性名相同,则默认使用子类的,叫 子类重写父类的同名方法和属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    # 定义一个Master父类
    class Master(object):
        def __init__(self):
            # 属性
            self.gufa = '古法煎饼果子配方'
        # 方法
        def make_cake(self):
            print('按照%s制作古法煎饼果子' % self.gufa)
        def eat_master(self):
            print('在师傅家吃饭')
      
    # 定义一个School父类
    class School(object):
        def __init__(self):
            self.gufa = '现代煎饼果子配方'
        def make_cake(self):
            print('按照%s制作现代煎饼果子' % self.gufa)
        def eat_school(self):
            print('在学校吃饭')
     
    # 定义一个Prentice子类,继承父类Master,School
    class Prentice(Master,School):
        # 子类重写了属性和方法
        def __init__(self):
            self.gufa = '猫式煎饼果子配方'
        def make_cake(self):
            print('用%s猫式煎饼果子配方制作煎饼果子' %self.gufa)
     
    # 创建子类实例对象
    = Prentice()
    print(p.gufa) # 猫式煎饼果子配方,子类重写了父类的属性,用子类的属性
    p.make_cake() # 用猫式煎饼果子配方猫式煎饼果子配方制作煎饼果子,子类重写了父类的方法,用子类的方法
      
    # 注意:如果重写了父类中有属性或方法,则默认使用子类的属性或方法(根据类的魔法属性mro的顺序来查找)
    print(Prentice.__mro__)
    # 结果(<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
  • 子类调用父类同名属性和方法

    剧情发展:大猫的新配方大受欢迎,但是有些顾客希望也能吃到古法配方和 现代配方 的煎饼果子...(子类调用父类的同名属性和方法)

    如果子类和父类的方法名或属性名相同,则默认使用子类的,叫子类重写父类的同名方法和属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    # 定义一个Master父类
    class Master(object):
        def __init__(self):
            # 属性
            self.gufa = '古法煎饼果子配方'
        # 方法
        def make_cake(self):
            print('按照%s制作古法煎饼果子' % self.gufa)
        def eat_master(self):
            print('在师傅家吃饭')
      
    # 定义一个School父类
    class School(object):
        def __init__(self):
            self.gufa = '现代煎饼果子配方'
        def make_cake(self):
            print('按照%s制作现代煎饼果子' % self.gufa)
        def eat_school(self):
            print('在学校吃饭')
     
    # 定义一个Prentice子类,继承父类Master,School
    class Prentice(Master,School):
        # 子类重写了属性和方法
        def __init__(self):
            self.gufa = '猫式煎饼果子配方'
        def make_cake(self):
            print('用%s猫式煎饼果子配方制作煎饼果子' %self.gufa)
        # 获取Master的属性和方法
        def make_master_cake(self):
            Master.__init__(self)
            Master.make_cake(self)
     
        # 获取School 的属性和方法
        def make_school_cake(self):
            School.__init__(self)
            School.make_cake(self)
      
    # 创建子类实例对象
    = Prentice()
    print(p.gufa) # 猫式煎饼果子配方,子类重写了父类的属性,用子类的属性
    p.make_cake() # 用猫式煎饼果子配方猫式煎饼果子配方制作煎饼果子,子类重写了父类的方法,用子类的方法
      
    # 注意:如果重写了父类中有属性或方法,则默认使用子类的属性或方法(根据类的魔法属性mro的顺序来查找)
    print(Prentice.__mro__)
    # 结果(<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
     
    # 调用Master的属性和方法
    p.make_master_cake() # 按照古法煎饼果子配方制作古法煎饼果子
    print(p.gufa) # 执行Master类的__init__方法后,self.kongfu属性:古法煎饼果子配方
     
    # 调用School的属性和方法
    p.make_school_cake() # 按照现代煎饼果子配方制作现代煎饼果子
    print(p.gufa) # 执行School类的__init__方法后,self.kongfu属性:现代煎饼果子配方
  • super()的使用

    子类继承了多个父类,如果父类类名修改了,那么子类也要涉及多次修改。而且需要重复写多次调用,显得代码臃肿。

    使用super() 可以逐一调用所有的父类方法,并且只执行一次。调用顺序遵循 mro 类属性的顺序。

    注意:如果继承了多个父类,且父类都有同名方法,则默认只执行第一个父类的(同名方法只执行一次,目前super()不支持执行多个父类的同名方法)

    super() 在Python2.3之后才有的机制,用于通常单继承的多层继承。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    # 定义一个Master父类
    class Master(object):
        def __init__(self):
            # 属性
            self.gufa = '古法煎饼果子配方'
     
        # 方法
        def make_cake(self):
            print('按照%s制作古法煎饼果子' % self.gufa)
     
        def eat_master(self):
            print('在师傅家吃饭')
      
    # 定义一个School父类
    class School(object):
        def __init__(self):
            self.gufa = '现代煎饼果子配方'
     
        def make_cake(self):
            print('按照%s制作现代煎饼果子' % self.gufa)
     
        def eat_school(self):
            print('在学校吃饭')
      
    # 定义一个Prentice子类,继承父类Master,School
    class Prentice(Master, School):
        # 子类重写了属性和方法
        def __init__(self):
            self.gufa = '猫式煎饼果子配方'
     
        def make_cake(self):
            print('用%s制作煎饼果子' % self.gufa)
     
        def make_all_cake(self):
            # 方式1. 指定执行父类的方法(代码臃肿)
            # School.__init__(self)
            # School.make_cake(self)
            #
            # Master.__init__(self)
            # Master.make_cake(self)
            #
            # self.__init__()
            # self.make_cake()
     
            # 方法2. super() 带参数版本,只支持新式类
            # super(Prentice, self).__init__() # 执行父类的 __init__方法
            # super(Prentice, self).make_cake()
            # self.make_cake()
     
            # 方法3. super()的简化版,只支持新式类
            super().__init__()  # 执行父类的 __init__方法
            super().make_cake()  # 执行父类的 实例方法
            self.__init__() # 执行本类的实例方法
            self.make_cake()  # 执行本类的实例方法
      
    # 创建子类实例对象
    = Prentice()
    print(p.gufa)
    p.make_all_cake()
  • 多层继承

    剧情发展:大猫的煎饼果子店非常红火,终于有一天,他成了世界首富!!但是他也老了,所以他希望把 师傅的配方 和 学校的配方 以及自己的配方 继续传承下去...(多层继承)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    # 定义一个Master父类
    class Master(object):
        def __init__(self):
            # 属性
            self.gufa = '古法煎饼果子配方'
        # 方法
        def make_cake(self):
            print('按照%s制作古法煎饼果子' % self.gufa)
        def eat_master(self):
            print('在师傅家吃饭')
      
    # 定义一个School父类
    class School(object):
        def __init__(self):
            self.gufa = '现代煎饼果子配方'
        def make_cake(self):
            print('按照%s制作现代煎饼果子' % self.gufa)
        def eat_school(self):
            print('在学校吃饭')
     
    # 定义一个Prentice子类,继承父类Master,School
    class Prentice(Master,School):
        # 子类重写了属性和方法
        def __init__(self):
            self.gufa = '猫式煎饼果子配方'
            self.money = 1000 # 亿美金
        def make_cake(self):
            print('用%s配方制作煎饼果子' %self.gufa)
        # 获取Master的属性和方法
        def make_master_cake(self):
            Master.__init__(self)
            Master.make_cake(self)
     
        # 获取School 的属性和方法
        def make_school_cake(self):
            School.__init__(self)
            School.make_cake(self)
    # 新建一个大猫徒弟的类,继承大猫类Prentice
    class PrenticePrentice(Prentice):
        pass
     
    # 创建大猫徒弟的实例对象
    pp = PrenticePrentice()
    pp.make_cake() # 用猫式煎饼果子配方配方制作煎饼果子
    print(pp.gufa) # 猫式煎饼果子配方
    pp.make_master_cake() # 按照古法煎饼果子配方制作古法煎饼果子
    print(pp.gufa) # 古法煎饼果子配方
    pp.make_school_cake() # 按照现代煎饼果子配方制作现代煎饼果子
    print(pp.gufa) # 现代煎饼果子配方

最后修改:2020年3月2日 03:23

Python基础-面向对象(四)

  • 私有权限

    面向对象三大特性:封装、继承、多态

    封装的意义

        1,将属性和方法放到一起做为一个整体,然后通过实例化对象来处理;

        2,隐藏内部实现细节,只需要和对象及其属性和方法交互就可以了;

        3,对类的属性和方法增加 访问权限控制。

    私有权限:在属性名和方法名 前面 加上两个下划线 __

        1,类的私有属性 和 私有方法,都不能通过对象直接访问,但是可以在本类内部访问;

        2,类的私有属性 和 私有方法,都不会被子类继承,子类也无法访问;

        3,私有属性 和 私有方法 往往用来处理类的内部事情,不通过对象处理,起到安全作用。

    剧情发展: 大猫觉得配方传承下去没问题,但是钱是辛辛苦苦挣得血汗钱,不想传给徒弟。(私有权限)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    # 定义一个Master父类
    class Master(object):
        def __init__(self):
            # 属性
            self.gufa = '古法煎饼果子配方'
     
        # 方法
        def make_cake(self):
            print('按照%s制作古法煎饼果子' % self.gufa)
     
        def eat_master(self):
            print('在师傅家吃饭')
     
     
    # 定义一个School父类
    class School(object):
        def __init__(self):
            self.gufa = '现代煎饼果子配方'
     
        def make_cake(self):
            print('按照%s制作现代煎饼果子' % self.gufa)
     
        def eat_school(self):
            print('在学校吃饭')
     
     
    # 定义一个Prentice子类,继承父类Master,School
    class Prentice(Master, School):
        # 子类重写了属性和方法
        def __init__(self):
            self.gufa = '猫式煎饼果子配方'
            self.__money = 1000  # 亿美金
     
        def make_cake(self):
            print('用%s配方制作煎饼果子' % self.gufa)
     
        # 获取Master的属性和方法
        def make_master_cake(self):
            Master.__init__(self)
            Master.make_cake(self)
     
        # 获取School 的属性和方法
        def make_school_cake(self):
            School.__init__(self)
            School.make_cake(self)
     
     
    # 新建一个大猫徒弟的类,继承大猫类Prentice
    class PrenticePrentice(Prentice):
        pass
     
     
    # 创建大猫徒弟的实例对象
    pp = PrenticePrentice()
    pp.make_cake()  # 用猫式煎饼果子配方配方制作煎饼果子
    print(pp.gufa)  # 猫式煎饼果子配方
    pp.make_master_cake()  # 按照古法煎饼果子配方制作古法煎饼果子
    print(pp.gufa)  # 古法煎饼果子配方
    pp.make_school_cake()  # 按照现代煎饼果子配方制作现代煎饼果子
    print(pp.gufa)  # 现代煎饼果子配方
     
    #monye式私有属性,实例化继承不了
    print(pp.__money)  # 继承大猫的钱,出错:AttributeError: 'PrenticePrentice' object has no attribute '__money'

    Python是以属性命名方式来区分,如果在属性和方法名前面加了2个下划线'__',则表明该属性和方法是私有权限,否则为公有权限。

  • 修改私有属性的值

    如果需要修改一个对象的属性值,通常有2种方法:

        1,对象名.属性名 = 数据 ----> 直接修改

        2,对象名.方法名() ----> 间接修改

    私有属性不能直接访问,所以无法通过第一种方式修改,一般的通过第二种方式修改私有属性的值:定义一个可以调用的公有方法,在这个公有方法内访问修改。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    # 定义一个Master父类
    class Master(object):
        def __init__(self):
            # 属性
            self.gufa = '古法煎饼果子配方'
     
        # 方法
        def make_cake(self):
            print('按照%s制作古法煎饼果子' % self.gufa)
     
        def eat_master(self):
            print('在师傅家吃饭')
     
     
    # 定义一个School父类
    class School(object):
        def __init__(self):
            self.gufa = '现代煎饼果子配方'
     
        def make_cake(self):
            print('按照%s制作现代煎饼果子' % self.gufa)
     
        def eat_school(self):
            print('在学校吃饭')
     
     
    # 定义一个Prentice子类,继承父类Master,School
    class Prentice(Master, School):
        # 子类重写了属性和方法
        def __init__(self):
            self.gufa = '猫式煎饼果子配方'
            self.__money = 1000  # 亿美金
     
            # 返回私有属性的值
        def get_money(self):
            return self.__money
        def set_money(self,num):
            self.__money = num
            return num
        def make_cake(self):
            print('用%s配方制作煎饼果子' % self.gufa)
     
        # 获取Master的属性和方法
        def make_master_cake(self):
            Master.__init__(self)
            Master.make_cake(self)
     
        # 获取School 的属性和方法
        def make_school_cake(self):
            School.__init__(self)
            School.make_cake(self)
     
     
    # 新建一个大猫徒弟的类,继承大猫类Prentice
    class PrenticePrentice(Prentice):
        pass
     
     
    # 创建大猫徒弟的实例对象
    pp = PrenticePrentice()
    print(pp.get_money())
    # 可以通过访问公有方法set_money()来获取私有属性的值
    pp.set_money(2000)
    # 可以通过访问公有方法get_money()来修改私有属性的值
    print(pp.get_money())
  • 多态

    大家应该听说过这样的故事:有一个中医世家,父亲是当地一位非常有名的老大夫,看病看的非常好,儿子从小就跟着父亲学医,医术也不错. 突然县太爷家的千金生了重病,急需老大夫前去治病,但是老大夫又不在家,就请了老大夫的儿子前去给治病. 最后儿子也把病给治好了

    那么,在python语言中能不能做类似的事情,比如说 在需要调用父类对象方法的地方,我们也可以调用子类对象的方法呢?

    当然可以! 要想这样,我们需要使用接下来要学习的知识点:多态.

    好,下面我们就开始正式讲解 多态.在讲解的时候:

    1.先讲解"多态"的概念

    2.再讲解如何使用多态

    3.最后讲解多态的好处

  • 什么是多态?

    在需要使用父类对象的地方,也可以使用子类对象, 这种情况就叫多态.

    比如, 在函数中,我需要调用 某一个父类对象的方法, 那么我们也可以在这个地方调用子类对象的方法.

  • 如何在程序中使用多态?

    可以按照以下几个步骤来写代码:

    1.子类继承父类

    2.子类重写父类中的方法

    3.通过对象调用这个方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class Father(object):
        def cure(self):
            print('父亲给人治病')
     
    class Son(Father):
        # 重新cure方法
        def cure(self):
            print('儿子给人治病')
     
    # 义函数,在里面 调用医生的cure函数
    def call_cure(doctor):
        # 调用医生治病的方法
        doctor.cure()
     
    # 创建父类对象
    father = Father()
    # 调用函数,把父类对象传递函数
    call_cure(father)
     
     
    # 创建子类对象
    son = Son()
    # 调用函数,把子类对象传递函数
    call_cure(son)
  • 使用多态的好处dt.png

    多态的好处:给call_cure(doctor)函数传递哪个对象,在它里面就会调用哪个对象的cure()方法,也就是说在它里面既可以调用son对象的cure()方法,也能调用father对象的cure()方法,当然了也可以在它里面调用Father类其它子类对象的cure()方法,这样可以让call_cure(doctor)函数变得更加灵活,额外增加了它的功能,提高了它的扩展性.

  • 类属性和实例属性

    在了解了类基本的东西之后,下面看一下python中这几个概念的区别。

    先来谈一下类属性和实例属性:

    在前面的例子中我们接触到的就是实例属性(对象属性),顾名思义,类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。对于公有的类属性,在类外可以通过类对象和实例对象访问

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class People(object):
        name = 'Tom'  # 公有的类属性
        __age = 12  # 私有的类属性
     
    = People()
     
    print(p.name)  # 正确
    print(People.name)  # 正确
    print(p.__age)  # 错误,不能在类外通过实例对象访问私有的类属性
    print(People.__age) # 错误,不能在类外通过类对象访问私有的类属性
  • 实例属性(对象属性)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class People(object):
        address = '广东'  # 类属性
        def __init__(self):
            self.name = 'xiaowang'  # 实例属性
            self.age = 20  # 实例属性
     
    = People()
    p.age = 12  # 实例属性
    print(p.address)  # 正确
    print(p.name)  # 正确
    print(p.age)  # 正确
     
    print(People.address)  # 正确,类属性
    print(People.name)  # 错误,不是类属性
    print(People.age)  # 错误,不是类属性
  • 通过实例(对象)去修改类属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class People(object):
        country = 'china' #类属性
     
     
    print(People.country)
    = People()
    print(p.country)
    p.country = 'japan'  # 增加一个跟类属性同名的实例属性,就相当于修改了类属性
    print(p.country)  # 实例属性会屏蔽掉同名的类属性
    print(People.country)
    del p.country  # 删除实例属性
    print(p.country)

    总结:如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

  • 类方法

    是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字,就最好用'cls'了),能够通过实例对象和类对象去访问。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class People(object):
        country = 'china'
     
        #类方法,用classmethod来进行修饰
        @classmethod
        def get_country(cls):
            return cls.country
     
    = People()
    print(p.get_country())    #可以用过实例对象引用
    print(People.get_country())    #可以通过类对象引用

    类方法还有一个用途就是可以对类属性进行修改:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class People(object):
        country = 'china'
     
        #类方法,用classmethod来进行修饰
        @classmethod
        def get_country(cls):
            return cls.country
     
        @classmethod
        def set_country(cls,country):
            cls.country = country
     
     
    = People()
    print(p.get_country())   # china 可以用过实例对象访问
    print(People.get_country())    # china 可以通过类访问
     
    p.set_country('japan')
     
    print(p.get_country()) # japan 
    print(People.get_country()) # japan

    结果显示在用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变

  • 静态方法

    需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数,可以通过对象和类来访问。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class People(object):
        country = 'china'
     
        @staticmethod
        #静态方法
        def get_country():
            return People.country
     
     
    = People()
    # 通过对象访问静态方法
    print(p.get_country()) # china
     
    # 通过类访问静态方法
    print(People.get_country()) # china

    总结:

    从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;

    实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。

    静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类实例对象来引用

最后修改:2020年3月2日 22:03

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多