这里为 C 98 程序员全面演示了 Python 中的 OOP 概念:
# 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!"
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; };
class Pet: def is_vaccinated(self): return True class DomesticDog(Dog, Pet): pass
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) {} };
from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self): pass
class Shape { public: virtual ~Shape() {} virtual double area() const = 0; };
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__
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 [] }
使用 dir(object) 查看对象的所有属性和方法,使用 help(object) 查看文档。
Animal . ' , _______ _ .`_|___|_`. _ Pet \ \ / / WorkingAnimal \ ' ' / \ " / \./ DomesticDog
当一个类继承自两个类,而这两个类又继承自一个公共基类时,就会发生钻石继承。这可能会导致几个问题:
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 使用方法解析顺序 (MRO) 和 C3 线性化来自动解决菱形继承问题。 MRO 确定在查找方法或属性时检查类的顺序。
# 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 线性化可确保尊重层次结构。
class Pet: def is_vaccinated(self): return True class DomesticDog(Dog, Pet): pass
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) {} };
from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self): pass
class Shape { public: virtual ~Shape() {} virtual double area() const = 0; };
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__
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中文网其他相关文章!