Python的类和对象(与C++对比学习)

一、前言

在学习Python的类和对象之前,我们先回顾一下C++的类和对象是如何实现的?

        我们通常会创建一个类,类中包含类的成员函数和成员变量,一般我们将想给外界暴露出来的接口函数设定为public,而成员变量和不想暴露给外界的函数设定为private。

        下面是最简单的日期类:

class datetime
{
public:
    datetime()
    {}
    ~datetime()
    {}
    int year() { return _year;}
    int month() { return _month;}
    int day() { return _day;}
private:
    int _year;
    int _month;
    int _day;
};

二、基本概念

类:

抽象出来的模版,不占用内存空间,就当成一个声明即可

实例化对象:

占有内存空间的类对象,每个类对象用到的方法都是一致的,但是类各自的数据可能不一致

类的方法:

        无论是C++还是Python,类的方法的参数中都提供了指向实例化对象的关键字

        C++中称其为this指针,形参与实参不需要显式传递,类方法中引用成员也不需要显式地写this-> xxx

        Python用self表示,self是一个对实例化对象的引用,访问成员用 ‘ . ',需要在形参位置写self,在实参不需要传self,在访问类成员需要显式写 self.XXX

        类的方法其它的特性与普通函数一致

三、Python类的实例化 - C++类的实例化

        先回顾一下C++中类的实例化,C++的类提供了默认构造函数,或者是我们自己显式地去写构造函数

class datetime
{
public:
    // 默认构造函数 -》 无参
    datetime()
        : _year(0)
        , _month(0)
        , _day(0)
    {}
    // 默认构造函数 -》 全缺省
    datetime(int year = 2024, int month = 7, int day = 7)
        : _year(year)
        , _month(month)
        , _day(day)
    {}
    // 我们不写构造函数,编译器自己生成的默认构造
    
    // 构造函数
    datetime(int year, int month, int day)
        : _year(year)
        , _month(month)
        , _day(day)
    {}
    ~datetime()
    {}
    int year() { return _year;}
    int month() { return _month;}
    int day() { return _day;}
private:
    int _year;
    int _month;
    int _day;
};

        Python的类的实例化跟C++的很相似,也是要通过构造函数来完成对每个实例化对象的初始化,只不过Python的构造函数是 __init__()来表示:

class Student(object):
# 参数与普通函数的参数设定形式一致,只不过类方法都多了self
    def __init__(self, name, age):  
        self.name = name
        self.age = age


s = Student('dd', 20)
print(s.name)
print(s.age)

四、实例属性和类属性

类属性

        归整个类所有 , 每个实例化对象都具有该属性,属性包括成员变量与成员方法,但是每个实例化对象拿到的类属性都是独立的,实例化对象之间对类属性进行修改不影响彼此

如下在类内部定义的成员变量和成员方法就是类属性

class Animal(object):
    name = '小丁'
    def Run(self):
        print('Animal is running ~ ')


a1 = Animal()
print(a1.name)

a2 = Animal()
print(a2.name)

实例属性 

        针对实例化对象设置的成员变量和成员方法,只可以被当前实例化对象使用;

如下是实例化对象中动态添加的成员变量和成员方法

from types import MethodType


class Student(object):
    def __init__(self, name):  # 设置名字属性
        self.name = name


def printf(self):
    print("%s的成绩是%d" % (self.name, self.score))


s = Student('Bob')
s.printf = MethodType(printf, s) # 给实例化对象绑定一个成员方法
s.score = 90  # 添加成员变量
s.printf()

限制可以添加的实例属性

        使用__slots__变量来限制可以添加的实例属性,下面的代码就只允许我们添加name和age两个属性,其余属性不允许添加。

  • 类属性的变量名不要与__slots__后的变量名冲突
  • 只对当前类的实例起作用,不影响继承出来的派生类
  • 在派生类中也定义__slots__变量,那派生类可添加的实例属性就是基类和派生类的总和
class Student(object):
    __slots__ = ('name', 'age')  # 限制Student类只允许有name和age两个属性

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def printf(self):
        print("%s is %d" % (self.name, self.age))


class Bob(Student):
    pass


b = Bob('Bob', 20)
Bob.score = 90  # 不限制派生类的实例化对象的实例属性添加
print(Bob.score)

五、Python的类的自定义成员方法

        与C++在思路上一致,类的成员方法无一不是对类的成员变量的增删查改,其实面向对象也基本就是这样的思路,比如人,你要给其一些关键的属性,也就是成员变量,再对成员变量做一些获取、更新的方法,这叫先描述;当一个对象设计好了,我们可以将其组织成不同的数据结构,比如顺序表、链表、哈希表等,来完成不同的功能,这叫再组织

        所以在上面想打印出Student的属性时,我们完全可以将其设计成一个方法,如果后续我们还需要设计其它方法,就直接在类中定义函数即可!

class Student(object):
    def __init__(self, name, age):  # 参数与普通函数的参数设定形式一致,只不过类方法都多了self
        self.name = name
        self.age = age

    def print_student(self):
        print("%s %d" % (self.name, self.age))


s = Student('dd', 20)
s.print_student()

六、访问限制

     C++中对访问限制时有强制性规定的,private不允许任何外部来访问,只允许类的内部访问;public允许外部访问;protected其实是专门为继承来设定的,因为protected不允许外部访问,但允许派生类访问。

class Debug
{
    public:
        // 公有,允许任何人访问
    private:
        // 私有,只允许内部访问
};

        但是Python中没有强制性规定访问的限制,一切都是靠程序员自觉。Python类中提供了一种规定,如果不想被外界访问,可以在成员前添加 ‘ __ ’

class Student(object):
    def __init__(self, name, age): 
        self.__name = name
        self.__age = age

    def __print_student(self):
        print("%s %d" % (self.__name, self.__age))
        
s = Student('dd', 20)
print(s.__age) #不允许访问
s.__print_student() # 不允许访问

【注】:

        不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,我们仍然可以通过_Student__name来访问__name变量,那也就说明我们如果对类的实例化对象添加__name属性,是一个新的属性,因为之前我们认为的__name 已经是_Student__name了。但是强烈不推荐访问私有成员,每个Python解释器对私有成员的变量名更改都不一致。

七、继承

        被继承的类为基类,继承基类的类为派生类,C++中派生类可以使用基类的protected、public的成员,无法使用基类private的成员(派生类继承了,但无法使用),C++中的继承方式分为public、protected、private。继承方式主要是改变基类成员的访问属性。

        但是在Python中没有这些规定,Python中派生类可以继承基类的任何成员,只不过私有成员只在内部访问,公有成员可以在外部访问。        

class Animal(object):
    def Run(self):
        print('Animal is running ~ ')
    def __Eat(self):
        print('Animal is eating~')

class Dog(Animal):
    pass


class Cat(Animal):
    pass


animal = Animal()
dog = Dog()
cat = Cat()
animal.Run()
dog.Run()
cat.Run()

八、多态

        在C++中多态的条件:

  1. 必须是基类的指针或引用调用虚函数
  2. 派生类必须对基类的虚函数完成功能的重写
#include <iostream>
class Animal
{
public:
    Animal(){}
    ~Animal(){}
    virtual void Run()
    {
        std::cout << "Animal is running" << std::endl;
    }
private:
};
class Dog : public Animal
{
public: 
    virtual void Run()
    {
        std::cout << "Dog is running" << std::endl;
    }
private:
};
int main()
{
    Animal* dog = new Dog();
    dog->Run();
    return 0;
}

在Python中就没有这么多规矩了,直接对基类的函数进行功能的重写就行

class Animal(object):
    def Run(self):
        print('Animal is running ~ ')


class Dog(Animal):
    def Run(self):
        print('Dgo is running ~')


animal = Animal()
dog = Dog()

animal.Run()
dog.Run()

九、@property

        负责将一个成员方法变为属性调用,常用于set或get一个属性

class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.__score = score

    @property # 读属性
    def score(self):
        return self.__score

    @score.setter # 写属性
    def score(self, score):
        if not isinstance(score, int):
            raise ValueError('score must be a integer')
        if score < 0 or score > 100:
            raise ValueError('socre must be in [0, 100]')
        self.__score = score


s = Student('dd', 20, 80)
s.score = 60 # 转换为 socre(60)
print(s.score) # 转换为 score()

【注】:

        属性的方法名不要和实例变量重名,否则在实际调用时,Python解释器会将其解释为方法,导致无限递归访问,从而使栈溢出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/781511.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

react dangerouslySetInnerHTML将html字符串以变量方式插入页面,点击后出现编辑状态

1.插入变量 出现以下编辑状态 2.解决 给展示富文本的标签添加css样式 pointerEvents: none

JAVA之(方法的重载与重写、this关键字、super关键字)

方法的重载与重写 一、方法的重载与重写1、回顾方法的定义2、重载的概念3、重写 二、this关键字1、何为this方法2、使用方法&#xff08;1&#xff09;在构造方法中指构造器所创建的新对象&#xff08;2&#xff09; 方法中指调用该方法的对象&#xff08;3&#xff09; 在类本…

【植物大战僵尸杂交版】获取+存档插件

文章目录 一、还记得《植物大战僵尸》吗&#xff1f;二、在哪下载&#xff0c;怎么安装&#xff1f;三、杂交版如何进行存档功能概述 一、还记得《植物大战僵尸》吗&#xff1f; 最近&#xff0c;一款曾经在15年前风靡一时的经典游戏《植物大战僵尸》似乎迎来了它的"文艺复…

自用款 复制粘贴工具 Paste macOS电脑适配

Paste是一款专为Mac和iOS用户设计的剪贴板管理工具&#xff0c;它提供了强大的剪贴板增强功能。Paste能够实时记录用户复制和剪切的内容&#xff0c;包括文本、图片、链接等多种数据类型&#xff0c;并形成一个可视化的剪贴板历史记录&#xff0c;方便用户随时访问和检索。此外…

嵌入式鸿蒙系统openharmony编译方法详解

大家好,时光如梭,今天主要给大家分享一下,鸿蒙系统的使用方法,以及源码该如何编译,其中要注意的细节有哪些? 第一:OpenHarmony系统简介 OpenHarmony 是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目, 目标是面向全场景、全连接、全智能时代,基于…

vite简介

vite是新一代前端构建工具&#xff0c;vite具有优势如下&#xff1a; 轻量快速的热重载&#xff08;HMR&#xff09;&#xff0c;能实现快速的服务启动。对TypeScript、JSX、CSS等支持开箱即用。真正的按需编译&#xff0c;不再等待整个应用编译完成。webpack构建与vite构建对…

html+css+JavaScript 实现两个输入框的反转动画

开发时遇到了一个输入框交换的动画 做完之后觉得页面上加些许过渡或动画&#xff0c;其变化虽小&#xff0c;却能极大的提升页面质感&#xff0c;给人一种顺畅、丝滑的视觉体验。它的实现过程主要是通过css中的transition和animation来实现的。平时在开发的时候增加一些动画效…

PYTHON自学笔记(一)vscode配置

安装python 自行官网下载 安装vscode 自行官网下载 环境变量设置 把python和scripts的文件路径&#xff0c;添加到环境变量的path中&#xff0c;如图&#xff1a; 此项不弄&#xff0c;在命令行模式中系统不会认为你装了python和pip&#xff0c;你的输入相关命令shell不会…

Python实现ABC人工蜂群优化算法优化随机森林回归模型(RandomForestRegressor算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 人工蜂群算法(Artificial Bee Colony, ABC)是由Karaboga于2005年提出的一种新颖的基于群智能的全局优化…

Day59 动态规划part12

LC115不同的子序列&#xff08;未掌握&#xff09; 递推公式与LC392类似&#xff0c;但是初始化略有不同 LC392的dp数组含义为相同字符个数而本体的dp数组含义为出现的次数&#xff0c;因此dp[i][0]1 两种情况 s[i-1]t[j-1] dp[i][j] dp[i-1][j-1]dp[i][j] dp[i-1][j] s[…

python等级考试——一级知识点汇总(turtle画图部分)

&#xff08;本篇文章是针对中国电子学会青少年编程等级考试的&#xff0c;适合初学者以及青少年编程学习者&#xff09; 本篇文章主要介绍turtle画图部分&#xff0c;其他一级考试知识点请移步下方链接&#xff1a;python等级考试——一级知识点汇总&#xff08;不包含turtle…

科大讯飞-群聊对话角色要素提取:不微调范式模拟官网评分

不微调范式模拟官网评分 step1: 模型api配置及加载测试step2: 数据加载与数据分析&#xff1a;测试集分析:step3: prompt设计:step4 :大模型推理&#xff1a;step 5: 结果评分测试&#xff1a;评分细则&#xff1a;评估指标 参考&#xff1a; 比赛说明&#xff1a; #AI夏令营 #…

uniapp如何隐藏默认的页面头部导航栏,uniapp开发小程序如何隐藏默认的页面头部导航栏

uniapp如何隐藏默认的页面头部导航栏 隐藏后 在pages.json文件中插入 在uni-app中&#xff0c;设置navigationStyle为custom来自定义导航栏&#xff0c;可以隐藏默认的头部了。 {"path": "pages/index/index","name": "index",&qu…

【SpringCloud应用框架】Nacos集群架构说明

第六章 Spring Cloud Alibaba Nacos之集群架构说明 文章目录 前言一、Nacos支持三种部署模式二、集群部署说明三、预备环境 前言 到目前为止&#xff0c;已经完成了对Nacos的一些基本使用和配置&#xff0c;接下来还需要了解一个非常重要的点&#xff0c;就是Nacos的集群相关的…

【MySQL基础篇】多表查询

1、多表关系 概述&#xff1a;项目开发中&#xff0c;在进行数据库表结构操作设计时&#xff0c;会根据业务需求及业务模板之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种…

关于新装Centos7无法使用yum下载的解决办法

起因 之前也写了一篇类似的文章&#xff0c;但感觉有漏洞&#xff0c;这次想直接把漏洞补齐。 问题描述 在我们新装的Centos7中&#xff0c;如果想要用C编程&#xff0c;那就必须要用到yum下载&#xff0c;但是&#xff0c;很多新手&#xff0c;包括我使用yum下载就会遇到一…

WEB05Web开发HTMLCSS

Web前端开发 什么是 Web &#xff1f; Web&#xff1a;全球广域网&#xff0c;也称为万维网(www World Wide Web)&#xff0c;能够通过浏览器访问的网站。 Web 网站的工作流程 W3C 万维网联盟&#xff08; World Wide Web Consortium &#xff09;&#xff0c;创建于1994年1…

PD虚拟机不能复制Mac的文件怎么回事 PD虚拟机不能复制Mac的文件怎么办 Parallels Desktop怎么用

PD虚拟机不仅能提供跨系统协作的服务&#xff0c;还能进行虚拟机系统与原生系统间的文件共享、文本复制、文件复制等操作&#xff0c;让系统间的资源可以科学利用。但在实际操作过程中&#xff0c;PD虚拟机不能复制Mac的文件怎么回事&#xff1f;PD虚拟机不能复制Mac的文件怎么…

甘肃黄米粽子:香甜软糯的塞上美食

甘肃黄米粽子是甘肃地区具有特色的传统美食。黄米粽子选用优质的黄米作为主要原料&#xff0c;黄米相较于糯米&#xff0c;有着独特的谷物香气和口感。在制作过程中&#xff0c;将黄米浸泡一段时间&#xff0c;使其充分吸收水分&#xff0c;变得饱满。馅料方面&#xff0c;通常…

AcWing 1260:二叉树输出

【题目来源】https://www.acwing.com/problem/content/1262/【题目描述】 树的凹入表示法主要用于树的屏幕或打印输出&#xff0c;其表示的基本思想是兄弟间等长&#xff0c;一个结点的长度要不小于其子结点的长度。 二叉树也可以这样表示&#xff0c;假设叶结点的长度为 1&…