Mutablity
Objects
- 对象用于表达信息,是一种包含了数据与行为的数据抽象
- 有属性的东西都可以作为对象,python中一切皆对象
- Python中,优先级最高的对象被称为类(class)
- 面向对象编程(OOP):
- 对象是OOP的核心
- OOP使用一种暗喻来组织大型程序
- 使用一种特殊语法可以提高程序的可读性与组织
- 很多数据操作都是通过对象实现的
- 对象可以做许多相关的事情,而函数只能做一件事
e.g. String
字符串是一种表达文本的数据抽象 ### 字符串的表示 目前常见的表示方法是用ASCII与Unicode字符集表示字符 前者包含了控制字符、数字、字母与标点,后者则包含了不同语言中的更多字符
1
2
3
4
from unicodedata import name, lookup
print(name('A')) # 查询字符集中的字符名称
print(lookup('BABY')) # 根据字符名称输出对应字符
print(lookup('BABY').encode()) # 查看该字符的字节编码LATIN CAPITAL LETTER A
👶
b'\xf0\x9f\x91\xb6'
Mutation Operations
一些对象是可以改变的
1
2
3
4
5
6
7
8
9
10
11
suits = ['coin', 'string', 'myriad']
original_suits = suits
print(suits.pop()) # 弹出一个元素(默认最后一个)
suits.remove('string') # 移除指定元素
print(suits)
suits.append('cup') # 在尾部增加一个元素
suits.extend(['sword', 'club']) # 添加序列中的多个元素来拓展列表
print(suits)
suits[2] = 'spade'
suits[0:2] = ['heart', 'diamond']
print(original_suits)myriad
['coin']
['coin', 'cup', 'sword', 'club']
['heart', 'diamond', 'spade', 'club']
根据以上代码发现,我们可以对一个对象(suits)进行若干操作来变化其值 而我们在最初将suits与original_suits进行绑定,故变化也会在original_suits中体现 综上,所有指向相同对象的names都会受到Mutation的影响,其中这里的mutation指对象发生的变化 只有可变类型的对象才能更改,如列表与字典
函数调用时发生的Mutation
函数可以更改其作用域中任何可变对象的值
1
2
3
4
5
def mystery(s):
s.pop()
s.pop()
four = [1,2,3,4]
mystery(four)mystery函数实现了对列表对象值的更改,甚至mystery不需要传入参数,直接更改其所在作用域(全局作用域)中four列表的内容
表达式的Mutation
表达式的值会随着names绑定值或对象的改变而改变
1
2
3
4
x = [1,2]
print(x+x)
x.append(3)
print(x+x)[1, 2, 1, 2]
[1, 2, 3, 1, 2, 3]
Tuples
- 元组是一种不可变的序列,使用圆括号包裹起来
- 实际上,任何以逗号隔开的元素都会被解释成元组,非必须加圆括号
- 使用
tuple()创建元组或将其他序列转化为元组 - 在单个元素后加一个逗号可以将单个元素转化成元组
- 元组可以相加,也可以使用成员运算符in来判断元素是否存在
- 由于元组不可变,可以将其作为字典的键使用
- 若元组中包含了可变对象,则该对象可以被更改
1
2
3
s = ([1,2],3)
s[0][0]=4
print(s)([4, 2], 3)
Mutation
相同与改变
1
2
3
4
5
a = [10]
b = a
print(a==b)
a.append(20)
print(a==b)True
True
在这个例子中,我们可以说a与b是相同的,因为b与a绑定到了同一个对象,当对其中一个发生变化,另一个也会同时改变
1
2
3
4
5
a = [10]
b = [10]
print(a==b)
b.append(20)
print(a==b)在这个例子中,a与b是不同的,尽管它们曾有过相同的内容,但对b进行改变后,a会随之改变,因此这时二者便不同了
Identity Operators
Identity: <exp0> is <exp1>
当两个表达式指向相同对象时返回True Equality
<exp0> == <exp1>
当两个表达式拥有相同值时返回True
相同对象始终拥有相等的值,但反之不一定成立
1
2
3
4
5
a = [10]
b = [10]
c = b
print(a is b)
print(b is c)False
True
可变对象在函数中的默认值
函数中声明的默认值是函数值的一部分,而不是每次调用时才生成 这导致了若该对象是可变的,而且在函数中间进行了修改,则该修改会在下次调用函数时保留 如下面的代码,每次调用增加的值会保留在默认值中
1
2
3
4
5
def f(s=[]):
s.append(3)
return len(s)
for i in range(3):
print(f())1
2
3
Mutable Fuctions
在函数中使用可变对象可以在多次调用时保留上次操作的值
1
2
3
4
5
6
7
8
9
10
11
12
13
def make_withdraw_list(balance):
b = [balance]
def withdraw(amount):
if amount > b[0]:
return 'Insufficient funds'
b[0] = b[0] - amount
return b[0]
return withdraw
withdraw = make_withdraw_list(100)
print(withdraw(25))
print(withdraw(25))
withdraw(100)75
50
'Insufficient funds'
该函数将存款存在作为可变对象的列表中
函数中的withdraw函数始终指向列表b并修改其值,该列表总是这个列表,随着时间其中的内容被更改
为了实现每次更改列表中的值,该函数使用了可变对象来创建了一个可变函数
