Python:可变对象、不可变对象、迭代器可迭代对象

一、可变对象与不可变对象

在Python中,对象可以分为可变对象和不可变对象。可变对象是指在创建后其值可以更改,而不可变对象则是指创建后其值不可更改。

常见的可变对象包括列表(List)、字典(Dict)和集合(Set),而不可变对象包括数值类型(int、float、complex)、布尔类型(bool)、字符串(str)、元组(tuple)和不可变集合(frozenset)等。

区别:

1、内存层面:

在内存层面,可变对象和不可变对象的主要区别在于其值存储的方式。不可变对象的值存储在对象的固定内存地址中,一旦创建就不能更改。而可变对象的值存储在可变的内存地址中,其内部结构也可能发生改变。

下面示例代码可以看到,在创建一个不可变对象(比如数字)时,其内存地址是不变的:

a = 10
print(id(a))  # 输出:140734751454848
a = 20
print(id(a))  # 输出:140734751455168

而在创建一个可变对象(比如列表)时,其内存地址可以发生变化:

li = [1, 2, 3]
print(id(li))  # 输出:140734751657672
li.append(4)
print(id(li))  # 输出:140734751657672

2、源码层面:

在源码层面,可变对象和不可变对象的主要区别在于其是否支持原处修改(in-place modification)。不可变对象不支持原处修改,而可变对象则支持。

下面的示例代码可以看到,尝试在一个不可变对象(比如元组)中进行修改会导致异常:

tup = (1, 2, 3)
tup[0] = 4  # 报错:TypeError: 'tuple' object does not support item assignment

而在一个可变对象(比如列表)中进行修改则不会出现这个问题:

li = [1, 2, 3]
li[0] = 4
print(li)  # 输出:[4, 2, 3]

二、迭代器和可迭代对象

1、迭代器

Python迭代器是一种可以遍历容器对象(例如列表、元组和字典)中的元素的对象。从源代码实现的角度来看,Python中的迭代器是一种实现了特定协议的对象。这个协议包括两个方法:

__iter__()__next__()。实现了这两个方法的对象就是迭代器。

__iter__()方法返回一个迭代器对象自身,这个对象将被用来遍历容器中的元素。

__next__()方法返回容器中的下一个元素。当迭代器已经到达了容器的末尾,__next__()方法将会抛出一个StopIteration异常。

从内存分配的角度来看,迭代器是一种能够更加高效地遍历容器中的元素的方式。与列表等容器对象不同,迭代器仅需为当前迭代的元素分配内存,而不是为容器中的所有元素分配内存。这意味着迭代器在处理大量数据时可以节省内存,并且可以更快地处理大型数据集。

在Python中,可以使用iter()函数来创建一个迭代器对象。例如,下面的代码创建了一个迭代器对象,并使用next()函数遍历了它的元素:

my_list = [1, 2, 3, 4, 5]
my_iter = iter(my_list)
print(next(my_iter))  # 输出:1
print(next(my_iter))  # 输出:2
print(next(my_iter))  # 输出:3

当容器中的元素已经被遍历完时,再调用next()函数将会触发StopIteration异常。在实际编程中,我们通常使用for循环语句遍历迭代器中的元素,这样就可以避免StopIteration异常的出现。例如:

my_list = [1, 2, 3, 4, 5]
for item in my_list:
    print(item)

这段代码中,my_list对象被转换成迭代器对象,并使用for循环语句遍历其中的元素。在遍历完所有元素后,循环语句自动结束,不会抛出StopIteration异常。

2、可迭代对象

可迭代对象是指能够被迭代的对象,例如列表、元组、字典、集合等。从源代码实现的角度来看,Python中的可迭代对象在实现上是通过实现__iter__()方法和__next__()方法来完成的。

iter()方法定义了可迭代对象应该如何被迭代。该方法应该返回一个迭代器对象。迭代器对象需要实现__next__()方法,返回下一个迭代值,如果没有更多的值可以迭代,应该抛出StopIteration异常。

例如,以下是一个实现了__iter__()方法和__next__()方法的简单的可迭代对象:

class MyIterable:
    def __init__(self):
        self.data = [1, 2, 3]
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == len(self.data):
            raise StopIteration
        value = self.data[self.index]
        self.index += 1
        return value

这个对象可以使用for循环来迭代:

for value in MyIterable():
    print(value)

输出结果为:

1
2
3

需要注意的是,Python中的可迭代对象不一定需要实现__next__()方法,如果一个对象只实现了__iter__()方法,那么它就是一个迭代器对象,而不是可迭代对象。但是,实现了__iter__()方法的可迭代对象会在每次迭代时返回一个新的迭代器对象,因此,如果要在多个迭代中共享迭代状态,应该实现一个独立的迭代器对象并返回它。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值