Python 传参方式;可变/不可变对象

1.以下Python代码分别输出什么?

         考察点:传参方式;可变对象。 

               Python传递值还是引用呢?都不是,唯一支持的参数传递是共享传参。

               Call by Object (Call by Reference or Call by Sharing)

               Call by sharing(共享传参)。函数形参获得实参中各个引用的副本,实际是通过对象引用进行传递的。

(1)可变类型作为参数(可变对象,形参和实参都是指向同一个对象,叫做对象传递或引用传递)

def flist(l):
	l.append(0)
	print(l)


ll = []
flist(ll)
flist(ll)

list 是可变对象

输出结果:

              [0]

              [0, 0]

 

(2)不可变类型作为参数(不可变对象,表现像copy的值,去修改它的新的这个值,实际不是这样)

def fstr(s):
	s += 'a'
	print(s)


ss = 'hehe'
fstr(ss)
fstr(ss)

 

str 是不可变对象

输出结果:

              hehea

              hehea

2.Python如何传递参数?

python通过对象引用进行传递,根据传递变量是可变还是不可变对象,然后得到两种不同结果。所以既有表现得像传引用,又有时候表现得像传入一个值。

         Python中一切皆对象,传递参数的时候实际是通过对象引用进行传递的就是实参和形参都指向同一个对象,但是因为Python里面有可变和不可变对象,所以对可变和不可变表现出了两种作用,一种是不可变对象时候变现的有点像传值就相当于把原来值拷贝一下其实并不是这样;一种是可变对象,对于可变对象来说因为指向的本身就是同一个对象所以直接可以在内存中修改它。而不可变对象不可修改它是因为每次赋值时候它会创建一个新的对象并且让你原来的形参去指定新对象。

3.Python可变/不可变对象

搞懂可变和不可变内置对象有利于理解函数参数的副作用即会不会修改它。

 哪些是可变对象?哪些是不可变对象?

        不可变对象 bool / int / float / tuple/ str / frozenset(固定集合)

        可变对象 list / set / dict

        (需要注意的是:如果传递的是可变对象作为参数,修改它的时候对外面是可见的)

 

4.一个小例题,请问这段代码会输出什么结果?

         提示:可变对象的一个错觉以为改变原来的值。

 

def clear_list(l):
    l = [ ]     # 形参指向一个新的值
    
ll = [1, 2, 3]  
clear_list(ll)
print(ll)  

这个过程还是解释一下:首先在一块内存中定义一个列表[1, 2, 3], 定义变量时候 ll 变量指向这块内存,调用函数传入 ll 实参,此时 l 形参也指向和 ll一样这块内存。这时候又在一块内存中定义空列表[],并赋值给 l ,然后 l 指向就变了指向了空列表这块内存。列表[1, 2, 3]并没有被操作。ll 指向没有改变所以值也就不变。

输出结果:

[1, 2, 3]

5.Python可变参数作为默认参数(默认参数只计算一次)

def flist(l=[1]):
    l.append(1)
    print(l)

flist()
flist()

输出结果:

[1, 1]

[1, 1, 1]

 

 

 

 

<think>好的,我现在需要回答用户关于Python可变对象不可变对象的问题。首先,我得回忆一下Python的基本数据类型,并确定它们的可变性。 我记得不可变对象包括像整数、浮点数、字符串、元组这些类型。比如,当修改字符串时,实际上是创建了一个新的字符串,原字符串不变。而可变对象比如列表、字典、集合,这些在修改时会直接改变对象本身,而不会创建新的对象。 接下来,我需要确认每个具体的数据类型是否正确分类。比如布尔类型属于不可变,因为它是基于整数的,对吧?还有frozenset应该是不可变的集合,而普通的set是可变的。这些都需要提到。 然后,用户可能需要例子来理解两者的区别。比如,列表添加元素后id不变,而字符串修改后id会变。这有助于说明可变可变的差异。 另外,我需要解释为什么可变不可变对象在函数参数传递时表现不同,比如不可变对象作为参数时不会被函数内的操作改变,而可变对象可能会被修改。这一点对理解Python传参机制很重要。 可能还需要提到一些注意事项,比如字典的键必须是不可变类型,所以列表不能作为键,但元组可以。这也关联到可变可变的应用场景。 结构方面,先分类列出不可变可变对象,再举例说明,然后讨论它们的区别影响,最后总结注意事项。这样用户能逐步理解概念。 需要确保术语使用正确,比如“不可变”对应immutable,“可变”对应mutable。同时,避免使用复杂术语,保持解释清晰易懂。 可能用户会混淆某些类型,比如bytes是否不可变?是的,bytes对象也是不可变的,而bytearray是可变的。这些细节需要确认。 最后,检查是否有遗漏的类型,比如NoneType属于不可变,但用户可能更关心常见类型。所以重点放在常用的数据类型上。 总结步骤: 1. 定义不可变可变对象。 2. 列出不可变对象的具体类型。 3. 列出可变对象的具体类型。 4. 用示例说明差异。 5. 讨论对编程的影响,如参数传递、哈希等。 6. 注意事项常见误区。 现在将这些整理成结构化的回答,确保每个部分清晰,并且例子准确。</think>在Python中,对象分为**可变对象****不可变对象**,它们的核心区别在于:对象创建后是否允许修改其内部值(内存地址是否变化)。以下是具体分类说明: --- ### **一、不可变对象(Immutable)** 不可变对象一旦创建,其值不可被修改。若尝试修改,Python会创建新对象并重新分配引用。 1. **常见不可变类型** - **数值类型** - 整数:`int`(如 `5`, `-3`) - 浮点数:`float`(如 `3.14`) - 复数:`complex`(如 `1+2j`) - 布尔:`bool`(本质是 `int` 的子类,`True=1`, `False=0`) - **字符串**:`str`(如 `"hello"`) - **元组**:`tuple`(如 `(1, 2, 3)`,但若元组内包含可变对象,其内容可能间接改变) - **字节串**:`bytes`(如 `b"abc"`) - **冻结集合**:`frozenset` 2. **示例说明** ```python a = 5 # 创建整数对象5,a指向内存地址A a += 1 # 创建新整数6,a改为指向地址B print(id(a)) # 地址B ≠ 地址A ``` --- ### **二、可变对象(Mutable)** 可变对象允许在内存地址不变的情况下修改其内容。 1. **常见可变类型** - **列表**:`list`(如 `[1, 2, 3]`) - **字典**:`dict`(如 `{"a": 1}`) - **集合**:`set`(如 `{1, 2, 3}`) - **字节数组**:`bytearray` - **自定义类实例**(默认可变,除非显式限制) 2. **示例说明** ```python lst = [1, 2] # 内存地址C lst.append(3) # 修改lst内容,内存地址仍为C print(id(lst)) # 地址C不变 ``` --- ### **三、关键区别与影响** 1. **赋值与修改行为** - 不可变对象的赋值会复制值(或引用),修改时生成新对象。 - 可变对象的赋值传递引用,多个变量可能指向同一对象。 ```python # 不可变示例 x = "abc" y = x # xy指向同一字符串 x += "d" # x指向新字符串"abcd",y仍指向"abc" # 可变示例 a = [1, 2] b = a # ab指向同一列表 a.append(3) # ab同时变为[1, 2, 3] ``` 2. **函数参数传递** - 不可变对象作为参数时,函数内修改不会影响原对象。 - 可变对象作为参数时,函数内修改会影响原对象。 ```python def modify(num, lst): num += 1 # 不影响外部的num(不可变) lst.append(4) # 修改外部lst(可变) n = 10 my_list = [1, 2] modify(n, my_list) print(n) # 输出10(未变) print(my_list) # 输出[1, 2, 4] ``` 3. **哈希性(Hashable)** - 不可变对象可哈希(可用作字典键或集合元素)。 - 可变对象不可哈希(无法作为字典键)。 ```python d = {} d[(1, 2)] = "ok" # 元组(不可变)作为键 d[[1, 2]] = "error" # 报错!列表不可哈希 ``` --- ### **四、注意事项** 1. **元组的特殊性** 元组本身不可变,但若包含可变元素(如列表),其内部可变元素仍可修改: ```python t = ([1, 2], 3) t[0].append(3) # 允许!t变为([1, 2, 3], 3) ``` 2. **性能考量** 频繁修改不可变对象(如字符串拼接)会产生大量临时对象,此时建议使用可变类型(如列表)优化性能。 --- ### **总结** | 类型 | 不可变对象 | 可变对象 | |----------|--------------------------------|---------------------| | 典型示例 | `int`, `str`, `tuple` | `list`, `dict`, `set` | | 修改行为 | 创建新对象 | 原地修改 | | 哈希性 | 可哈希 | 不可哈希 | | 内存效率 | 修改时可能低效 | 高效 |
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值