可变数据
作者:互联网
引入(Intro)
The behavior of a changing object may be influenced by its history, just like an entity in the world. Adding state to data is a central ingredient of a paradigm called object-oriented programming.
可变数据是一种数据状态可以不断改变的数据类型,它独立与项目的其他部分。它的行为会受到数据变化历史的影响(即前面的操作会影响数据后面的状态)。面对对象编程核心的范式就是给数据增加新的状态。
----John DeNero, UCB
对象的隐喻(The Object Metaphor)
- 对象(Object):对象是数据和行为的组合,不仅可以表示信息,还可以表示行为。
from datetime import date
date 作为类的名称,绑定到一个类(class),可以通过调用这个类来创建实例(Instance)
today = date(2021,2,16)
对象还有自己的属性(attribute),用 ”·“ 来指定对象的属性。
<expression>.<attribute_name>
# expression :赋予对象的名称
# attribute_name: 属性的名称
>>>today.year
2021
对象的属性还可以是函数,称为对象的方法(Method),例如”strftime“方法可以用字符串格式表示时间。
>>>today.strftime('%A, %B %d')
‘Monday,Feburary 16’
计算strftime的返回值需要两个输入值:
- 输出日期的字符串格式
- 绑定到today的日期信息
除了日期,数字、字符串、列表、范围都是对象,都有自己的属性和方法。
数组型对象(Sequence Objects)
初始内置数据的实例是不可变的(immutable),他们的值不会随之程序的执行随之变化。相反,数组就是一种可变数据类型(mutable data)。可变数据类型用来表示会随时间变化的变量。例如一个人,尽管会生老病死,但这个人还是同一个人。
>>> chinese = ['coin', 'string', 'myriad'] # A list literal
>>> suits = chinese # Two names refer to the same list
>>> suits.pop() # Remove and return the final element
'myriad'
>>> suits.remove('string') # Remove the first element that equals the argument
>>> suits.append('cup') # Add an element to the end
>>> suits.extend(['sword', 'club']) # Add all elements of a sequence to the end
我们可以对数组进行一系列方法的调用,来改变这个数组的状态
元组
元组是python的内置实例,是一种不可变类型的序列。元组通过逗号将各元素分隔开,可以加括号也可以不加括号
>>> 1, 2 + 3
(1, 5)
>>> ("the", 1, ("and", "only"))
('the', 1, ('and', 'only'))
>>> type( (10, 20) )
<class 'tuple'>
空元组和单元素元组
>>> () # 0 elements
()
>>> (10,) # 1 element
(10,)
元组是不可变数据类型,所以不能该表元组内部的元素值。如果元组内部含有数组,则可以改变内部的数组。
>>> nest = (10, 20, [30, 40])
>>> nest[2].pop()
(10, 20, [30])
元组一般在多重隐式赋值中被使用。将两个值赋给两个变量名可以创建一个包含两个元素的元组。
字典(Dictionaries)
字典是包含(key:value)数据对的一种数据类型,key和value都是对象。有了字典就不用去按索引查找元素了,可以直接用描述性的key来查找元素。例如在超市报一个菜名,熟练的收银员能立马知道菜的价格。
>>> numerals = {'I': 1.0, 'V': 5, 'X': 10}
>>>> numerals['X']
10
>>> numerals['I'] = 1
#新增元素
>>> numerals['L'] = 50
>>> numerals
{'I': 1, 'X': 10, 'L': 50, 'V': 5}
字典也支持一系列方法:
- .keys: 返回字典的key
- .values:返回字典的元素值
- .items:
- .get:返回元素值,或者是key。输入的参数是key和默认元素值
>>> sum(numerals.values())
66
>>> numerals.get('A', 0)
0
>>> numerals.get('V', 0)
5
字典的限制:
- 字典的key不能包含可变数据类型
- 一个key只能对应一个值
字典的理解型语法(comprehension syntax)
用冒号将key和value隔开,创建一个新的字典。
>>> {x: x*x for x in range(3,6)}
{3: 9, 4: 16, 5: 25}
局部状态(local state)
例如在取款机取钱
>>> def make_withdraw(balance):
"""Return a withdraw function that draws down balance with each call."""
def withdraw(amount):
nonlocal balance # 声明"balance" nonlocal
if amount > balance:
return 'Insufficient funds'
balance = balance - amount # 重新绑定balance
return balance
return withdraw
>>> withdraw = make_withdraw(100)
>>> withdraw(25)
75
>>> withdraw(25)
50
>>> withdraw(60)
'Insufficient funds'
>>> withdraw(15)
35
使用了nonlocal声明后,之后的每一次调用,把balance绑定到初始的余额。Nonlocal表示每当程序要把balance绑定给一个新值的时候,这个变化都会在最初balance被绑定的框架进行。即初始余额是100,取出25后,把剩余的75重新绑定给最初的balance。每次调用withdraw函数,都会创建一个新的框架。每个withdraw框架都有一个共同的母框架。
非本地分配的好处(The Benefits of Non-Local Assignment)
非本地分配可以让程序变得独立自治。例如上面的程序可以建立两个账户,账户之间的的取款在不同的框架内,互不干扰。
def make_withdraw(balance):
def withdraw(amount):
nonlocal balance
if amount > balance:
return 'Insufficient funds'
balance = balance - amount
return balance
return withdraw
wd = make_withdraw(20)
wd2 = make_withdraw(7)
wd2(6)
wd(8)
非本地分配的代价
当把wd和wd2弄混淆的时候,会很容易出错。避免这种错误的关键是记住:只有调用函数才会引入新的框架,只有make_withdraw被调用两次,才会有两个框架。
标签:10,withdraw,元组,key,可变,balance,数据,字典 来源: https://blog.csdn.net/Ennis_Tongji/article/details/113816461