面向 C++98 程序员的 Python 中的 OOP 概念
来源:dev.to
2024-11-18 14:25:07
0浏览
收藏
本篇文章向大家介绍《面向 C++98 程序员的 Python 中的 OOP 概念》,主要包括,具有一定的参考价值,需要的朋友可以参考一下。

这里为 c++98 程序员全面演示了 python 中的 oop 概念:
类定义和对象创建
python
# privado por convenção: _underscore_simples
# "realmente privado": __underscore_duplo (name mangling)
# público: sem underscore
from abc import abstractmethod
class animal(abc):
# em python, variáveis declaradas no escopo da classe e não dentro de um
# método específico, são automaticamente compartilhadas por todas instâncias.
species_count = 0 # além disso, elas podem ser inicializadas diretamente dentro da classe.
# construtor
def __init__(self, name):
# variáveis de instância
self.name = name # público
self._age = 0 # protegido por convenção
self.__id = id(self) # privado (mas você consegue acessar com name mangling)
animal.species_count += 1
# destrutor
def __del__(self):
animal.species_count -= 1
# método regular
@abstractmethod
def make_sound(self):
pass # equivalente a um método abstrato/virtual (deve ser implementado apenas nas classes filhas)
# método estático (não precisa da instância para ser utilizado, nem utiliza seus atributos)
@staticmethod
def get_kingdom():
return "animalia"
# método de classe (recebe a classe como primeiro argumento, pode acessar atributos da classe)
@classmethod
def get_species_count(cls):
return cls.species_count
# decorador de propriedade (getter)
@property
def age(self):
return self._age
# decorador de propriedade (setter)
@age.setter
def age(self, value):
if value >= 0:
self._age = value
# métodos especiais (sobrecarga de operadores)
def __str__(self): # como tostring() - para string legível
return f"animal named {self.name}"
def __repr__(self): # para debugging
return f"animal(name='{self.name}')"
def __eq__(self, other): # operador de comparação ==
return isinstance(other, animal) and self.name == other.name
def __len__(self): # função len()
return self._age
def __getitem__(self, key): # operador de acesso []
if key == 'name':
return self.name
raise keyerror(key)
c++98
#include <iostream>
#include <string>
#include <sstream>
class animal {
public:
static int species_count;
animal(const std::string& name) : name(name), _age(0), __id(++id_counter) { // construtor
++species_count;
}
~animal() { // destrutor
--species_count;
}
virtual void make_sound() = 0; // método não implementável na classe base (virtual/abstrato)
static std::string get_kingdom() { // não existe distinção entre
// @classmethod e @staticmethod em cpp, apenas static methods.
return "animalia";
}
// static methods podem ser utilizados sem instanciar uma classe e têm
// acesso às propriedades estáticas da classe:
static int get_species_count() {
return species_count;
}
// getter:
int get_age() const {
return _age;
}
// setter:
void set_age(int age) {
if (age >= 0) {
_age = age;
}
}
// implementação dos métodos especiais que vimos em python:
std::string to_string() const {
return "animal named " + name;
}
std::string repr() const {
std::ostringstream oss;
oss << "animal(name='" << name << "', age=" << _age << ", id=" << __id << ")";
return oss.str();
}
bool operator==(const animal& other) const {
return name == other.name;
}
// sobrecarga do operador []
std::string operator[](const std::string& key) const {
if (key == "name") {
return name;
}
throw std::out_of_range("invalid key");
}
// método isinstance
template <typename t>
bool isinstance() const {
return dynamic_cast<const t*>(this) != nullptr;
}
protected:
std::string name;
int _age;
private:
int __id;
static int id_counter;
};
// variáveis estáticas de classe são compartilhadas por todas as instâncias mas
// precisam ser inicializadas separadamente.
int animal::species_count = 0;
int animal::id_counter = 0;
遗产
python
class dog(animal):
def __init__(self, name, breed):
# chama o construtor da classe pai
super().__init__(name)
self.breed = breed
# sobrescreve o método da classe pai
def make_sound(self):
return "woof!"
c++98
class dog : public animal {
public:
dog(const std::string& name, const std::string& breed) : animal(name), breed(breed) {}
void make_sound() override {
std::cout << "woof!" << std::endl;
}
private:
std::string breed;
};
多重继承
python
class pet:
def is_vaccinated(self):
return true
class domesticdog(dog, pet):
pass
c++98
class pet {
public:
bool is_vaccinated() const {
return true;
}
};
class domesticdog : public dog, public pet {
public:
domesticdog(const std::string& name, const std::string& breed) : dog(name, breed) {}
};
抽象类
python
from abc import abc, abstractmethod
class shape(abc):
@abstractmethod
def area(self):
pass
c++98
class shape {
public:
virtual ~shape() {}
virtual double area() const = 0;
};
使用示例
python
if __name__ == "__main__":
# cria objetos
dog = dog("rex", "golden retriever")
# acessa atributos
print(dog.name) # público
print(dog._age) # protegido (ainda acessível)
# print(dog.__id) # isso falhará
print(dog._animal__id) # isso funciona (acessando attribute privado com name mangling)
# propriedades
dog.age = 5 # usa setter automaticamente
print(dog.age) # usa getter automaticamente
# métodos estáticos e de classe
print(animal.get_kingdom())
print(animal.get_species_count())
# verifica herança
print(isinstance(dog, animal)) # true
print(issubclass(dog, animal)) # true
# métodos especiais em ação
print(str(dog)) # usa __str__
print(repr(dog)) # usa __repr__
print(len(dog)) # usa __len__
print(dog['name']) # usa __getitem__
c++98
int main() {
// cria objetos
dog dog("rex", "golden retriever");
// acessa atributos
std::cout << dog.name << std::endl; // público
std::cout << dog.get_age() << std::endl; // protegido (ainda acessível)
// std::cout << dog.__id << std::endl; // isso falhará (privado)
// propriedades
dog.set_age(5); // usa setter
std::cout << dog.get_age() << std::endl; // usa getter
// métodos estáticos e de classe
std::cout << animal::get_kingdom() << std::endl;
std::cout << animal::get_species_count() << std::endl;
// equivalente aos "métodos especiais":
// verifica herança
if (dog.isinstance<animal>()) {
std::cout << "dog é uma instância de animal" << std::endl;
}
std::cout << dog.to_string() << std::endl; // usa to_string
std::cout << dog.repr() << std::endl; // usa repr
std::cout << dog["name"] << std::endl; // usa operador []
}
python 和 c++98 之间的主要区别
- 没有公共/私有/受保护的关键字(使用命名约定)
- 多重继承不同:
- python 使用方法解析顺序 (mro) 和 c3 线性化
- 不需要像c++那样的虚拟继承
- super() 自动遵循 mro
- python 中基类的顺序很重要
- 您可以使用 __mro__ 检查解析顺序
- 默认情况下所有方法都是虚拟的
- 指针/引用之间没有区别
- 不需要内存管理(垃圾收集器)
- 动态类型而不是静态类型
- 属性装饰器而不是 getter/setter 方法
- 特殊方法使用 __name__ 格式而不是运算符 关键字
- 更多用于运算符重载的 pythonic 语法(例如 __eq__ 与运算符 ==)
使用 dir(object) 查看对象的所有属性和方法,使用 help(object) 查看文档。
专题:
钻石继承问题
animal
. ' ,
_______
_ .`_|___|_`. _
pet \ \ / / workinganimal
\ ' ' /
\ " /
\./
domesticdog
c++98 中的 diamond 继承问题
当一个类继承自两个类,而这两个类又继承自一个公共基类时,就会发生钻石继承。这可能会导致几个问题:
- 歧义:公共基类的方法和属性可能会变得不明确。
- 数据重复:每个派生类都可以拥有自己的公共基类成员副本,从而导致数据重复。
c++98 中的 diamond 继承示例
class animal {
public:
animal() {
std::cout << "animal constructor" << std::endl;
}
virtual void make_sound() {
std::cout << "some generic animal sound" << std::endl;
}
};
class pet : public animal {
public:
pet() : animal() {
std::cout << "pet constructor" << std::endl;
}
void make_sound() override {
std::cout << "pet sound" << std::endl;
}
};
class workinganimal : public animal {
public:
workinganimal() : animal() {
std::cout << "workinganimal constructor" << std::endl;
}
void make_sound() override {
std::cout << "working animal sound" << std::endl;
}
};
class domesticdog : public pet, public workinganimal {
public:
domesticdog() : animal(), pet(), workinganimal() {
std::cout << "domesticdog constructor" << std::endl;
}
void make_sound() override {
pet::make_sound(); // ou workinganimal::make_sound(), dependendo do comportamento desejado
}
};
int main() {
domesticdog dog;
dog.make_sound();
return 0;
}
预期行为
animal constructor pet constructor workinganimal constructor domesticdog constructor pet sound
在这个例子中,domesticdog继承自pet和workinganimal,它们都继承自animal。这创造了一颗传家宝钻石。使用虚拟继承来避免数据重复和歧义。
python 如何自动阻止 diamond 继承
python 使用方法解析顺序 (mro) 和 c3 线性化来自动解决菱形继承问题。 mro 确定在查找方法或属性时检查类的顺序。
python 中的 diamond 继承示例
class animal:
def make_sound(self):
print("some generic animal sound")
class pet(animal):
def make_sound(self):
print("pet sound")
class workinganimal(animal):
def make_sound(self):
print("working animal sound")
class domesticdog(pet, workinganimal):
pass
dog = domesticdog()
dog.make_sound()
预期行为
pet sound
在此示例中,python 使用 mro 自动解析菱形继承。您可以使用 __mro__:
属性检查 mro
print(domesticdog.__mro__)
python中的mro确保domesticdog正确继承自pet和workinganimal,并且animal在对象之前被解析。因此,声明顺序会影响 mro,但 c3 线性化可确保尊重层次结构。
解释:
- 声明顺序:mro 从最派生的类开始,遵循基类声明的顺序。
- c3 线性化:确保每个类出现在其超类之前,并保持继承顺序。
数据结构:栈、队列和映射
堆
python
stack = [] # we could just use a list as a stack stack.append(1) # push stack.append(2) print(stack.pop()) # pop
c++98
#include <stack> // we have to import the stack type std::stack<int> stack; stack.push(1); // push stack.push(2); std::cout << stack.top() << std::endl; // top stack.pop(); // pop
队列
python
from collections import deque queue = deque() queue.append(1) # enqueue queue.append(2) print(queue.popleft()) # dequeue
c++98
#include <queue> std::queue<int> queue; queue.push(1); // enqueue queue.push(2); std::cout << queue.front() << std::endl; // front queue.pop(); // dequeue
地图
python
map = {} # this is automatically creating a map (which is called a dictionary in python)
map['key1'] = 'value1'
map['key2'] = 'value2'
print(map['key1'])
c++98
#include <map> std::map<std::string, std::string> map; map["key1"] = "value1"; map["key2"] = "value2"; std::cout << map["key1"] << std::endl;
感谢您遵循本有关 python 和 c++98 中的 oop 概念的指南。我们希望它对您的学习之旅有用。如果您喜欢内容,请留下您的评论、点赞并分享给您的朋友和同事。如果您发现错误,请留下您的评论,我会纠正它!下次见!
文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《面向 C++98 程序员的 Python 中的 OOP 概念》文章吧,也可关注golang学习网公众号了解相关技术文章。
版本声明
本文转载于:dev.to 如有侵犯,请联系study_golang@163.com删除
JTabbedPane的add()和addTab()方法:有何区别?
- 上一篇
- JTabbedPane的add()和addTab()方法:有何区别?
- 下一篇
- Win10电脑怎么连接投影仪怎么设置 Win10电脑怎么连接投影仪
查看更多
最新文章
-
- 文章 · python教程 | 7分钟前 |
- Python指定文件路径的方法及技巧
- 362浏览 收藏
-
- 文章 · python教程 | 35分钟前 |
- Pandas统计连续相同值并新增列技巧
- 297浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- DjangoQ对象使用技巧与优化方法
- 245浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Dagster数据流转与参数配置方法
- 211浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- OpenCV调整亮度技巧与方法
- 204浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Python轻松生成九九乘法表并导出Excel
- 147浏览 收藏
-
- 文章 · python教程 | 1小时前 | 图像处理 Pillow Image.open() resize() save()
- Pillow库使用技巧与教程详解
- 467浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python代码审查与协作技巧分享
- 333浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- 彻底卸载WindowsPython方法详解
- 365浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Tkintericonphoto()默认参数详解
- 446浏览 收藏
查看更多
课程推荐
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
查看更多
AI推荐
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3211次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3425次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3454次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4563次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3832次使用
查看更多
相关文章
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

