《趣学Python——教孩子学编程》学习笔记第9-10章

96
麦典威
2018.04.04 00:12 字数 2250

第9章 Python的内建函数

9.1 使用内建函数

9.1.1 abs函数
>>> print(abs(10))
10
>>> print(abs(-10))
10

对比使用abs函数与不使用的差别:

>>> steps = -3
>>> if steps<0 or steps>0:
    print('Character is moving')

    
Character is moving
>>> steps = -3
>>> if abs(steps)>0:
    print('Character is moving')

    
Character is moving
9.1.2 bool函数

对数字使用bool函数时,0返回False,其它任何值都返回True

>>> print(bool(0))
False
>>> print(bool(1))
True
>>> print(bool(-1))
True
>>> print(bool(123.12))
True
>>> 

对字符串使用bool函数时,None或者空字符串返回False,其它任何值返回True

>>> print(bool(None))
False
>>> print(bool(''))
False
>>> print(bool(' '))
True
>>> print(bool('a'))
True
>>> print(bool('How do you do?'))
True

对空的列表、元组、字典返回False,其它任何值都返回True

>>> my_list = []
>>> print(bool(my_list))
False
>>> my_list = ['s','i','l','l','y']
>>> print(bool(my_list))
True
>>> my_turple = ()
>>> print(bool(my_turple))
False
>>> my_turple = ('s','i','l','l','y')
>>> print(bool(my_turple))
True
>>> my_dict = {}
>>> print(bool(my_dict))
False
>>> my_dict = {'Tom':'pencil','Marry':'pen'}
>>> print(bool(my_dict))
True
>>> year = input('Year of birth:')
Year of birth:
>>> if not bool(year.rstrip()):
    print('You need to enter a value for your year of birth')

    
You need to enter a value for your year of birth

input()与sys.stdin.readline()效果一样;rstrip()函数把字符串结尾的空白和回车删除

9.1.3 dir函数

dir函数可以返回关于任何值得相关信息。

>>> dir(['a','short','list'])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

当你想要快速在一个变量上可以做些什么的时候,dir函数就很有用。

例如,对一个包含字符串值的叫popcorn的变量调用dir,你会得到一系列string类所提供的函数(所有的字符串都属于string类)

>>> popcorn = 'I love popcorn!'
>>> dir(popcorn)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

接下来,你可以用help得到列表中某个函数的简短描述。下面的例子是对upper函数调用help的结果:

>>> help(popcorn.upper)
Help on built-in function upper:

upper(...) method of builtins.str instance
    S.upper() -> str
    
    Return a copy of S converted to uppercase.

省略号(...)意味着upper是一个string类内建的函数并且没有参数。下面一行的箭头(->)的意思是这个函数返回一个字符串(str)。最后一行给出了这个函数简要的介绍

9.1.4 eval函数

eval函数把一个字符串作为参数并返回它作为一个Python表达式的结果。例如 eval('print("wow")')实际上会执行语句print("wow")

eval函数只能用于简单的表达式,拆分成多行的表达式(如if语句)一般不能运算。

>>> eval('''if True:
    print("this is a pen")''')
Traceback (most recent call last):
  File "<pyshell#155>", line 2, in <module>
    print("this is a pen")''')
  File "<string>", line 1
    if True:
     ^
SyntaxError: invalid syntax

eval函数常用于把用户输入转换成Python表达式,因为用户的输入会被当做字符串读进来,Python如果要进行计算的话需要把他转换成数字和运算符。

>>> your_calculation = input('Enter a calculation:')
Enter a calculation:12*52
>>> eval(your_calculation)
624
9.1.5 exec函数

exec函数和eval函数差不多,但它可以运行更复杂的程序。两者的不同在于eval返回一个值(你可以把它保存在变量中),而exec则不会。

>>> my_small_program = '''print('ham')

print('sandwich')'''
>>> exec(my_small_program)
ham
sandwich

这有什么用呢?你可以用exec来运行Python程序从文件中读入的小程序,也就是程序中又包含了程序!这在写很长、很复杂的程序时可能很有用。例如,你可以写一个机器人对站游戏,其中两个机器人在屏幕上移动并试图向对方进攻。游戏玩家要提供写成Python小程序的对机器人的指令。机器人对战游戏会读入这些脚本并用exec来运行。

9.1.6 float函数

float函数把字符串或数字转换成“浮点数”,也就是一个带有小数点的数字(也叫“实数”)。

>>> float('12')
12.0
>>> float(123)
123.0
>>> float('123.321')
123.321

可以用float把程序中的输入转换成恰当的数字,尤其是在你需要把某人的输入与其它值作比较的时候这很有用:

>>> your_age = input('Enter your age:')
Enter your age:20
>>> age = float(your_age)
>>> if age>13:
    print('You are %s years too old'%(age-13))

    
You are 7.0 years too old
9.1.7 int函数

int函数把字符串或者数字转换成整数,这样会把小数点后面的内容丢掉。

>>> int(123.321)
123
>>> int('123')
123

int函数无法把包含浮点数的字符串进行转换

>>> int('123.321')
Traceback (most recent call last):
  File "<pyshell#183>", line 1, in <module>
    int('123.321')
ValueError: invalid literal for int() with base 10: '123.321'
9.1.8 len函数
>>> len('this is a test string')
21
>>> print(len(creature_list))
5
>>> enemies_map = {'Batman':'Joker','Superman':'Lex Luthor','Spiderman':'Green Goblin'}
>>> print(len(enemies_map))
3

len函数在for循环中特别有用

>>> creature_list = ['unicorn','cyclops','fairy','elf','dragon']
>>> for x in range(0,len(creature_list)):
    print('the creature_list at index %s is %s' %(x,creature_list[x]))

    
the creature_list at index 0 is unicorn
the creature_list at index 1 is cyclops
the creature_list at index 2 is fairy
the creature_list at index 3 is elf
the creature_list at index 4 is dragon
9.1.9 max和min函数
>>> numbers = [5,3,2,9,8,7]
>>> print(max(numbers))
9
>>> strings = 's,t,r,i,n,g,S,T,R,I,N,G'
>>> print(max(strings))
t
>>> turple = (10,300,450,50,90)
>>> print(max(turple))
450

假设你与四个玩家一起玩猜数字游戏,他们每个人要猜想一个比你的数字小的数字,如果任何一个玩家猜的数字比你的大,那么所有的玩家就都输了,但是如果他们猜的都比你的小,那么他们赢。

>>> guess_this_number = 61
>>> player_gesses = [12,15,70,45]
>>> if max(player_gesses)<guess_this_number:
    print('You win')
else:
    print('Boom! You all lose')

    
Boom! You all lose
9.1.10 range函数
>>> for x in range(0,5):
    print(x)

    
0
1
2
3
4

>>> print(list(range(0,5)))
[0, 1, 2, 3, 4]
>>> print(list(range(0,5,2)))
[0, 2, 4]
>>> print(list(range(10,0,-2)))
[10, 8, 6, 4, 2]
9.1.11 sum函数
>>> numbers = [5,3,2,9,8,7]
>>> print(sum(numbers))
34
>>> numbers = list(range(0,500,50))
>>> print(sum(numbers))
2250

9.2 使用文件

9.2.1 创建测试文件

在D:\DataguruPyhton目录下新建文件funnyPythonTest.txt,并在此文件中输入 hello Python!

9.2.2 在Python中打开文件
>>> test_file = open('d:\\DataguruPyhton\\funnyPythonTest.txt')
>>> text = test_file.read()
>>> print(text)
hello Python!
9.2.3 写入到文件
>>> test_file = open('d:\\DataguruPyhton\\funnyPythonTest.txt','w')
>>> test_file.write('this is my test file')
20
>>> test_file.close()
>>> test_file = open('d:\\DataguruPyhton\\funnyPythonTest.txt')
>>> text = test_file.read()
>>> print(text)
this is my test file

第10章 常用的Python模块

10.1 使用copy模块来复制

复制对象

>>> class Animal:
    def __init__(self,species,number_of_legs,color):
        self.species = species
        self.number_of_legs = number_of_legs
        self.color = color

        
>>> harry = Animal('hippogriff',6,'pink')
>>> import copy
>>> harriet = copy.copy(harry)
>>> print(harry.species)
hippogriff
>>> print(harriet.species)
hippogriff

复制列表

>>> harry = Animal('hippogriff',6,'pink')
>>> carrie = Animal('chimera',4,'green polka dots')
>>> billy = Animal('bogill',0,'paisley')
>>> my_animals = [harry, carrie, billy]
>>> more_animals = copy.copy(my_animals)
>>> print(more_animals[0].species)
hippogriff
>>> print(more_animals[1].species)
chimera

如果我们改变my_animals列表中的一个元素,more_animals列表中的元素也会改变

>>> my_animals[0].species = 'ghoul'
>>> print(my_animals[0].species)
ghoul
>>> print(more_animals[0].species)
ghoul

为什么会这样?因为copy实际上只做了“浅拷贝”,也就是说他不会拷贝我们要拷贝的对象中的对象。在这里,它拷贝了主对象list对象,但是并没有拷贝其中的每个对象。因此我们得到的是一个新列表,但其中的对象并不是新的。

同样用这些变量,如果我们给第一个列表my_animals添加一个新的对象,它不会出现在拷贝more_animals中。

>>> sally = Animal('sphinx',4,'sand')
>>> my_animals.append(sally)
>>> print(len(my_animals))
4
>>> print(len(more_animals))
3

copy模块中的另一个函数deepcopy,会创建被拷贝对象中的所有对象的拷贝,对于原来列表中对象的改动不会影响到新的列表。

>>> more_animals = copy.deepcopy(my_animals)
>>> my_animals[0].species = 'wyrm'
>>> print(my_animals[0].species)
wyrm
>>> print(more_animals[0].species)
ghoul

10.2 keyword模块记录了所有的关键字

Python自身所用到的那些单词被称为“关键字(keyword)”,比如if、else、for

>>> import keyword
>>> print(keyword.iskeyword('if'))
True
>>> print(keyword.iskeyword('abc'))
False
>>> print(keyword.kwlist)
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

10.3 用random模块获得随机数

10.3.1 用randint来随机挑选一个数字

randint函数是从一个指定的范围里随机选取一个整数

>>> import random
>>> print(random.randint(1,100))
77
>>> print(random.randint(100,1000))
128
>>> print(random.randint(1000,5000))
1632

哈哈,无聊的猜数字游戏

>>> import random
>>> num = random.randint(1,100)
>>> while True:
    print('Guess a number 1 and 100')
    guess = input()
    i = int(guess)
    if i == num:
        print('You guessed right')
        break
    elif i < num:
        print('Try higher')
    elif i > num:
        print('Try lower')

        
Guess a number 1 and 100
50
Try higher
Guess a number 1 and 100
75
Try lower
Guess a number 1 and 100
62
Try higher
Guess a number 1 and 100
69
You guessed right
10.3.2 用choice从列表中随机选取一个元素

choice函数是从一个列表中随机选取一个元素

>>> import random
>>> desserts = ['ice cream','pancake','brownies','cookies','candy']
>>> print(random.choice(desserts))
brownies
10.3.3 用shuffle来给列表洗牌

shuffle函数用来给列表洗牌,把元素打乱

>>> import random
>>> desserts = ['ice cream','pancake','brownies','cookies','candy']
>>> random.shuffle(desserts)
>>> print(desserts)
['ice cream', 'cookies', 'candy', 'brownies', 'pancake']

10.4 用sys模块来控制Shell程序

10.4.1 用exit函数来退出Shell程序

可以用exit函数来停止Python Shell程序或者控制台

>>> import sys
>>> sys.exit()
10.4.2 从stdin对象读取

stdin是“标准输入(standard input)”的缩写,功能和input函数很像。

>>> import sys
>>> v = sys.stdin.readline()
he Who laughs last thinks slowest
>>> print(v)
he Who laughs last thinks slowest

input和readline函数的区别之一是readline可以用一个参数来指定读取多少个字符。

>>> import sys
>>> v = sys.stdin.readline(13)
he Who laughs last thinks slowest
>>> print(v)
he Who laughs
10.4.3 用stdout对象来写入

stdout是“标准输入(standard output)”的缩写,在某些方面它与print相同,但是stdout是一个文件对象。

>>> import sys
>>> sys.stdout.write('What does a fish say when it swims into wall? Dam')
What does a fish say when it swims into wall? Dam49

当write结束时,它返回它所写入的字符的个数,我们可以把这个值保存到变量中作为记录,来看看我们总共在屏幕上打印出多少个字符

10.4.4 我用的Python是什么版本的
>>> import sys
>>> print(sys.version)
3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)]

10.5 用time模块来得到时间

>>> import time
>>> print(time.time())
1522552434.9343157

time()返回的数字实际上是自1970年1月1日00:00:00 AM 以来的秒数。单独看起来这种罕见的表现形式没法直接使用,但它有它的目的,比如想要计算你的程序的某一部分运行多久,你可以在开始和结束时记录时间,然后比较两个值。

>>> import time
>>> def lots_of_numbers(max):
    for x in range(0,max):
        print(x)

        
>>> lots_of_numbers(1000)
0
1
2
3
4
.
.
.
996
997
998
999
it took 4.131357431411743 second
10.5.1 用asctime来转换日期
>>> import time
>>> print(time.asctime())
Sun Apr  1 11:22:15 2018

asctime可以带参数,但首先要创建一个包含日期和时间数据的元组

>>> import time
>>> t = (2020,2,23,10,30,48,6,0,0)
>>> print(time.asctime(t))
Sun Feb 23 10:30:48 2020

t = (2020,2,23,10,30,48,6,0,0) 这一系列值分别是:年、月、日、时、分、秒、星期几(0代表星期一,1代表星期二,以此类推)、一年中的第几天(这里0作为一个占位符)
、是否夏令时(0不是,1是)

10.5.2 用localtime来得到日期和时间

与asctime不同,函数localtime把当前的日期和时间作为一个对象返回,其中的值大体与asctime的参数顺序一样。如果你要打印这个对象,就能看到类的名字,还有其中的每个值,这些值被标记为tm_year(年)、tm_mon(月)、tm_mday(日)、tm_hour(时)、tm_min(分)、tm_sec(秒)、tm_wday(星期几)、tm_yday(一年中的第几天)、tm_isdst(是不是夏令时)。

>>> import time
>>> print(time.localtime())
time.struct_time(tm_year=2018, tm_mon=4, tm_mday=1, tm_hour=14, tm_min=12, tm_sec=47, tm_wday=6, tm_yday=91, tm_isdst=0)

如果要打印当前的年和月,可以用索引来获取。

>>> import time
>>> t = time.localtime()
>>> year = t[0]
>>> month = t[1]
>>> print(year)
2018
>>> print(month)
4
10.5.3 用sleep来休息一会吧
>>> import time
>>> for x in range(1,5):
    print(x)
    time.sleep(1)

    
1
2
3
4

10.6 用pickle模块来保存信息

pickle模块用来把Python对象转换成可以方便写入到文件和从文件读取的形式。如果你在写一个游戏并且想保存玩家的进度信息的话,可能就会用得上pickle。

>>> import pickle
>>> game_data = {
    'player-position':'N23 E45',
    'pockets':['keys','pocket knife','polished stone'],
    'backpack':['rope','hammer','apple'],
    'money':158.50
    }
>>> save_file = open('D:\\DataguruPyhton\\save.dat','wb')
>>> pickle.dump(game_data,save_file)
>>> save_file.close()

此时打开 save.dat 文件,会看到一堆乱码。纯文本文件中只可以包含人们可读的字符,图像、音乐、电影、序列化(被pickle过)的Python对象中的信息并不总是对人们可读的,所以它们被称为二进制文件。

image

这些“乱码”怎么读取呢?我们可以用pickle的load函数来把写入的文件反序列化。

>>> load_file = open('D:\\DataguruPyhton\\save.dat','rb')
>>> loaded_game_data = pickle.load(load_file)
>>> load_file.close()
>>> print(loaded_game_data)
{'player-position': 'N23 E45', 'pockets': ['keys', 'pocket knife', 'polished stone'], 'backpack': ['rope', 'hammer', 'apple'], 'money': 158.5}