跳至主要内容

类方法和属性

Class Methods and Properties in Python

本文探讨了在 Python 中的类 中使用 函数 和方法的来龙去脉。具体来说,我们深入探讨了类构造函数(或 __init__ 方法)、抽象类方法以及类方法和静态方法之间的区别。因此,如果您希望提升对类中函数的理解,请继续阅读!

掌握 Python 类构造函数

我们可以在类中定义函数,称为方法。类构造函数或 __init__ 方法是一种特殊方法,在创建类的对象时调用该方法。它用于初始化类的实例变量。

抽象类方法是一种已声明但没有包含任何实现的方法。它用作在子类中定义的其他方法的模板。

类方法是一种绑定到类而不是类实例的方法。可以使用类名访问它。

静态方法是一种绑定到类而不是类实例的方法。它不接受任何参数,如 self 或 cls。

示例 1:类构造函数

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

p1 = Person("John", 36)

print(p1.name)
print(p1.age)

# Output:
# John
# 36

在上面的示例中,我们定义了一个 Person 类,其中包含一个构造函数,该构造函数初始化类的 name 和 age 属性。然后,我们创建了类 p1 的一个对象,并使用点表示法访问了它的属性。

示例 2:类方法与静态方法

class Calculator:
    @classmethod
    def add(cls, num1, num2):
        return num1 + num2
    
    @staticmethod
    def multiply(num1, num2):
        return num1 * num2

print(Calculator.add(2,3))
print(Calculator.multiply(2,3))
# Output:
# 5
# 6

在此示例中,我们定义了一个 Calculator 类,其中包含两个方法:add 作为类方法和 multiply 作为静态方法。我们使用类名 Calculator 访问了这些方法,而没有创建类的对象。我们使用 @classmethod@staticmethod 装饰器来定义这些方法。

Python 抽象类方法

抽象类方法是在抽象基类中声明但没有实现的方法。它用于定义一个必须由从抽象类继承的任何类实现的方法。使用 @abstractmethod 装饰器创建抽象类方法。以下是 Python 中抽象类方法的一个示例

from abc import ABC, abstractmethod

class Shape(ABC):
    def __init__(self, type):
        self.type = type

    @abstractmethod
    def area(self):
        pass

class Square(Shape):
    def __init__(self, side):
        super().__init__("Square")
        self.side = side

    def area(self):
        return self.side ** 2

my_square = Square(5)
print(my_square.area()) # Output: 25

方法重载

方法重载是 Python 中的一项功能,它允许一个类具有多个同名但参数不同的方法。此功能有助于为代码设计提供灵活性和可重用性。它不同于方法覆盖,后者允许子类提供其超类中定义的方法的实现。

class Example:
    def method(self, a):
        print("Method with one parameter:", a)
    
    def method(self, a, b):
        print("Method with two parameters:", a, b)  
class Example:
    def method(self, a=None, b=None, c=None):
        if a != None and b == None and c == None:
            print("Method with one parameter:", a)
        
        elif a != None and b != None and c == None:
            print("Method with two parameters:", a, b)
            
        elif a != None and b != None and c != None:
            print("Method with three parameters:", a, b, c)

在第一个示例中,我们定义了一个类,其中包含两个同名但参数不同的方法。Python 不直接支持方法重载,因此最后一个方法定义会覆盖前一个方法定义。因此,当我们创建类的对象并调用 method 时,我们将获得最后一个方法定义的输出。

在第二个示例中,我们定义了一个具有一个 method 的类,该 method 接受多个可选参数。我们可以使用条件 语句 来检查传递的参数数量,并相应地 print 输出。这种方法为代码提供了可重用性,因为我们可以使用不同的参数调用同一个 method

Python 中的公共、私有和受保护方法

在 Python 中,我们可以根据公共、私有和受保护方法的访问级别对其进行区分。

  • 公共方法是可以从类内或类外任何地方访问的方法。
  • Python 类中的私有方法只能从类内部访问。
  • 受保护的方法只能从类及其子类内部访问。

公共方法

公共方法可以从类内或类外任何地方访问。它们在与类的属性和功能交互中发挥着重要作用。当开发人员创建不带任何下划线前缀的方法时,它会自动成为公共方法。

class MyClass:
    def public_method(self):
        print("This is a public method")

obj = MyClass()
obj.public_method()  # Accessing the public method

如示例所示,public_method() 可以从类 MyClass 外部访问。这些方法允许外部代码直接与类的功能交互。

Python 私有方法

Python 中的私有方法设计为只能从定义它们的类中访问。它们通过在方法名前加上双下划线 __ 来表示。

class MyClass:
    def __private_method(self):
        print("This is a private method")

obj = MyClass()
obj.__private_method()  # Attempting to access the private method (Raises an error)

尝试从类外部访问私有方法会导致 AttributeError。Python 名称混淆使以双下划线为前缀的方法名更难直接从外部代码访问。这些方法用于内部类操作,增强封装并防止意外误用或覆盖。

受保护的方法

受保护的方法通过在方法名前加上单个下划线 _ 来表示。它们可以从类本身及其子类中访问。

class MyClass:
    def _protected_method(self):
        print("This is a protected method")

class SubClass(MyClass):
    def access_protected(self):
        self._protected_method()  # Accessing the protected method from a subclass

obj = SubClass()
obj.access_protected()  # Accessing the protected method from the subclass

受保护的方法提供了一种允许子类访问某些方法的方法,同时仍然防止外部代码直接访问。但是,与其他一些语言不同,Python 并不强制执行严格的可见性限制。

Python 获取器和设置器方法

Python 提供 getter 和 setter 便利方法来控制对类私有实例变量的访问。getter 和 setter 方法很重要,因为如果没有它们,私有实例变量将无法在类外部访问。

getter 方法允许从类外部访问私有实例变量的值,而 setter 方法允许从类外部设置私有实例变量的值。

下面是一个带有 getter 和 setter 方法的简单示例类

class MyClass:
    def __init__(self):
        self._value = None

    def get_value(self):
        return self._value

    def set_value(self, value):
        self._value = value

obj = MyClass()
obj.set_value(10)
print(obj.get_value())

现在,你可以使用这些方法来访问和设置 MyClassvalue 属性值。

class MyClass:
    def __init__(self):
        self._value = None

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

obj = MyClass()
obj.value = 10
print(obj.value) 

现在,你可以使用 MyClassvalue 属性来获取和设置 value 属性的值

总之,getter 和 setter 方法提供了一种受控的方式来访问和设置 Python 类中的私有实例变量的值。

方法与函数

在 Python 中,方法和函数都用于执行特定任务。但是,它们有一些明显的区别。

函数

函数在类外部定义,可以在代码中的任何地方使用其名称调用。它们获取输入参数并return一个值。下面是一个函数的示例,它将两个数字作为输入并返回它们的和

def add_numbers(x, y):
    return x + y

result = add_numbers(3, 5)
print(result)  # Output: 8

要使用此函数,我们可以调用它并提供输入参数

方法

另一方面,方法在类内部定义,并在该类的实例上调用。它们可以访问实例属性并修改其状态。

这是一个方法的示例,它接受一个输入参数并修改实例的状态

class Car:
    def __init__(self, make, model):
        self.make = make
        self.model = model
        self.speed = 0

    def accelerate(self, speed):
        self.speed += speed

my_car = Car("Toyota", "Corolla")
my_car.accelerate(20)
print(my_car.speed)  # Output: 20

在这个示例中,accelerate() 方法在 Car 类中定义,并在 Car 类的实例上调用。它通过将输入参数添加到实例的 speed 属性中来加速汽车的速度。

总之,函数是独立的代码块,它们接受输入参数并返回一个值,而方法在类中定义,并在该类的实例上调用,可以访问实例属性并修改其状态。

覆盖类方法

方法覆盖是面向对象编程中的一项特性,它允许子类提供对其超类中已定义的方法的不同实现。在 Python 中,方法覆盖很简单,只需在子类中定义一个与超类中方法同名的函数即可。

class Parent:
  def my_method(self):
    print("Parent method called")

class Child(Parent):
  def my_method(self):
    print("Child method called")

obj = Child()
obj.my_method() ### prints Child method called

在这个示例中,Child 类扩展了 Parent 类并覆盖了 my_method() 方法。当我们创建一个 Child 类的对象并调用 my_method() 时,它将打印 Child method called 而不是 Parent method called

class Animal:
  def move(self):
    print("Animal is moving")

class Bird(Animal):
  def move(self):
    super().move()
    print("Bird is flying")

obj = Bird()
obj.move() ### prints "Animal is moving" and "Bird is flying

在这个示例中,Bird 类扩展了 Animal 类并覆盖了类方法 move()。但是,它还首先使用 super() 函数调用超类的 move() 实现,然后添加它自己的 Bird is flying 实现。输出将是 Animal is movingBird is flying

在 Python 中使用方法覆盖可以提高类的行为的灵活性并进行自定义。

与我们一起贡献!

不要犹豫,在 GitHub 上为 Python 教程做出贡献:创建一个分支,更新内容并发出拉取请求。

Profile picture for user AliaksandrSumich
Python 工程师,第三方 Web 服务集成专家。
更新:05/03/2024 - 21:52
Profile picture for user angarsky
已审阅并批准