专栏首页极客起源Python编程思想(23):类和对象

Python编程思想(23):类和对象

类是面向对象的核心组成部分,类是一种自定义类型,并且可以将类作为变量的类型、以及函数参数和返回值的类型。

1. 如何定义类

在面向对象的程序设计过程中有两个重要概念:类(class)和对象( object),对象也被称为实例(instance),其中类是拥有类似特性的对象的抽象,可以把类理解成某种概念,对象才是一个具体存在的实体。

从这个意义上看,日常所说的具体的人就是对象,而“人类”相当于类。

Python定义类的简单语法如下:

class类名:
    执行语句...
    零个到多个类变量...
    零个到多个方法...

类名只要是一个合法的标识符即可,但这仅仅满足的是 Python的语法要求。如果从程序的可读性方面来看,Python的类名最好是由一个或多个有意义的单词连缀而成的,每个单词首字母大写(大驼峰命名法),其他字母全部小写,单词与单词之间不要使用任何分隔符。

从上面定义来看,Python的类定义有点像函数定义,都是以冒号(:)作为类体的开始,以缩进的部分作为类体的。区别只是函数定义使用def关键字,而类定义则使用 class关键字。

Python的类定义由类头(指 class关键字和类名部分)和统一缩进的类体构成,在类体中最主要的两类成员就是变量和方法。如果不为类定义任何变量和方法,那么这个类就相当于一个空类。如果空类不需要其他可执行语句,则可使用pass语句作为占位符。例如,如下类定义是允许的。

class MyClass
    pass

通常来说,空类没有太大的实际意义。类中各成员之间的定义顺序没有任何影响。各成员之间可以相互调用。

成员变量属于类本身,用于定义该类本身所包含的状态数据。而实例变量则属于该类的对象,用于定义对象所包含的状态数据。方法则用于定义该类的对象的行为或功能实现。

Python是一门动态语言,因此它的类所包含的类变量可以动态增加或删除。程序在类体中为新变量赋值就是增加类变量,程序也可在任何地方为已有的类增加变量。程序可通过del语句删除已有类的类变量。

与类变量类似,Python对象的实例变量也可以动态增加或删除。只要对新实例变量赋值就是增加实例变量,因此程序可以在任何地方为已有的对象增加实例变量。程序可通过del语句删除已有对象的实例变量。

在类中定义的方法默认是实例方法,定义实例方法的方式与定义函数的方式基本相同,只是实例方法的第一个参数会被绑定到方法的调用者(该类的实例)上。因此实例方法至少应该定义一个参数,该参数通常会被命名为self。

注意:

实例方法的笫1个参数并不一定要叫self,其实完全可以叫任何参数名,只是约定俗成地把该参数命名为self,这样具有最好的可读性。

在实例方法中有一个特别的方法:init。这个方法被称为构造方法。构造方法用于构造该类的对象,Python通过调用构造方法返回该类的对象(创建Python对象时不需要使用new)。

构造方法是一个类创建对象是第1个要执行的方法,因此 ,Python还提供了一个功能。如果开发者没有为该类定义任何构造方法,那么 Python会自动为该类定义一个只包含一个self参数的构造方法。

下面程序将定义一个 Product类。

示例代码:Product.py

class Product :
    '我们编写的第1个Python类'
    # 下面定义了一个类变量
    type = 'Mobile'
    def __init__(self, name = 'iPhone12 Pro', price=8000):
        # 下面为Product对象增加2个实例变量
        self.name = name
        self.price = price
    # 下面定义了一个buy方法
    def buy(self, price):
        print(f"您已经花了{price}元购买了一部{self.name}手机")

上面的Product类代码定义了一个构造方法,该构造方法只是方法名比较特殊,该方法的第1个参数同样是self,被绑定到构造方法初始化的对象。与函数类似的是, Python也允许为类定义说明文档,该文档同样被放在类声明之后、类体之前,如上面程序中第1行的字符串所示。

在定义类之后,接下来即可使用该类了。Python的类大致有如下作用。

  • 定义变量
  • 创建对象
  • 派生子类

下面先介绍如何创建类的实例(对象),以及如何使用对象。

2. 对象的创建和使用

创建对象的根本途径是构造方法,调用某个类的构造方法即可创建这个类的对象, Python无须使用new调用构造方法。如下代码示范了调用 Product类的构造方法(Product类的代码见前面的内容)。

# 调用Product类的构造方法,返回一个product
# 将该Product对象赋值给product变量
product = Product()

在创建对象之后,接下来即可使用该对象了。Python的对象大致有如下作用。

  • 操作对象的实例变量(包括访问实例变量的值、添加实例变量、删除实例变量);
  • 调用对象的方法;

对象访问方法或变量的语法如下:

对象.变量|方法(参数)

在这种方式中,对象是主调者,用于访问该对象的变量或方法。

下面代码通过Product对象来调用 Product的实例和方法(Product类的源代码见前面的内容)。

# 输出product的name、price实例变量
print(product.name, product.price)
# 访问product的name实例变量,直接为该实例变量赋值
product.name = 'iPhone12 pro max'
product.price = 12000
# 调用product的buy()方法,声明buy()方法时定义了2个形参
# 但第1个形参(self)是自动绑定的,因此调用该方法只需为第2个形参指定一个值
product.buy(12000)
# 再次输出p的name、age实例变量
print(product.name, product.price)

上面程序开始访问了product对象的name和price两个实例变量。这两个变量是何时定义的呢?留意在Product的构造方法中有如下2行代码

self. name= name
self. price = price

这两行代码用传入的name和price参数(这两个参数都有默认值)对self的name、price变量赋值。由于 Python的第1个self参数是自动绑定的(在构造方法中自动绑定到该构造方法初始化的对象),而这2行代码就是对self的name、price两个变量赋值,也就是对该构造方法初始化的对象(product对象)的name和age变量赋值,即为product对象增加了name和price两个实例变量。

上面代码中通过Product对象调用了buy方法,在调用该方法时必须为方法的形参赋值。但buy方法的第1个形参self是自动绑定的,它会被绑定到方法的调用者(product)上,因此程序只需要为buy方法传入1个浮点数作为参数值,这个浮点数将被传给price参数。

大部分时候,定义一个类就是为了重复创建该类的对象,同一个类的多个对象具有相同的特征,而类则定义了多个对象的共同特征。从某个角度来看,类定义的是多个对象的特征,因此类不是个具体存在的实体,对象才是一个具体存在的实体。

3. 动态增加实例变量

由于 Python是动态语言,因此程序完全可以为product对象动态增加实例变量。只要为它的新变量赋值即可,动态删除实例变量需要使用del语句。

为Product对象增加一个size实例变量

# 为product对象增加一个size实例变量
product.size = '6.7英寸'
print(product.size)
# 删除product对象的name实例变量
del product.name
# 再次访问pproduct的name实例变量
# print(product.name)  # AttributeError

上面程序先为product对象动态增加了一个size实例变量。只要对roduct对象的 price实例变量赋值,就是新增一个实例变量。

接下来程序中调用del删除了product对象的name实例变量,当程序再次访问print( p name)时就会导致 Attribute error错误,并提示:" Product' object has no attribute name

Python是动态语言,当然也允许为对象动态增加方法。比如上面程序中在定义 Product类时只定义了一个buy方法,但程序完全可以为product对象动态增加方法。

但需要说明的是,为product对象动态增加的方法,Python不会自动将调用者自动绑定到第一个参数(即使将第1个参数命名为self也没用)。例如如下代码。

# 先定义一个函数
def info(self):
    print("---info函数---", self)
# 使用info对Product的info方法赋值(动态绑定方法)
product.info = info
# Python不会自动将调用者绑定到第一个参数,
# 因此程序需要手动将调用者绑定为第一个参数
product.info(product)

# 使用lambda表达式为product对象的bar方法赋值(动态绑定方法)
product.info = lambda self: print('--lambda表达式--', self)
product.info(product)

上面两行粗体字代码分别使用函数、 lambda表达式为p对象动态增加了方法,但对于动态增加的方法,Python不会自动将方法调用者绑定到它们的第1个参数,因此程序必须手动为第1个参数传入参数值,如上面程序中所示。

如果希望动态增加的方法也能自动绑定到第1个参数,则可借助于 types模块下的 Method Type进行包装。例如如下代码。

def intro_func(self, price):
    print(f"您已经花了{price}元购买了一部手机")
# 导入MethodType
from types import MethodType
# 使用MethodType对intro_func进行包装,将该函数的第一个参数绑定为p
product.intro = MethodType(intro_func, product)
# 第一个参数已经绑定了,无需传入
product.intro("生活在别处")

正如从上面代码所看到的,通过 Method Type包装 intro_func函数之后(包装时指定了将该函数的第1个参数绑定为product),为product对象动态增加的 info方法的第1个参数已经绑定,因此,程序通过product调用 intro方法时无须传入第一个参数的值。只需要像定义类时已经定义了 info方法一样。

本文分享自微信公众号 - 极客起源(geekculture),作者:geekori

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 深度解析Java中的5个“黑魔法”

    现在的编程语言越来越复杂,尽管有大量的文档和书籍,这些学习资料仍然只能描述编程语言的冰山一角。而这些编程语言中的很多功能,可能被永远隐藏在黑暗角落。本文将为你解...

    蒙娜丽宁
  • 震惊!当Python遇到Excel后,将开启你的认知虫洞

    本文主要讲Python与Excel的关系以及集成方案,Office家族的其他成员,如Word、PowerPoint与Excel拥有类似的功能,Python同样可...

    蒙娜丽宁
  • 微信小程序开发实战(9):单行输入和多行输入组件

    input组件用于录入单行文本,尽管input的基本功能是文本录入,但该组件的属性还是比较多的,也比较复杂。下面是input属性的属性及其含义。

    蒙娜丽宁
  • python3第八天(面向对象)

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

    py3study
  • [ASP.NET Core 3框架揭秘] 文件系统[2]:总体设计

    在《抽象的“文件系统”》中,我们通过几个简单的实例演示从编程的角度对文件系统做了初步的体验,接下来我们继续从设计的角度来进一步认识它。这个抽象的文件系统以目录的...

    蒋金楠
  • python入门到放弃(三)-基本数据类型之int整数和bool值

    #整数可以进行的操作有:bit_length(),计算整数在内存中占用的二进制码的长度

    guoke-boy
  • 【数据】数据科学面试问题集一

    数据科学也被称为数据驱动型决策,是一个跨学科领域,涉及以各种形式从数据中提取知识的科学方法,过程和系统,并基于这些知识进行决策。 数据科学家不应仅仅根据他/她对...

    陆勤_数据人网
  • 二月技术通讯.pdf丨核心数据库一波三折异常重启分析

    每月关注:55 页 干货,汇总一个月数据库行业热点事件、新的产品特性,包括重要数据库产品发布、警报、更新、新版本、补丁等。

    数据和云
  • 【POJ 2342】Anniversary party(入门树形dp)

    没有告诉你树根,dp的方向我第一次写的是用队列维护叶子节点,每次计算完,它的父亲的孩子数量--,如果减到0,就变成叶子加入队列。直到队列空。后来看别人写的两种是...

    饶文津
  • 视频界的FaceApp研究:DeepMind建模算法生成更复杂逼真的视频

    还记得前些天风靡网络的FaceApp吗,它是利用AI算法的自拍应用,把人们上传的照片中的人脸变年轻或者老化。

    AiTechYun

扫码关注云+社区

领取腾讯云代金券