Python中,类的特殊方法与内置函数的关联
Python类
Python类的设计原则
- 封装(Encapsulation):Python类被设计用来将相关数据和行为封装到一个独立的单元中。
- 继承(Inheritance):Python支持继承,允许子类从父类继承属性和方法。有利于代码的复用和创建相关类的层次结构。
- 多态(Polymorphism):Python支持多态,也就意味着不同类的对象可以被视为同一类型,这使得代码的设计具有更大的灵活性。
- 组合(Composition):Python鼓励使用组合而不是继承,这意味着对象是由其他对象组成的,而不是由父类派生的。这可以使您的代码更加模块化,更易于维护。
- Duck类型(Duck typing):Python使用Duck类型,这意味着对象的类型由其行为而非类决定,这样更容易编写可用于各种对象的通用代码。
- 特殊方法(Special methods):Python提供了许多特殊方法,允许为内置操作自定义行为。例如
__len__
方法允许你定义len()
函数如何处理类的对象。 - 可读性(Readability):与Python的一般设计原则一样,类也应该优先考虑可读性和简单性,也就是说,对方法和属性使用清晰简洁的名称,避免不必要的复杂性。
特殊方法【Special methods】
Python中的特殊方法是一系列预定义的方法,允许你为对象上的内置操作定义自定义行为,使用双下划线前缀和后缀来识别,也成为"dunder"方法。这里讲述一些Python类中常用的特殊方法:
__init__(self, ...)
: 这是构造方法,对象创建时调用,用于初始化对象的属性并设置其初始状态。__str__(self)
: 返回对象的字符串表示,用于创建一个人类可读的字符串表示。__repr__(self)
: 返回对象的字符串表示,用于创建可用于创建对象的字符串表示。__len__(self)
: 返回对象的长度,供len()
函数使用。__getitem__(self, key)
: 这个方法允许你以括号的形式访问对象的元素,可以使用[]
来访问元素。__setitem__(self, key, value)
: 这个方法允许你以括号的形式设置对象元素的值,可以使用[]
来修改元素的值。__delitem__(self, key)
: 这个方法允许你以括号的形式删除对象的元素。__add__(self, other)
: 自定义对象的+
操作方式。__eq__(self, other)
: 自定义对象的==
操作方式。__lt__(self, other)
: 自定义对象的<
操作方式。
这只是较为常用的一些,Python中还提供了很多其他的特殊方法。在你的自定义类中,通过定义这些方法,你可以自定义你对象的行为以更直观、更方便地使用它们。
示例一:
class Person:
def __init__(self, name, age, items):
self.name = name
self.age = age
self.items = items
def __str__(self):
return f"{self.name} ({self.age})"
def __repr__(self):
return f"Person(name='{self.name}', age={self.age})"
person = Person("Alice", 25)
print(person) # output: Alice (25)
print(repr(person)) # output: Person(name='Alice', age=25)
示例二:
class MyObject:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.items[index]
def __setitem__(self, index, value):
self.items[index] = value
def __delitem__(self, index):
del self.items[index]
def __add__(self, other):
new_items = self.items + other.items
return MyObject(new_items)
def __eq__(self, other):
if isinstance(other, MyObject):
return self.items == other.items
return False
def __lt__(self, other):
if isinstance(other, MyObject):
return len(self.items) < len(other.items)
return NotImplemented
obj = MyObject([1, 2, 3])
print(len(obj)) # output: 3
print(obj[1]) # output: 2
obj[1] = 4
print(obj.items) # output: [1, 4, 3]
del obj[1]
print(obj.items) # output: [1, 3]
obj1 = MyObject([1, 2])
obj2 = MyObject([3, 4])
obj3 = obj1 + obj2
print(obj3.items) # output: [1, 2, 3, 4]
obj4 = MyObject([1, 2, 3])
obj5 = MyObject([4, 5])
obj6 = MyObject([1, 2, 3])
print(obj1 == obj2) # output: False
print(obj1 == obj3) # output: True
print(obj1 < obj2) # output: False
print(obj2 < obj1) # output: True
- 格式化字符串
详细解释下这句话,字符串文字前面的f
用于创建格式化字符串(f-string, formatted string
),格式化字符串是一种允许你使用大括号{}
将表达式嵌入占位符中的字符串,这些表达式将在运行时被求值并替换为它们的值。
例如下面的代码中,嵌入的表达式有两个{self.name}
和{self.age}
,运行时,会将这两个表达式替换为其值并返回。
f"Person(name='{self.name}', age={self.age})"
Duck typing
The term "duck typing" comes from the saying, "If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck."
Duck类型是Python等动态类型编程语言中使用的一种编程概念。在Duck类型中,一个对象的类型是由它的行为决定的,而不是它的class或者type决定的。Duck Typing一词来源于这样一句话“如果它看起来像鸭子,游泳像鸭子,嘎嘎叫像鸭子,那么它可能就是鸭子”。
Duck类型使得程序员可以编写适用于任何具有必要属性和方法的对象的代码,比如:
def print_size(obj):
print(len(obj))
该函数接收一个参数obj
并打印其size。由于Python使用duck类型,这个函数适用于任何包含len()
方法的对象,比如字符串、列表、元组、字典等等(string, list, tuple, dictionaries and so on)。
使用Duck类型可以编写更加通用的代码,使得代码更加容易复用和维护。
但是使用Duck类型也极易出错,为了避免这些错误,可是使用类型检查来确保你的代码运行在你期望的对象类型上。
内置函数
- 关于
len(obj)
中的len()
len()
是Python内置函数,用于返回对象的长度。
len()
可被用于多种类型的对象,包括字符串、列表、元组、字典、集合等,并返回对象中元素的数目。
在自定义的类中,通过实现特殊方法__len__()
来使用len()
函数来检索对象的长度,返回值要求是整数。
-
关于内置函数的更多细节
上面讲述的是其中一个内置函数,详细看下,Python中的一些其他内置函数:
print()
: 打印特定信息到控制台,对应__str__()
type()
: 返回对象类型,对应__class__()
len()
: 返回对象长度,对应__len__()
range()
: 生成数字序列,默认从0开始,步长为1,直到某个终止值[不包括]input()
: 接收控制台输入int(), float(), str()
: 将输入转换为某种特定类型,整数、浮点数或字符串。max(), min()
: 在一个序列中找到最大值和最小值,适用于列表、元组、集合等,对应__gt__
,__lt__()
sum()
: 取得序列值得和,适用于列表、元组、集合等sorted()
以升序排序一个序列,适用于列表、元组、集合等zip()
: 将两个或多个序列合并为一个元组序列
示例一:
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})"
def __lt__(self, other):
return self.age < other.age
def __gt__(self, other):
return self.age > other.age
p1 = Person("Alice", 25)
p2 = Person("Bob", 30)
p3 = Person("Charlie", 20)
people = [p1, p2, p3]
print(p1) # Output: Person(name='Alice', age=25)
print(min(people).name) # Output: 'Charlie'
print(max(people).name) # Output: 'Bob'
特殊方法与内置函数的对应:
特殊方法 | 内置函数 | 备注 |
---|---|---|
__len__() |
len() |
返回对象的长度 |
__getitem__(), __setitem__() |
[] |
定义对象元素的访问和修改行为 |
__iter__(), __next__() |
for 等 |
定义对象的迭代行为 |
__contains__() |
in |
判断对象是否包含某个特定元素 |
__add__(), __radd__() |
+ |
定义对象的加法行为 |
__sub__(), __rsub__() |
- |
定义对象的减法行为 |
__mul__(), __rmul__() |
* |
定义对象的乘法行为 |
__divmod__(), __rdivmod__() |
divmod() |
定义对象的余数除法行为 |
__eq__(), __ne__() |
==, != |
定义对象的判等操作 |
__lt__(), __le__(), __gt__(), __ge__() |
<, <=, >, >= |
定义对象间的比较操作 |
__hash__() |
hash() |
定义对象的哈希值(hash value) |
English Version
The key design principles for Python classes
- Encapsulation:Python classes are designed to encapsulated related data and bahavior into a single unit.
- Inheritance:Python supports inheritance, which allows classes to inherit attributes and methods from parent classes. This makes it easier to reuse code and create hierarchies of related classes.
- Polymorphism:Python supports polymorphism, which means that objects of different classes can be treated as if they are the same type. This allows for greater flexibility in the design of your code.
- Composition:Python encourages the use of composition over inheritance, which means that objects are made up of other objects rather than being derived from parent classes. This can make your code more modular and easier to maintain.
- Duck typing: Python uses duck typing, which means that the type of an object is determined by its behavior rather than its class. This makes it easier to write generic code that works with a variety of objects.
- Special methods: Python has a number of special methods that allow you to define custom behavior for built-in operations. For example, the
__len__
method allows you to define how thelen()
function works with objects of your class. - Readability: As with the general design principles of Python, classes should also prioritize readability and simplicity. This means using clear and concise names for methods and attributes, avoiding unnecessary complexity, and following PEP 8 guidelines for formatting.
Special methods
Special methods in Python are a set of predefined methods that allow you to define custom behavior for built-in operations on your objects. They are identified by their double underscore prefix and suffix, also known as "dunder" methods.
Here are some of the most commonly used special methods in Python:
__init__(self, ...)
: This is the constructor method that is called when an object is called. It initializes the object's attributes and sets its initial state.__str__(self)
: This methods returns a string representation of the object. It's called by thestr()
function and by theprint()
statement.__repr__(self)
: This method returns a string representation of the object that can be used to recreate the object. It is called by therepr()
function and by the interactive Python shell. The difference between__str__
and__repr__
is that__repr__
is used to create an unambiguous string representation of an object that can be used to recreate the object, while__str__
is used to create a human-readable string representation of an object.__len__(self)
: This method returns the length of the object. It is called by thelen()
function.__getitem__(self, key)
: This method allows you to access an item in the object using bracket notation. It is called when you use the bracket operation([]
) on the object.__setitem__(self, key, value)
: This method allows you to set the value of an item in the object using bracket notation. It is called when you use the bracket operation([]
) on the object with an assignment.__delitem__(self, key)
: This method allows you to delete an item from the object using bracket notation. It is called when you use thedel
statement on the object with bracket notation.__add__(self, other)
: This method allows you to define how the+
operator works with your object. It is called when you use the+
operator on the object.__eq__(self, other)
: This method allows you to define how the==
operator works with your object. It is called when you use the==
operator on the object.__lt__(self, other)
: This method allows you to define how the<
operator works with your object. It is called when you use the<
operator on the object.
There are many other special methods available in Python, but these are some of the most commonly used ones. By defining these methods in your classes, you can customize the behavior of your objects and make them more intuitive and convenient to use.
Example1:
class Person:
def __init__(self, name, age, items):
self.name = name
self.age = age
self.items = items
def __str__(self):
return f"{self.name} ({self.age})"
def __repr__(self):
return f"Person(name='{self.name}', age={self.age})"
person = Person("Alice", 25)
print(person) # output: Alice (25)
print(repr(person)) # output: Person(name='Alice', age=25)
Example2:
class MyObject:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.items[index]
def __setitem__(self, index, value):
self.items[index] = value
def __delitem__(self, index):
del self.items[index]
def __add__(self, other):
new_items = self.items + other.items
return MyObject(new_items)
def __eq__(self, other):
if isinstance(other, MyObject):
return self.items == other.items
return False
def __lt__(self, other):
if isinstance(other, MyObject):
return len(self.items) < len(other.items)
return NotImplemented
obj = MyObject([1, 2, 3])
print(len(obj)) # output: 3
print(obj[1]) # output: 2
obj[1] = 4
print(obj.items) # output: [1, 4, 3]
del obj[1]
print(obj.items) # output: [1, 3]
obj1 = MyObject([1, 2])
obj2 = MyObject([3, 4])
obj3 = obj1 + obj2
print(obj3.items) # output: [1, 2, 3, 4]
obj4 = MyObject([1, 2, 3])
obj5 = MyObject([4, 5])
obj6 = MyObject([1, 2, 3])
print(obj1 == obj2) # output: False
print(obj1 == obj3) # output: True
print(obj1 < obj2) # output: False
print(obj2 < obj1) # output: True
built-in functions
- what's len() in len(obj) ?
In the context of len(obj)
, len()
is a built-in Python function that returns the length of an object.
The len()
function can be applied to different types of objects in Python, such as strings, lists, tuples, dictionaries, and sets, and it returns the number of elements in the object.
For example, len("Hello")
returns 5 because there are 5 characters in the string "Hello", and len([1, 2, 3])
returns 3 because there are 3 elements in the list [1, 2, 3]
.
In custom classes, the len()
function can be used to retrieve the length of objects by implementing the __len__()
special method, which should return an integer representing the length of the object.
- more details about built-in Python functions
print()
: This function is used to print the specified message or object to the console. It can take multiple arguments, separated by commas, and can also use formatting to display variables and values.type()
: This function returns the type of an object. It takes one argument and returns the type of that object.len()
: This function returns the length of an object. It can be used with objects such as strings, lists, tuples, dictionaries, and sets.range()
: This function generates a sequence of numbers, starting from a specified start value (by default 0), and incrementing by a specified step value (by default 1), up to but not including a specified stop value.input()
: This function is used to get input from the user via the console. It takes one optional argument, which is the prompt to display to the user, and returns a string containing the user's input.int()
,float()
,str()
: These functions are used to convert values from one type to another.int()
converts a value to an integer,float()
converts a value to a floating-point number, andstr()
converts a value to a string.max()
,min()
: These functions are used to find the maximum or minimum value in a sequence. They can be used with objects such as lists, tuples, and sets.sum()
: This function is used to find the sum of all the values in a sequence. It can be used with objects such as lists, tuples, and sets.sorted()
: This function is used to sort a sequence in ascending order. It can be used with objects such as lists, tuples, and sets.zip()
: This function is used to combine two or more sequences into a single sequence of tuples. It takes two or more arguments and returns a zip object containing tuples of elements from the input sequences.
These are just a few examples of the built-in Python functions. Python has many more built-in functions that can be used to perform a variety of tasks, such as manipulating strings, performing mathematical calculations, working with files and directories, and more.