【CS61A】CS61A——Mutablity

  • ~2.87K 字
  1. 1. Mutablity
    1. 1.1. Objects
    2. 1.2. e.g. String
    3. 1.3. Mutation Operations
      1. 1.3.1. 一些对象是可以改变的
      2. 1.3.2. 函数调用时发生的Mutation
      3. 1.3.3. 表达式的Mutation
    4. 1.4. Tuples
    5. 1.5. Mutation
      1. 1.5.1. 相同与改变
      2. 1.5.2. Identity Operators
      3. 1.5.3. 可变对象在函数中的默认值
    6. 1.6. Mutable Fuctions

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
14
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并修改其值,该列表总是这个列表,随着时间其中的内容被更改 为了实现每次更改列表中的值,该函数使用了可变对象来创建了一个可变函数

赞助喵
非常感谢您的喜欢!
赞助喵