Python编程快速上手-让繁琐工作自动化 — 读书与代码笔记

chapter4

# -*- coding:utf-8 -*-
# @FileName     :chapter4_list.py
# @Time         :2020/8/13 21:38
# @Author       :Wu Hongyi
# @Copyright    :Wu Hongyi
# Function description:
'''
本文件为Python编程快速上手-让繁琐工作自动化一书的第四章示例练习代码
'''
# @version      :Version1.0
# Modification description:
'''

'''

# 列表也可以包含其他列表值。这些列表的列表中的值,可以通过多重
# 下标􁶕来访问
spam = [ ['cat', 'bat'], [10, 20, 30, 40, 50] ]
spam[0]
spam[0][1]
spam[1][4]

# 列表切片
spam = ['cat', 'bat', 'rat', 'elephant']
spam[0:4]
spam[1:3]
spam[0:-1]      # 不取最后一个
spam[:2]
spam[1:]
spam[:]         #相当于复制原列表

# len()函数不仅可以取得字符串长度,还可以取得列表的长度
spam = ['cat', 'dog', 'moose']
len(spam)
len(spam[2])

# 用下标来改变列表中的值
spam = ['cat', 'bat', 'rat', 'elephant']
spam[1]  = 'aardvark'
spam
spam[2] = spam[1]
spam[-1] = 12345

# 列表连接和列表复制
# +操作符可连接两个列表得到一新列表,如同连接字符串一样
# *操作符同理
[1, 2, 3] + ['A', "B", 'C']
['X', 'Y', 'Z'] * 3

# 用del语句从列表中删除值
spam = ['cat', 'bat', 'rat', 'elephant']
del spam[2]
del spam[2]

# 使用列表来整理大量同类型输入值
# allMyCats1.py
catNames = []
while True:
    print('Enter the name of cat ' + str(len(catNames) + 1) + ' (Or enter nothing to stop.):')
    name = input()
    if name == '':
        break
    catNames = catNames + [name]      # list concatenation
print('The cat names are:')
for name in catNames:
    print(' ' + name)

# 列表用于迭代:
for i in [0, 1, 2, 3]:
    print(i)

# 一个常见的Python技巧,是用for循环中使用range(len(someList)),
# 迭代列表的每一个下标。
# 循环中的代码可以访问下标(通过变量i),以及下标处的值(通过
# supplies[i])。最妙的是,range(len(supplies))将迭代supplies的所有
# 下标,无论它包含多少表项
supplies = ['pens', 'staplers', 'flame-throwers', 'binders']
for i in range(len(supplies):    # 注意迭代列表要是整数,可通过列表下标来迭代
    print('Index ' + str(i) + ' in supplies is: ' + supplies[i])

# in 和not in操作符
# 可以用于确定一个值是否在列表中,表达式求值为布尔值
'123' in ['he', 'hiud', '123', '879e9']
'he' not in ['he', 'hiud', '123', '879e9']

# 检查输入的宠物名字是否在宠物列表中
# myPets.py
myPets = ['Zophie', 'Pooka', 'Fat-tail']
print('Enter a pet name:')
name = input()
if name not in myPets:
    print('I do not have a pet named ' + name)
else:
    print(name + ' is my pet.')

# 多重赋值技巧
# 多重赋值可以在一行代码中,用列表的值为多个变量赋值,注意变量数目和列表的长度必须相等,否则报错ValueError
cat = ['fat', 'black', 'loud']
size, color, disposition = cat

# 增强的赋值操作
# 分为:+= -= *= /= %=
# 其中+=操作符可用于完成字符串和列表的连接
# *=操作符可用于完成字符串和列表的复制
spam = 'Hello'
spam += ' world!'
spam

bacon = ['mono']
bacon *= 3
bacon

# 方法
# 方法和函数是一回事,只是它是调用在一个值上。如有一个列表值存储在spam中
# 就可以在该列表上调用index()列表方法( spam.index('hello') ),方法
# 部分跟在这个值后面,以一句点分割

# 用index()方法在列表中查找值
# 在index()方法中传入一个值,如果该值存在于列表,返回其在列表中的下标,否则报ValueError
spam = ['hello', 'hi', 'howdy', 'heyas']
spam.index('hello')
# 当列表中存在重复的值时,就返回其第一次出现的下标
list = ['we', 'detor', 'ok', 'we', 'goose']
list.index('we')

# 用append()和insert()方法在列表中添加值
# append()方法将参数添加到末尾
list = ['we', 'detor', 'ok', 'we', 'goose']
list.append('moose')
list
# insert()方法中第一个参数是新值的下标,第二个是要插入的新值,其将新值添加到列表指定下标处
animals = ['cat', 'dog', 'bat']
animals.insert(1, 'chicken')
animals
# 注意,以上两方法的返回值都为None,故写成list = list.append('value') 是得不到预期结果的,list现在存储的是‘None’
#      以上两方法只可用于列表,不可用于其他值如字符串、元组等使用

# 用remove()方法从列表中删除值
animals = ['cat', 'dog', 'bat', 'rat']
animals.remove('bat')
animals
# 如试图删除列表中不存在的值,将导致ValueError错误

# 如果该值在列表中多次出现,只有第一次出现的值会被删除
animals = ['cat', 'bat', 'rat', 'cat', 'hat', 'cat']
animals.remove('cat')
# 要完全删除某一元素,可用以下代码:
while 'cat' in animals:
    animals.remove('cat')
# 总结:如果知道􁜣要删除的值在列表中的下标,del语句就很好用。如果知道
# 想要从列表中删除的值,remove()方法就很好用

# 用sort()方法将列表中的值排序
# 适用对象:数值的列表或字符串的列表
numlist = [2, 5, 3.14, 1, -8]
numlist.sort()
numlist

charlist = ['ants', 'cats', 'apples', 'dogs', 'elephants']
charlist.sort()
charlist
# 默认情况下sort()方法为正序(数值从小到大,字母(ascii值)从小到大)
# 指定reverse = True时,sort()方法按逆序排序
# 注意:sort()方法当场对列表排序,不要写出spam = spam.sort()这样的代码,试图记录返回值。
#      不能对既有数字又有字符串值的列表排序,因为Python不知道如何比较它们
#      如果列表值中全是字符串且字符串混合了数字和字母也能排序)
#      sort()方法对字符串排序时,使用“ASCII字符顺序”,而不是实际的字典顺序,。这意味着大写字母
#      排在小写字母之前,如需按普通的字典顺序来排序,就在sort()方法调用时,将关键字参数key设置为str.lower。
#      这将导致sort()方法将列表中所有的表项当成小写,但实际上并不会改变他们在列表中的值
strlist = ['12w', '34t', 'a12', 'a23', ’A12‘]
strlist.sort()
strlist

mixlist = [1, 2, 3, 'a', 'e', 'A']      # 不可以对其排序,会报错,列表元素之间类型不同
mixlist.sort()
mixlist


list = ['a', 'z', 'A', 'Z']
list.sort(key = str.lower)
list


# 例程:神奇8球和列表
# 上一章已写过神奇8球程序。利用列表,可以得到更优雅的版本如下:
# magic8Ball2.py
import random
messages = [
    'It is certain',
    'It is decidedly so',
    'Yes definitely',
    'Reply hazy try again',
    'Ask again later',
    'Concentrate and ask again',
    'My reply is no',
    'Outlook not so good',
    'Very doubtful'
]

print(messages[random.randint(0, len(messages) - 1)])

# 续行符:\
# 可以在行末使用续行字符\,将一条指令写成多行。可以把\看成是“这条指令在下一行继
# 续”。\续行字符之后的一行中,缩进并不重要。
print('Four score and seven ' + \
      'years ago...')

# 类似列表的类型:字符串和元组
# 列表并不是唯一表示序列值的数据类型。例如,字符串和列表实际上
# 很相似,只要你认为字符串是单个文本字符的列表。对列表的许多操作,
# 也可以使用于字符串:按下标取值、切片、用于for循环、用于len(),以
# 及用于in和not in操作符
name = 'Zophie'
name[0]
name[-2]
name[0 : 4]
'Zo' in name
'z' in name
'p' not in name
for i in name:
    print('***' + i + '***')

# 可变和不可变数据类型
# 列表:“可变的”数据类型,其值可增删改
# 字符串:“不可变”数据类型,不可被更改,对字符串中的一个字符重新赋值会导致TypeError错误
name = 'Zophie a cat'
name[7] = 'the'

# “改变”一个字符串的正确方式,是使用切片和连接。构造一个“新的”字符串,从老的字符串那里复制一些部分
name = 'Zophie a cat'
newName = name[0:7] + 'the' + name[8:12]
name
newName

# 尽管列表值是可变的,但下面代码中的第二行并没有修改列表eggs:
eggs = [1, 2, 3]
eggs = [4, 5, 6]
eggs
# 这里eggs中的列表值并没有改变,而是整个新的不同的列表值([4, 5, 6])
# 覆写了老的列表值。如果确实希望修改eggs中原来的列表,让它包含[4, 5, 6],就要这样做:
eggs = [1, 2, 3]
del eggs[2]
del eggs[1]
del eggs[0]
eggs.append(4)
eggs.append(5)
eggs.append(6)
eggs
# 改变一个可变数据类型的值(就像前面例子中del语句和append()方法
# 所做的事),当场改变了该值,因为该变量的值没有被一个新的列表值取代。
# 区分可变与不可变类型,似乎没有什么意义,但4.7.1节“传递引用”将解释,
# 使用可变参数和不可变参数调用函数时产生的不同行为

# 元组数据类型  —— 不可变
eggs = ('hello', 42, 0.5)
eggs[0]
eggs[1:3]
len(eggs)

# 元组与列表的主要区别还在于,元组像字符串一样,是不可变的。
# 元组不能让它们的值被修改、添加或删除。
eggs = ('hello', 42, 0.5)
eggs[1] = 99            # 元组不支持修改自身的值

# 如果元组中只有一个值,你可以在括号内该值的后面跟上一个逗号,
# 表明这种情况。否则,Python将认为,你只是在一个普通括号内输入了一
# 个值。逗号告诉Python,这是一个元组(不像其它编程语言,Python接受
# 列表或元组中最后表项后面跟的逗号)
type(('hello', ))
type(('hello'))

# 用list()和tuple()函数来转换类型
# 函数list()和tuple()将返回传递给它们的值的列表和元组版本
tuple(['cat', 'dog', 'rat', 5])
list(('cat', 'dog', 5))      # 利用list()函数将元组转换成列表来生成可变版本很方便
list('hello')

# 引用
# 将列表赋给一个变量时,实际上是将列表的“引用”赋给了该变量。引用是一个值,指向某些数据
# 列表引用是指向一个列表的值
spam = [0, 1, 2, 3, 4, 5]
cheese = spam
cheese[1] = 'Hello!'
spam
cheese
# 上述代码只改变了cheese列表,但cheese和spam列表同时发生了改变。
# 当创建列表时,将对它的引用赋给了变量。但之后只是将spam中的列表
# 引用拷贝到cheese,而不是列表值本身。这意味着存储在spam和cheese
# 中的值,现在指向了同一个列表。底下只有一个列表,因为列表本身实际
# 从未复制。所以当你修改cheese变量的第一个元素时,也修改了spam指向的同一个列表
# 列表变量实际上没有包含列表,而是包含了对列表的“引用”(这些引用包含一些ID数字,
# Python在内部使用这些ID

# 变量包含对列表值的引用,而不是列表值本身。但对于字符串和整数值,变量就包含了字符串或整数值。
# 在变量必须保存可变数据类型的值时,例如列表或字典,python就使用引用。对于不可变的数据类型的
# 值时,例如字符串、整型或元组,python变量就保存值本身

# 传递引用
# 要理解参数如何传递给函数,引用就特别重要。当函数被调用时,参数的值被复制给变量。对于列表
# (以及字典,下一章中讨论),这意味着变元得到的是引用的拷贝
# passingReference.py
def eggs(someParameter):
    someParameter.append('Hello')

spam = [1, 2, 3]
eggs(spam)
print(spam)
# 注意:当eggs()被调用时,没有使用返回值来为spam赋新值。相反,它直接当场修改了该列表
# 尽管spam和someParameter包含了不同的引用,但它们都指向相同的列表。这就是为什么函数
# 内的append('Hello')方法调用在函数调用返回后,仍然会对该列表产生影响

# copy模块的copy()和deepcopy()函数————浅拷贝和深拷贝
# 在处理列表和字典时,尽管传递引用常常是最方便的方法,但如果函数修改了传入的列表或字典
# 你可能不希望这些变动影响原来的列表或字典。要做到这一点,Python提供了名为copy的模块,
# 其中包含copy()和deepcopy()函数。第一个函数copy.copy(),可以用来复制列表或字典这样
# 的可变值,而不只是复制引用
import copy
spam = ["A", "B", "C", "D"]
cheese = copy.copy(spam)
cheese[1] = 42
spam
cheese
# 现在spam和cheese变量指向独立的列表,这就是为什么将42赋给下标1时,只有cheese中的列表被改变
# cheese = copy.copy(spam)创建了第二个列表,能独立于第一个列表修改

# 如果要复制的列表中包含了列表,那就使用copy.deepcopy()函数来代替。deepcopy()函数将同时复制
# 它们内部的列表。
import copy
list1 = ['asdsa', 'sdd', 'pdd', ['wer', 34, 89]]
list2 = copy.copy(list1)
list2[2] = 'fault'
list1
list2

list1[3] = ['qwe', '123']
list1
list2

list3 = ['asdsa', 'sdd', 'pdd', ['wer', 34, 89]]
list4 = copy.deepcopy(list3)
list4[3] = [23, 'a']
list3
list4

# 总结:
# 列表是可变的,这意味着它们的内容可以改变。元组和字符串虽然在某些方面像列表,却是不可变的
# 不能被修改。包含一个元组或字符串的变量,可以被一个新的元组或字符串覆写,但这和现场修改原
# 来的值不是一回事,不像append()和remove()方法在列表上的效果。
# 变量不直接保存列表值,它们保存对列表的“引用”。在复制变量或将列表作为函数调用的参数时,这一点很重要
# 因为被复制的只是列表引用,所以要注意,对该列表的所有改动都可能影响到程序中的其他变量。如果需要对一
# 个变量中的列表修改,同时不修改原来的列表,就可以使用copy()或deepcopy()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值