Rumah > pembangunan bahagian belakang > Tutorial Python > Konsep OOP dalam Python untuk Pengaturcara C 98

Konsep OOP dalam Python untuk Pengaturcara C 98

Mary-Kate Olsen
Lepaskan: 2024-11-16 15:50:03
asal
472 orang telah melayarinya

Conceitos de POO em Python para Programadores C  98

Berikut ialah demonstrasi komprehensif konsep OOP dalam Python untuk pengaturcara C 98:

Definisi Kelas dan Penciptaan Objek

Ular sawa

# 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)
Salin selepas log masuk
Salin selepas log masuk

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!"
Salin selepas log masuk
Salin selepas log masuk

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;
};
Salin selepas log masuk
Salin selepas log masuk

Pusaka Berbilang

Ular sawa

class Pet:
    def is_vaccinated(self):
        return True

class DomesticDog(Dog, Pet):
    pass
Salin selepas log masuk
Salin selepas log masuk

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) {}
};
Salin selepas log masuk
Salin selepas log masuk

Kelas Abstrak

Ular sawa

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
Salin selepas log masuk
Salin selepas log masuk

C 98

class Shape {
public:
    virtual ~Shape() {}
    virtual double area() const = 0;
};
Salin selepas log masuk
Salin selepas log masuk

Contoh Penggunaan

Ular sawa

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__
Salin selepas log masuk
Salin selepas log masuk

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 []
}
Salin selepas log masuk
Salin selepas log masuk

Perbezaan Utama antara Python dan C 98

  1. Tiada kata kunci awam/swasta/dilindungi (gunakan konvensyen penamaan)
  2. Pewarisan berbilang berbeza:
    • Python menggunakan Perintah Resolusi Kaedah (MRO) dengan linearisasi C3
    • Tidak memerlukan warisan maya seperti dalam C
    • super() secara automatik mengikut MRO
    • Tertib kelas asas penting dalam Python
    • Anda boleh memeriksa susunan resolusi dengan __mro__
  3. Semua kaedah adalah maya secara lalai
  4. Tiada perbezaan antara petunjuk/rujukan
  5. Tidak perlu pengurusan ingatan (pengumpul sampah)
  6. Penaipan dinamik dan bukannya penaipan statik
  7. Penghias harta dan bukannya kaedah getter/setter
  8. Kaedah khas menggunakan format __name__ dan bukannya operator
  9. kata kunci
  10. Lebih banyak sintaks Pythonic untuk operator lebih muatan (cth. __eq__ vs operator==)

Gunakan dir(objek) untuk melihat semua atribut dan kaedah objek dan bantu(objek) untuk dokumentasi.

Topik Khas:

Masalah Pusaka Berlian

                              Animal

                           .    '    ,
                             _______
                        _  .`_|___|_`.  _
                    Pet     \ \   / /     WorkingAnimal
                             \ ' ' /
                              \ " /   
                               \./

                           DomesticDog
Salin selepas log masuk

Masalah dengan Diamond Inheritance dalam C 98

Warisan berlian berlaku apabila kelas mewarisi daripada dua kelas yang, seterusnya, mewarisi daripada kelas asas biasa. Ini boleh menyebabkan beberapa masalah:

  1. Kekaburan: Kaedah dan atribut kelas asas biasa boleh menjadi samar-samar.
  2. Penduaan Data: Setiap kelas terbitan boleh mempunyai salinan sendiri ahli kelas asas biasa, yang membawa kepada pertindihan data.

Contoh Warisan Berlian dalam 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;
}
Salin selepas log masuk

Tingkah Laku yang Dijangka

Animal constructor
Pet constructor
WorkingAnimal constructor
DomesticDog constructor
Pet sound
Salin selepas log masuk

Dalam contoh ini, DomesticDog mewarisi daripada Pet dan WorkingAnimal, kedua-duanya mewarisi daripada Animal. Ini mencipta berlian pusaka. Warisan maya digunakan untuk mengelakkan pertindihan dan kesamaran data.

Bagaimana Python Menghalang Warisan Berlian Secara Automatik

Python menggunakan Method Resolution Order (MRO) dengan linearisasi C3 untuk menyelesaikan masalah warisan berlian secara automatik. MRO menentukan susunan kelas yang diperiksa semasa mencari kaedah atau atribut.

Contoh Warisan Berlian dalam 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)
Salin selepas log masuk
Salin selepas log masuk

Tingkah Laku yang Dijangka

#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!"
Salin selepas log masuk
Salin selepas log masuk

Dalam contoh ini, Python menyelesaikan pewarisan berlian secara automatik menggunakan MRO. Anda boleh menyemak MRO menggunakan atribut __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;
};
Salin selepas log masuk
Salin selepas log masuk

MRO dalam Python memastikan DomesticDog mewarisi dengan betul daripada Pet dan WorkingAnimal, dan Haiwan itu diselesaikan sebelum objek. Oleh itu, perintah pengisytiharan mempengaruhi MRO, tetapi linearisasi C3 memastikan hierarki dihormati.

Penjelasan:

  1. Perintah Pengisytiharan: MRO bermula dengan kelas terbitan paling banyak dan mengikut susunan kelas asas diisytiharkan.
  2. C3 Linearization: Memastikan setiap kelas muncul sebelum kelas supernya dan susunan pewarisan dikekalkan.

Struktur Data: Timbunan, Baris Gilir dan Peta

timbunan

Ular sawa

class Pet:
    def is_vaccinated(self):
        return True

class DomesticDog(Dog, Pet):
    pass
Salin selepas log masuk
Salin selepas log masuk

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) {}
};
Salin selepas log masuk
Salin selepas log masuk

Beratur

Ular sawa

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
Salin selepas log masuk
Salin selepas log masuk

C 98

class Shape {
public:
    virtual ~Shape() {}
    virtual double area() const = 0;
};
Salin selepas log masuk
Salin selepas log masuk

Peta

Ular sawa

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__
Salin selepas log masuk
Salin selepas log masuk

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 []
}
Salin selepas log masuk
Salin selepas log masuk

Terima kasih kerana mengikuti panduan ini tentang konsep OOP dalam Python dan C 98. Kami berharap ia berguna untuk perjalanan pembelajaran anda. Jika anda menyukai kandungan tersebut, sila tinggalkan komen anda, suka dan kongsi dengan rakan dan rakan sekerja anda. Jika anda mendapati ralat, tinggalkan komen anda dan saya akan membetulkannya! Sehingga kali seterusnya!

Atas ialah kandungan terperinci Konsep OOP dalam Python untuk Pengaturcara C 98. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan