Think Python读书笔记及课后习题---【前三章】

昨天明明可以靠脸吃饭却偏偏要靠实力吃饭的班主任给我推荐了 T h i n P y t h o n 《ThinPython》 这本书,于是乎我便开始了我的啃书之路。这本书最大的优点,比如给出一个知识点,他就让你思考如果不按这样来会怎么样,故意试错,这是学习编程语言必须有的一种思想,当初我可能就是喜欢去故意试错,所以以前对C语言的理解才会比同学稍微深刻一点吧(因为平常应用中我们更多的是把代码规范化,该括号的打上括弧,所以像什么优先级之类的只记得常用的了,该忘的还是会忘,但是现在能理解深刻到时候要回头看也很轻松),昨天刚看这本书的时候真的难受,可能是翻译的缘故,第一章讲概念的时候翻译得真的难受,比如bug翻译成故障(不更多说是漏洞嘛),但是好在一些术语会在边上注释英文,这也是我喜欢这本书的原因还之一;还有就是有一部分知识点都没有(不知道后面有没有出现),比如print("%d"%variable),这里的占位符这一块知识点就没讲到,还有取整符//和取余%也没讲到,但是出于班主任的膜拜和对他的信任,我看到了第三章,发现此书还是极好的,推荐此书 T h i n P y t h o n 《ThinPython》 (如果看到后面觉得这本书一般般我自然会删了这句话),接下来我就要开始啃书啦,我是在Linux下开发的,图形界面推荐PyCharm,书中推荐先用网页版解释器也是入门时挺不错的选择

下面摘选第二章的一个习题

Exercise2.1.和上一章一样,我还是要建议大家在学习新特性之后,在交互模式下充分 试验,故意犯一些错误,看看到底会出什么问题。
• 我们已经知道n = 42 是合法的。那么42 = n 呢?
• x = y = 1 合法吗?
• 在某些编程语言中,每个语句都是以分号; 结束的。如果你在一个Python语句后 也以分号结尾,会发生什么?
• 在数学记法中,你可以将 x 和 y 像这样相乘:xy 。如果你在 Python 中也这么写 的话,会发生什么

第一、二章

这是昨天看的,笔记写在Onenote里,复制几个吧,就不整理思路了

  1. 如果我上午 6:52 离开家,以轻松跑 (easy pace)的速度跑 1 里(即每英里耗时 8 分 15 秒),再以节奏跑 (tempo) 的速度跑 3 英里(每英里耗时 7 分 12 秒),之后 又以放松跑的速度跑 1 英里,我什么时候回到家吃早饭?
# 先以小时为单位,转换成十进制计算,很容易算出十进制的到家时间
• time_decimal = (6+52/60) + (easy_pace + easy2_pace)*(8+15/60)/60 + tempo*(7+12/60)/60
# 将小时为单位的十进制数转换成60进制,要取整算当前,取余算下个单位
• print("%02d:%02d:%02d" % (time_decimal//1, time_decimal%1*60//1, time_decimal%1*60%1*60))
  1. 取整函数区别于数学与C语言
In [3]: int(-3.2)
Out[3]: -3

In [12]: int(-3.999999999999999)
Out[12]: -3

In [13]: int(-3.9999999999999999)
Out[13]: -4

In [14]: int( 3.9999999999999999)
Out[14]: 4
  • Python区别于数学概念上的取整,python只是取整数部分,而不是数学概念的取不大于本值的最大整数
  • 另外,有个精度问题,超过15位小数(16个小数9)被看成整数1了
  1. (x+1)++不是合法的。
    这个涉及到左值的概念。x+1的值是一个临时变量,不是左值,是不可以使用后自增运算的。
    同理(x++)++也不合法。(++x)++是合法的。因为前自增返回左值,后自增返回的是一个临时变量,只能作为右值。
    就像您不能使用x+1=2这样的表达式一样。

  2. 除单行多语句以外,分号可加可不加,单号多语句必须加,
    a. x=1; y=1 ; z=1
    b. 除此之外官方不推荐使用分号

第三章

3.4

针对本节中出现的这句话应该避免变量和函数同名做出以下尝试,

def printf():
	print("Hello World")
print(printf)
printf()
printf = 2
print(printf)

输出结果如下

<function printf at 0x7f659388a5f0>
Hello World
2

从面结果来看,可以得出以下几点:

  • print的实参为函数时,输出为该函数分配的地址
  • 自定义的printf函数可以被强制修改类型,同样的python自带的函数(叫内建函数)如type()也可以被这样的赋值强制改变数据类型。上例中的printf被改成了int型,所以printf()也就不存在了,如果在此之后还使用printf就会出错,尝试过程如下
lenovo@ubuntu:~/Desktop$ cat 3_3.py 
#!/usr/bin/env python3
def printf():
	print("Hello World")
print(printf)
printf()
printf = 2
printf()
print(printf)

lenovo@ubuntu:~/Desktop$ python3 3_3.py 
<function printf at 0x7f0c718de2f0>
Hello World
Traceback (most recent call last):
  File "3_3.py", line 7, in <module>
    printf()
TypeError: 'int' object is not callable
  • 从执行结果来看再一次说明python解释型语言,所以可以正常执行前面几条语句,正常执行了prinf = 2之前的所有语句,这里出现的错误类型在 T h i n P y t h o n 《ThinPython》 有提到,叫做运行时错误(runtime error) 。By the way,书上提到的另外两种错误类型叫做语法错误和语义错误。

3.4

  1. print("My name is ‘AI_Fanatic’ ")
    正确,输出My name is ‘AI_Fanatic’ 双引号和单引号都可以表示字符串,使用上基本没什么差别,但是像这种字符串内部需要嵌套字符串的,可以双引号中嵌套单引号,或者用\'或者\"来表示字符串内部的单引号或者双引号
  2. 列表内容

3.5

  • 假设有一个函数A,我们可以在外部执行它(不在任何函数里,懂C语言的或者可以理解成全局与局部的区别),但是执行语句必须在函数A的定义之后,否则会报错;
  • 但是假设函数A内部调用了函数B,函数B的定义可以在函数A的前面后面都可以,原因其实就是3.6提到的函数定义只是创建函数对象,而并不会执行函数体内部。但是有一个要求就是在函数体外执行函数A之前(我也不知道Python中怎么称呼它,姑且先叫函数体外或者全局吧),必须已经定义了函数B,或者说我在用函数A时必须前面用到的所有函数都已经定义了,原因是Python是一门解释型语言,从上往下执行。

3.6

函数定义只会创建一个函数对象,并不会执行函数体内部的语句。
如果函数不被调用的话,函数内部的语句是不会执行的。

阅读程序时,你没有必要总是从上往下读。有时候,跟着执行流程阅读反而更加合理。

Exercise 3.2.2

Exercise 3.2.2

def print_spam(linus):
    print('spam')
    print(linus)


def do_twice(f, value):
    f(value)
    f(value)


do_twice(print_spam, input("Please Input a value:"))

输出结果如下

Please Input a value:hello
spam
hello
spam
hello

Process finished with exit code 0

不要问我为啥空这么多行,你得问PEP 8,这是官方的一个规范,函数定义后面空两行,其实我对自己的代码规范是空一行,而且我个人习惯变量名首字母大写,这些对于Python来说都是不符合规范的,但是没办法,国有国法,家有家规,咱得按官方的规矩来,但其实看起来也还算挺舒服的咧

关于代码规范
• Python官方提供有一系列PEP(Python Enhancement Proposals)文档
• 其中第8篇文档专门针对Python的代码格式 给出了建议,也就是俗称的 PEP 8
• 文档地址:https://www.python.org/dev/peps/pep-0008/
• 谷歌有对应的中文文档:http://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules/
任何语言的程序员,编写出符合规范的代码,是开始程序生涯的第一步

之前在代码编写过程中不小心在do_twice前多打了一个空格,error提示如下:

File “/home/lenovo/Desktop/printpy/3.2.py”, line 11
   do_twice(print_spam, input(“Please Input a value”))
                                                                                 ^
IndentationError: unindent does not match any outer indentation level

Process finished with exit code 1

Exercise 3.2

def print_twice(bruce):
    print(bruce)
    print(bruce)


# PEP 8
def do_twice(f, value):
    f(value)
    f(value)


def do_four(g, four_value):
    do_twice(g, four_value)
    do_twice(g, four_value)


do_four(print_twice, 'spam')

Exercise 3.3

我写的程序可以输出任意行任意列的网格,改边长需要改的地方我也注释清楚了,不过现在还没学循环,所以还不能用for实现真正的输出任意行列,不过我考虑到了这一部分,可扩展性还是过得去的,全写在程序里了,学过for之后两花分钟就能加上去
Exercise 3.3

"""
对我来说最难的不是程序,而是命名,真的烦
很多单词我认识但是写不出也想不到,如果有学弟学妹看到了,一定要学好英语!!!
现在很晚了,这道题我已经想到怎么做了,但是很难想命名
所以我选择以数字递增命名,早点写完早点睡觉,我会备注是打印那一部分的.
"""


# '+ - - - -',最小输出单元
# 不会随行列数而变化的,改变边长时改变字符串'- '拼接次数
# end前面的逗号不会自动转换成空格输出
# 其他逗号会自动转换成空格输出
def one_print():
    print('+', '- ' * 4, end='')


# '|        ',最小输出单元
# 不会随行列数而变化的,改变边长时改变空格拼接次数
def two_print():
    print('|', ' '*8, end='')


# 输出类似第一行的一整行+---+----+
# 改变列数需要改变内部函数重复次数,重复columns次
def edge_one_print():
    one_print()
    one_print()
    print("+")


# 输出类似第二行的一整行|    |    |
# 改变列数需要改变内部函数重复次数,重复columns次
def edge_two_print():
    two_print()
    two_print()
    print("|")


# 完成grid画图
# 改变行数需要改变内部函数重复次数,重复rows次
def print_grid():
    part_print()
    part_print()
    edge_one_print()


# 输出像倒着的“山”字的那一部分,2X2中为上半部分
# 不会随着行列数变化的,改变边长时改变内部函数重复次数
def part_print():
    edge_one_print()
    edge_two_print()
    edge_two_print()
    edge_two_print()
    edge_two_print()


# rows = int(input("How many rows do you want to print:"))
# columns = int(input("How many columns do you want to print:"))
print_grid()

这里是输出2X2,想要多少行数只需改print_grid()中的part_print重复次数就行;想要多少列数需要改edge_one_print()和edge_two_print()中的one_print()和two_print()重复次数就行

猜你喜欢

转载自blog.csdn.net/AI_Fanatic/article/details/82530266