python学习笔记(二)—面向对象编程

六、面向对象编程(OOP)

面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,将数据和操作封装为对象,通过对象之间的交互来构建程序。它强调将问题划分为多个独立的实体(对象),每个对象都有自己的数据和行为。

1. 类和对象

  • 类(Class):类是面向对象编程中的核心概念,它是对象的蓝图或模板。类定义了对象的属性(数据)和方法(行为)。
  • 对象(Object):对象是类的实例化,它是类的具体实体,具有类定义的属性和方法。

以下是一个简单的类和对象的示例:

# 定义一个类
class Person:
    # 类属性
    species = "Human"

    # 构造方法
    def __init__(self, name, age):
        # 实例属性
        self.name = name
        self.age = age

    # 实例方法
    def say_hello(self):
        print(f"Hello, my name is {self.name}.")

# 创建对象
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)

# 访问对象的属性和调用方法
print(person1.name)  # 输出结果为 "Alice"
print(person2.age)  # 输出结果为 30
person1.say_hello()  # 输出结果为 "Hello, my name is Alice."

在上述代码中,我们定义了一个Person类,它具有类属性species、实例属性nameage,以及实例方法say_hello()。通过创建Person类的两个对象person1person2,我们可以访问对象的属性和调用对象的方法。

2. 封装

  • 封装(Encapsulation):封装是一种将数据和对数据的操作封装在一起的机制,使其成为一个独立的单位。通过封装,对象的内部状态和实现细节对外部是不可见的,只提供有限的接口进行访问和操作。

封装的目的是隐藏对象的内部实现细节,提供一种抽象的方式与对象进行交互,减少对对象内部变化的影响,并提高代码的安全性和可维护性。

以下是一个封装的示例:

class BankAccount:
    def __init__(self, account_number, balance):
        self.account_number = account_number
        self.__balance = balance

    def deposit(self, amount):
        self.__balance += amount

    def withdraw(self, amount):
        if amount <= self.__balance:
            self.__balance -= amount
        else:
            print("Insufficient balance.")

    def get_balance(self):
        return self.__balance

# 创建银行账户对象
account = BankAccount("1234567890", 1000)

# 尝试访问对象

的私有属性
print(account.account_number)  # 输出结果为 "1234567890"
print(account.__balance)  # 报错,无法直接访问私有属性

# 调用对象的方法
account.deposit(500)
account.withdraw(200)
print(account.get_balance())  # 输出结果为 1300

在上述代码中,我们定义了一个BankAccount类,它包含一个公有属性account_number和一个私有属性__balance。通过公有的方法deposit()withdraw()get_balance(),我们可以间接地访问和修改私有属性__balance的值,而无法直接访问它。

3. 继承

  • 继承(Inheritance):继承是一种通过创建新类来重用和扩展现有类的属性和方法的机制。继承允许我们定义一个基类(父类),并在其基础上创建一个派生类(子类),子类继承了父类的属性和方法,并可以在此基础上进行扩展。

继承的关系可以形象地描述为"是一个"的关系,子类是父类的特殊化。

以下是一个继承的示例:

# 定义一个基类
class Shape:
    def __init__(self, color):
        self.color = color

    def area(self):
        pass

# 定义一个派生类
class Circle(Shape):
    def __init__(self, color, radius):
        super().__init__(color)
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

# 创建对象
circle = Circle("Red", 5)
print(circle.color)  # 输出结果为 "Red"
print(circle.area())  # 输出结果为 78.5

在上述代码中,我们定义了一个基类Shape,它具有属性color和方法area(),并定义了一个派生类Circle,它继承了基类Shape的属性和方法,并在此基础上添加了属性radius和重写了方法area()

4. 多态

  • 多态(Polymorphism):多态是一种使用同样的接口来处理不同类型对象的能力。在多态中,同一个方法名可以在不同的对象上产生不同的行为。

多态可以通过继承和方法重写来实现。在面向对象编程中,多态提供了一种灵活的方式来处理不同类型的对象,提高了代码的可扩展性和可维护性。

以下是一个多态的示例:

# 定义一个基类
class Animal:
    def __init__(self, name):
        self.name = name

    def make_sound(self):
        pass

# 定义派生类
class Dog(Animal):
    def make_sound(self):
        return "Woof!"

class Cat(Animal):
    def make_sound(self):
        return "Meow!"

# 处理不同类型的对象
dog = Dog("

Buddy")
cat = Cat("Kitty")

print(dog.make_sound())  # 输出结果为 "Woof!"
print(cat.make_sound())  # 输出结果为 "Meow!"

在上述代码中,我们定义了一个基类Animal,它具有属性name和方法make_sound(),并定义了两个派生类DogCat,它们分别重写了基类的make_sound()方法。

通过处理不同类型的对象dogcat,调用相同的方法make_sound(),我们可以获得不同的结果,实现了多态的效果。

5.类方法和静态方法

在面向对象编程中,除了实例方法,还可以定义类方法和静态方法。

类方法

  • 类方法(Class Method):类方法是与类相关联的方法,而不是与实例相关联的方法。类方法通过装饰器@classmethod进行定义,第一个参数通常被命名为cls,用于表示类本身。

类方法可以通过类直接调用,也可以通过实例调用。类方法可以访问类的属性,但不能访问实例的属性。

以下是一个类方法的示例:

class MathUtils:
    @classmethod
    def add(cls, x, y):
        return x + y

# 直接调用类方法
print(MathUtils.add(2, 3))  # 输出结果为 5

# 通过实例调用类方法
math = MathUtils()
print(math.add(4, 5))  # 输出结果为 9

在上述代码中,我们定义了一个类方法add(),它接受两个参数并返回它们的和。类方法add()可以通过类直接调用,也可以通过实例调用。

静态方法

  • 静态方法(Static Method):静态方法是与类无关的方法,它既不需要访问实例的属性,也不需要访问类的属性。静态方法通过装饰器@staticmethod进行定义,它不需要额外的参数。

静态方法可以通过类直接调用,也可以通过实例调用。静态方法与类的任何特定实例无关,因此不需要访问实例属性。

以下是一个静态方法的示例:

class StringUtils:
    @staticmethod
    def reverse(string):
        return string[::-1]

# 直接调用静态方法
print(StringUtils.reverse("Hello"))  # 输出结果为 "olleH"

# 通过实例调用静态方法
string_util = StringUtils()
print(string_util.reverse("World"))  # 输出结果为 "dlroW"

在上述代码中,我们定义了一个静态方法reverse(),它接受一个字符串作为参数,并返回反转后的字符串。静态方法reverse()可以通过类直接调用,也可以通过实例调用。

6.属性访问和属性装饰器

在面向对象编程中,属性访问和属性装饰器提供了一种更灵活和安

全的方式来访问和设置对象的属性。

属性访问

属性访问允许我们通过类的实例来访问和修改对象的属性。属性访问使用特殊的方法,如__getattribute__()__getattr__()__setattr__()__delattr__()等。

以下是一个属性访问的示例:

class Person:
    def __init__(self, name):
        self.name = name

    def __getattribute__(self, attr):
        print("Accessing attribute:", attr)
        return super().__getattribute__(attr)

    def __setattr__(self, attr, value):
        print("Setting attribute:", attr)
        super().__setattr__(attr, value)

    def __delattr__(self, attr):
        print("Deleting attribute:", attr)
        super().__delattr__(attr)

person = Person("Alice")
print(person.name)  # 输出结果为 "Accessing attribute: name" 和 "Alice"

person.age = 25  # 输出结果为 "Setting attribute: age"
del person.name  # 输出结果为 "Deleting attribute: name"

在上述代码中,我们重写了Person类的特殊方法__getattribute__()__setattr__()__delattr__(),并在其中添加了额外的逻辑。

当访问属性时,__getattribute__()方法会被调用,并打印出相应的信息。当设置属性时,__setattr__()方法会被调用,并打印出相应的信息。当删除属性时,__delattr__()方法会被调用,并打印出相应的信息。

属性装饰器

属性装饰器提供了一种更简洁和优雅的方式来定义和管理对象的属性。属性装饰器可以用于访问、设置和删除属性,并允许在访问属性时执行额外的逻辑。

以下是一个属性装饰器的示例:

class Person:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        print("Getting name")
        return self._name

    @name.setter
    def name(self, value):
        print("Setting name")
        self._name = value

    @name.deleter
    def name(self):
        print("Deleting name")
        del self._name

person = Person("Alice")
print(person.name)  # 输出结果为 "Getting name" 和 "Alice"

person.name = "Bob"  # 输出结果为 "Setting name"
del person.name  # 输出结果为 "Deleting name"

在上述代码中,我们使用@property装饰器定义了一个名为name的属性,并为它定义了相应的gettersetterdeleter方法。

当访问属性时,getter方法会被调用,并打印出相应的信息。当设置属性时,setter方法会被调用,并打印出相应的信息。当删除属性时,deleter方法会被调用,并打印出相应的信息。

通过使用属性装饰器,我们可以像访问普通属性一样访

问、设置和删除属性,并在其背后执行自定义的逻辑。

7.OOP的设计和构建更复杂的程序

面向对象编程不仅仅是一种编程范式,它还提供了一种思考和设计程序的方法。通过使用OOP的概念和原则,可以更好地组织代码、降低耦合性、提高可维护性,并且可以构建更复杂的程序。

以下是一些常用的OOP设计原则和技巧:

  • 封装(Encapsulation):将数据和操作数据的方法封装在一个对象中,隐藏内部实现细节,通过公开的接口与对象进行交互。
  • 组合(Composition):通过将对象组合在一起,创建更复杂的对象或数据结构。对象之间的组合关系可以是一对一、一对多或多对多。
  • 接口(Interface):定义对象的公共接口,明确规定对象所支持的方法和属性。接口提供了一种契约,用于指导对象之间的交互。
  • 继承(Inheritance):使用继承来重用和扩展现有类的功能。子类继承父类的属性和方法,并可以添加自己的特定行为。
  • 多态(Polymorphism):通过继承和方法重写,使得不同类型的对象可以以相同的方式进行处理,提供了更大的灵活性和扩展性。

这些原则和技巧可以帮助你设计和构建更复杂的程序,提高代码的可读性、可维护性和可扩展性。

总结

本文介绍了面向对象编程的基本概念和原则,包括类和对象的定义、封装、继承和多态。此外,还介绍了类方法和静态方法的使用,以及属性访问和属性装饰器的应用。

掌握面向对象编程的基本概念和技巧,将使您能够更好地设计和组织代码,提高代码的可读性、可维护性和可扩展性。

你可能感兴趣的:(python,学习笔记,python,学习,笔记)