一、Python类的特殊成员概述
在Python中,类中包含一些特殊的方法或属性,它们提供了便捷的方式来实现定制对象的行为和操作。这些特殊的方法或属性常被称为“魔法方法”或“魔术方法”,它们可以被调用,以执行特定的操作或产生特定的结果。
Python中的特殊方法或属性都是以双下划线开头和结尾的,例如__init__
方法。这些方法或属性在类中的定义和调用与普通的方法或属性不同,具有特殊的作用。
二、Python类的构造函数__init__()
1. 构造函数概述
构造函数是类中的一个特殊方法,其名称固定为__init__
,用于创建和初始化对象的属性。在创建对象时,构造函数会自动调用,可以在构造函数中对对象的属性进行初始化,以实现对象的定制化。
构造函数的语法如下:
def __init__(self, 参数列表):
# 初始化代码
其中,self
表示当前对象,在调用构造函数时,Python会自动将当前对象作为第一个参数传递给构造函数。
2. 构造函数示例
以下代码示例定义了一个名为Person
的类,其中包含name
和age
两个属性,并定义了一个构造函数__init__
用于初始化这两个属性:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
在上述代码中,__init__
方法接受两个参数name
和age
,用于初始化对象的属性self.name
和self.age
。
3. 构造函数调用
创建类的对象时,构造函数__init__
会自动调用,可以通过以下语句创建对象:
p = Person("Tom", 20)
在上述语句中,Person("Tom", 20)
表示创建一个Person
类的对象,并将name
属性初始化为"Tom"
,age
属性初始化为20
。
4. 构造函数应用
构造函数可以用于各种定制化场景,例如在创建对象时对属性进行校验或设置一些默认值。以下是一个简单的示例:
import datetime
class User:
def __init__(self, name, birth):
self.name = name
self.birth = birth
self.age = datetime.datetime.now().year - birth.year
def say_hello(self):
print(f"Hello, my name is {self.name}, {self.age} years old.")
user = User("Tom", datetime.date(1990, 1, 1))
user.say_hello()
在上述代码中,User
类的构造函数__init__
用于初始化对象的name
属性和birth
属性。在初始化之后,还计算了age
属性,用于表示用户的年龄,并通过say_hello()
方法打印出用户的信息。
三、Python类的字符串表示__str__()
1. 字符串表示概述
Python中的对象可以通过字符串来描述自己,便于打印、调试和展示。可以通过特殊方法__str__
来实现对象的字符串表示,以便于输出和显示。
特殊方法__str__
返回对象的字符串表示,其返回值为一个字符串。当使用print()
函数或str()
函数显示对象时,会自动调用__str__
方法。
2. 字符串表示示例
以下代码示例定义了一个名为Person
的类,其中包含name
和age
两个属性,并实现了__str__
方法用于返回字符串表示:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Person(name={self.name}, age={self.age})"
p = Person("Tom", 20)
print(p)
在上述代码中,Person
类中的__str__
方法返回类对象的字符串表示,其中包含了name
和age
两个属性的值。
3. 字符串表示应用
字符串表示可以用于对象的输出和调试,尤其是在编写大型程序并进行对象交互时非常有用。以下是一个简单的示例:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def __str__(self):
return f"Rectangle({self.width}, {self.height})"
def area(self):
return self.width * self.height
r = Rectangle(10, 20)
print(f"The area of {r} is {r.area()}")
在上述代码中,Rectangle
类通过__str__
方法返回类对象的字符串表示,并定义了area()
方法用于计算对象的面积,在输出时使用{r}
语法进行字符串格式化。
四、Python类的属性访问__getattr__()和__setattr__()
1. 属性访问概述
Python中的类可以通过属性来描述和访问对象的状态和行为,属性可以看作是类中的变量或函数。
Python类中的属性分为两种:实例属性和类属性。实例属性属于对象的状态,每个实例可以有不同的属性值;类属性属于类的状态,每个实例共享相同的属性值。属性的访问和设置可以通过特殊方法__getattr__
和__setattr__
实现。
2. 属性访问示例
以下代码示例定义了一个名为Person
的类,其中包含name
和age
两个属性,并实现了__getattr__
和__setattr__
方法,用于属性的访问和设置:
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
def __getattr__(self, key):
if key == "name":
return self._name
elif key == "age":
return self._age
else:
return None
def __setattr__(self, key, value):
if key == "name":
self._name = value
elif key == "age":
self._age = value
else:
super().__setattr__(key, value)
p = Person("Tom", 20)
print(p.name)
p.name = "Jerry"
print(p.age)
p.hobby = "reading"
print(p.hobby)
在上述代码中,Person
类中的__getattr__
方法用于访问属性,如果属性存在,则返回对应的值,否则返回None
;__setattr__
方法用于设置属性,如果属性存在,则进行设置操作,否则调用父类的__setattr__
方法。
3. 属性访问应用
属性访问可以用于属性的动态取值和赋值,实现对象状态的灵活控制,以适应不同的需求。以下是一个简单的示例:
class Rectangle:
def __init__(self, width, height):
self._width = width
self._height = height
@property
def width(self):
return self._width
@width.setter
def width(self, value):
if value < 0:
raise ValueError("Width must be non-negative.")
self._width = value
@property
def height(self):
return self._height
@height.setter
def height(self, value):
if value < 0:
raise ValueError("Height must be non-negative.")
self._height = value
def area(self):
return self._width * self._height
r = Rectangle(10, 20)
print(f"The area of {r.width}x{r.height} rectangle is {r.area()}")
r.width = 30
print(f"The area of {r.width}x{r.height} rectangle is {r.area()}")
r.height = -5
print(f"The area of {r.width}x{r.height} rectangle is {r.area()}")
在上述代码中,Rectangle
类通过@property
装饰器将属性width
和height
定义为类属性,同时定义了相应的setter
方法用于输入校验。在调用area()
方法时,可以直接使用类属性进行计算,并在更改属性值时自动触发输入校验。
五、Python类的操作符重载__add__()和__sub__()等
1. 操作符重载概述
Python中的类可以通过操作符重载机制实现对象的自定义操作和运算。通过特殊方法__add__
、__sub__
等,可以重载+、-等操作符,以实现定制的对象运算。
操作符重载是一种高级的特性,可以极大地丰富对象的行为和操作。同时,由于操作符代表了对象之间的关系和交互,因此需要具备一定的设计能力和实践经验。
2. 操作符重载示例
以下代码示例定义了一个名为Complex
的类,用于描述复数运算和操作。通过操作符重载机制,实现了复数的加减乘除等运算:
class Complex:
def __init__(self, real, imag):
self.real = real
self.imag = imag
def __add__(self, other):
return Complex(self.real + other.real, self.imag + other.imag)
def __sub__(self, other):
return Complex(self.real - other.real, self.imag - other.imag)
def __mul__(self, other):
return Complex(self.real * other.real - self.imag * other.imag,
self.real * other.imag + self.imag * other.real)
def __truediv__(self, other):
a, b, c, d = self.real, self.imag, other.real, other.imag
r = float(c ** 2 + d ** 2)
return Complex((a * c + b * d) / r, (b * c - a * d) / r)
def __str__(self):
return f"{self.real} + {self.imag}i"
a = Complex(1, 2)
b = Complex(3, 4)
print(f"({a}) + ({b}) = {a + b}")
print(f"({a}) - ({b}) = {a - b}")
print(f"({a}) * ({b}) = {a * b}")
print(f"({a}) / ({b}) = {a / b}")
在上述代码中,Complex
类通过__add__
、__sub__
、__mul__
和__truediv__
等方法重载了+、-、*、/等操作符。在实现运算时,需要针对不同的操作数进行处理,并返回新的Complex
对象。
3. 操作符重载应用
操作符重载可以用于自定义对象之间的运算和操作,以满足不同的需求和场景。例如,可以重载__getitem__
方法实现对象的下标访问,重载__call__
方法实现对象的函数调用等。以下是一个简单的示例:
class Fibonacci:
def __init__(self):
self.cache = {0: 0, 1: 1}
def __getitem__(self, idx):
if idx < 0:
return None
if idx in self.cache:
return self.cache[idx]
value = self[idx - 1] + self[idx - 2]
self.cache[idx] = value
return value
f = Fibonacci()
for i in range(10):
print(f"Fibonacci({i}) = {f[i]}")
在上述代码中,Fibonacci
类通过__getitem__
方法实现对象的下标访问,以便于返回斐波那契数列中指定索引的值。在访问时,如果缓存中存在对应的值,则直接返回,否则根据上一项和下一项计算出新的值,并保存到缓存中。