Dunder(双下划线)或魔法方法是 Python 中的特殊方法,允许自定义类和对象。这些方法被称为魔法,因为它们可以以意外的方式更改代码的行为。理解和实现这些方法可以极大地增强 Python 程序的功能和灵活性。
构造对象和表达式
在 Python 中,对象是类的实例,这些类定义了对象的属性和方法。在 Python 中创建对象的过程涉及定义一个类,该类指定对象的结构和行为,然后创建该类的实例。
在 Python 中定义类
要在 Python 中定义类,请使用 class
关键字,后跟类名。例如,以下代码定义了一个名为 Person
的简单类
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print(f"Hello, my name is {self.name} and I am {self.age} years old.")
__init__
方法是一个特殊方法,当创建类的实例时调用该方法。它初始化对象属性。
Python __init__
魔法方法
__init__
方法是一个特殊的魔法方法,当创建类的实例时调用该方法。它初始化对象属性。在上面的示例中,__init__
方法采用两个参数 name
和 age
,用于初始化对象的 name
和 age
属性。
在 Python 中创建类的实例
要创建类的实例,请像调用函数一样调用类,传递 __init__
dunder 方法所需的任何参数。例如,以下代码创建了 Person
类的两个实例
# Defining a car class
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def describe_car(self):
print(f"The car is a {self.year} {self.make} {self.model}.")
# Creating an instance of Car class
car1 = Car("Honda", "Accord", 2021)
# Calling the describe_car method
car1.describe_car()
# Output: The car is a 2021 Honda Accord.
# Defining a book class
class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages
def describe_book(self):
print(f"The book '{self.title}' is written by {self.author} and has {self.pages} pages.")
# Creating an instance of Book class
book1 = Book("The Alchemist", "Paulo Coelho", 208)
# Calling the describe_book method
book1.describe_book()
# Output: The book 'The Alchemist' is written by Paulo Coelho and has 208 pages.
创建迭代器对象
迭代器是一个对象,它支持对项目集合进行顺序迭代(循环),一次一个项目。在 Python 中,可以使用类或函数创建迭代器对象。
Python 生成器类
可以使用 Python 中的生成器类创建迭代器。生成器类是一种对象类型,用于使用 yield
语句创建可迭代对象。
class MyGenerator:
def __init__(self):
self.num = 0
def __iter__(self):
return self
def __next__(self):
if self.num <= 5:
value = self.num
self.num += 1
return value
else:
raise StopIteration
def my_generator():
num = 0
while num <= 5:
yield num
num += 1
# Using the generator class
gen = MyGenerator()
for x in gen:
print(x)
# Using the function generator
gen = my_generator()
for x in gen:
print(x)
在此示例中,MyGenerator
是一个从内置 object
类继承的生成器类。它定义了一个 __init__()
方法,该方法将 num
属性初始化为 0。它还定义了一个 __iter__()
方法,该方法返回迭代器对象(在本例中为 self
),以及一个 __next__()
魔法方法,该方法生成序列中的下一个值。
还可以使用Python 函数生成器创建迭代器。函数生成器是包含 yield
语句的函数。
在此示例中,my_generator
函数是一个函数生成器,它使用 yield
语句生成序列中的下一个值。
在以上两个示例中,可以如下创建迭代器对象
迭代时,这两个代码示例都将输出值 0
、1
、2
、3
、4
和 5
。
处理属性引用
属性引用用于访问 Python 中对象的属性。可以使用点表示法语法访问它们,也可以使用 getattr()
函数动态访问它们。
getattr()
函数接受两个参数 - 需要访问其属性的对象和作为字符串的属性名称。如果找不到该属性,则会引发 AttributeError
。
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
my_dog = Dog("Max", "German Shepherd")
print(my_dog.name) ### Output
my_cat = {"name": "Fluffy", "breed": "Persian"}
cat_name = getattr(my_cat, "name")
print(cat_name) ### Output
在第一种情况下,我们创建一个 Dog
类,并使用点表示法语法访问 name
属性。
在第二种情况下,我们创建一个字典对象 my_cat
,并使用 getattr()
函数动态访问 name
属性。我们将属性值存储在 cat_name
中并将其打印出来。
使用魔法方法将对象表示为字符串
在 Python 中,我们可以使用 __repr__()
dunder 方法将对象表示为字符串。当我们使用 repr()
函数或使用 print()
函数打印对象时,将调用此方法。
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
p = Point(2, 3)
print(p) ### Output
在上面的代码中,我们定义了一个具有 x
和 y
属性的 Point
类。我们还定义了一个 __repr__()
dunder 方法,该方法返回 Point
对象的字符串表示形式。当我们打印 p
对象时,它会调用 __repr__()
魔术方法以获取其字符串表示形式。
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def __repr__(self):
return f"Car(make={self.make}, model={self.model}, year={self.year})"
c = Car("Toyota", "Camry", 2021)
print(c) ### Output
在此示例中,我们定义了一个具有 make
、model
和 year
属性的 Car
类。我们还定义了一个 __repr__()
方法,该方法返回 Car
对象的字符串表示形式。当我们打印 c
对象时,它会调用 __repr__()
dunder 方法以获取其字符串表示形式。
使用 Dunder 方法清理对象
在 Python 中,当不再需要对象时,会自动对其进行垃圾回收。但是,有时可能需要为对象定义其他清理操作。可以使用 __del__
方法来实现此目的,该方法在对象即将被销毁时调用。
此 dunder 方法对于释放资源(例如文件、网络连接或其他未由 Python 自动管理的系统级对象)非常有用。
class MyClass:
def __init__(self):
self.file = open('example.txt', 'r')
def __del__(self):
self.file.close()
在此示例中,MyClass
构造函数创建一个文件对象并将其存储在 file
实例变量中。当对象被销毁时,将调用 __del__
方法,该方法关闭文件。
使用 Dunder 方法执行比较
Python 提供了多种比较值、变量或表达式的途径。一些用于执行比较的常用运算符包括 ==
、!=
、>
、<
、>=
、<=
、in
和 is
。
Python 比较字符串
__lt__()
方法用于在 Python 中实现小于比较运算符。如果第一个字符串小于第二个字符串,则返回 True
,否则返回 False
。
string1 = "apple"
string2 = "banana"
if string1.__lt__(string2):
print("string1 is less than string2")
else:
print("string1 is greater than or equal to string2")
# Output:
#string1 is less than string2
fruits = ["apple", "banana", "orange", "kiwi"]
sorted_fruits = sorted(fruits, key=lambda x: x.__lt__("c"))
print(sorted_fruits)
# Output:
# ['orange', 'kiwi', 'apple', 'banana']
在上面的示例中,我们根据每个字符串的第一个字符是否小于或大于 c
,按升序对水果列表进行了排序。lambda x: x.__lt__(
c)
返回 True
(如果 x
的第一个字符小于 c
)或 False
(否则)。