面向 C 程序员的 Python 中的 OOP 概念 98
这里为 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 << ",> <h2> Herança </h2> <h3> Python </h3> <pre class="brush:php;toolbar:false">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 中的钻石继承问题
当一个类继承自两个类,而这两个类又继承自一个公共基类时,就会发生钻石继承。这可能会导致几个问题:
- 歧义:公共基类的方法和属性可能会变得不明确。
- 数据重复:每个派生类都可以拥有自己的公共基类成员副本,从而导致数据重复。
C 98 中的钻石继承示例
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 继承示例
# 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)
预期行为
#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 << ",> <h2> Herança </h2> <h3> Python </h3> <pre class="brush:php;toolbar:false">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!"
在此示例中,Python 使用 MRO 自动解析菱形继承。您可以使用 __mro__:
属性检查 MRO
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中的MRO确保DomesticDog正确继承自Pet和WorkingAnimal,并且Animal在对象之前被解析。因此,声明顺序会影响 MRO,但 C3 线性化可确保尊重层次结构。
解释:
- 声明顺序:MRO 从最派生的类开始,遵循基类声明的顺序。
- C3 线性化:确保每个类出现在其超类之前,并保持继承顺序。
数据结构:栈、队列和映射
堆
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 中的 OOP 概念的指南。我们希望它对您的学习之旅有所帮助。如果您喜欢内容,请留下您的评论、点赞并分享给您的朋友和同事。如果您发现错误,请留下您的评论,我会纠正它!下次见!
以上是面向 C 程序员的 Python 中的 OOP 概念 98的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Linux终端中查看Python版本时遇到权限问题的解决方法当你在Linux终端中尝试查看Python的版本时,输入python...

在使用Python的pandas库时,如何在两个结构不同的DataFrame之间进行整列复制是一个常见的问题。假设我们有两个Dat...

如何在10小时内教计算机小白编程基础?如果你只有10个小时来教计算机小白一些编程知识,你会选择教些什么�...

使用FiddlerEverywhere进行中间人读取时如何避免被检测到当你使用FiddlerEverywhere...

本文讨论了诸如Numpy,Pandas,Matplotlib,Scikit-Learn,Tensorflow,Tensorflow,Django,Blask和请求等流行的Python库,并详细介绍了它们在科学计算,数据分析,可视化,机器学习,网络开发和H中的用途

Uvicorn是如何持续监听HTTP请求的?Uvicorn是一个基于ASGI的轻量级Web服务器,其核心功能之一便是监听HTTP请求并进�...

在Python中,如何通过字符串动态创建对象并调用其方法?这是一个常见的编程需求,尤其在需要根据配置或运行...
