Day1
1、Python的优缺点
Python的优点很多,简单的可以总结为以下几点。
- 简单和明确,做一件事只有一种方法。
- 学习曲线低,跟其他很多语言相比,Python更容易上手。
- 开放源代码,拥有强大的社区和生态圈。
- 解释型语言,天生具有平台可移植性。
- 支持两种主流的编程范式(面向对象编程和函数式编程)都提供了支持。
- 可扩展性和可嵌入性,可以调用C/C++代码,也可以在C/C++中调用Python。
- 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。
Python的缺点主要集中在以下几点。
- 执行效率稍低,因此计算密集型任务可以由C/C++编写。
- 代码无法加密,但是现在很多公司都不销售卖软件而是销售服务,这个问题会被淡化。
- 在开发时可以选择的框架太多(如Web框架就有100多个),有选择的地方就有错误。
解释型语言:
使用专门的解释器对源程序逐行解释成特定平台的机器码并立即执行。
特点
解释型语言不需要事先编译,其直接将源代码解释成机器码并立即执行,所以只要某一平台提供了相应的解释器即可运行该程序。
总结
解释型语言每次运行都需要将源代码解释称机器码并执行,效率较低;
只要平台提供相应的解释器,就可以运行源代码,所以可以方便源程序移植;
Python等属于解释型语言。
编译型语言:
使用专门的编译器,针对特定的平台,将高级语言源代码一次性的编译成可被该平台硬件执行的机器码,并包装成该平台所能识别的可执行性程序的格式。
特点
在编译型语言写的程序执行之前,需要一个专门的编译过程,把源代码编译成机器语言的文件,如exe格式的文件,以后要再运行时,直接使用编译结果即可,如直接运行exe文件。因为只需编译一次,以后运行时不需要编译,所以编译型语言执行效率高。
总结
一次性的编译成平台相关的机器语言文件,运行时脱离开发环境,运行效率高;
与特定平台相关,一般无法移植到其他平台;
现有的C、C++、Objective等都属于编译型语言。
Day2
运算符
Python支持多种运算符,下表大致按照优先级从高到低的顺序列出了所有的运算符,我们会陆续使用到它们。
运算符 | 描述 |
---|---|
[] [:] | 下标,切片 |
** | 指数 |
~ + - | 按位取反, 正负号 |
* / % // | 乘,除,模,整除 |
+ - | 加,减 |
>> << | 右移,左移 |
& | 按位与 |
^ | | 按位异或,按位或 |
<= < > >= | 小于等于,小于,大于,大于等于 |
== != | 等于,不等于 |
is is not | 身份运算符 |
in not in | 成员运算符 |
not or and | 逻辑运算符 |
= += -= *= /= %= //= **= &= ` | = ^= >>= <<=` |
Day4
range
可以用来产生一个不变的数值序列,而且这个序列通常都是用在循环中的,例如:
range(101)
可以产生一个0到100的整数序列。range(1, 100)
可以产生一个1到99的整数序列。range(1, 100, 2)
可以产生一个1到99的奇数序列,其中的2是步长,即数值序列的增量。- range(10,0,-1)意思是从列表的下标为10的元素开始,倒序取到下标为0的元素
-
for _ in range(i + 1):下划线表示 临时变量, 仅用一次,后面无需再用到
Day6
函数的参数
函数是绝大多数编程语言中都支持的一个代码的“构建块”,但是Python中的函数与其他语言中的函数还是有很多不太相同的地方,其中一个显著的区别就是Python对函数参数的处理。在Python中,函数的参数可以有默认值,也支持使用可变参数,所以Python并不需要像其他语言一样支持函数的重载,因为我们在定义一个函数的时候可以让它有多种不同的使用方式,下面是两个小例子。
from random import randint def roll_dice(n=2): """ 摇色子 :param n: 色子的个数 :return: n颗色子点数之和 """ total = 0 for _ in range(n): total += randint(1, 6) return total def add(a=0, b=0, c=0): return a + b + c # 如果没有指定参数那么使用默认值摇两颗色子 print(roll_dice()) # 摇三颗色子 print(roll_dice(3)) print(add()) print(add(1)) print(add(1, 2)) print(add(1, 2, 3)) # 传递参数时可以不按照设定的顺序进行传递 print(add(c=50, a=100, b=200))
我们给上面两个函数的参数都设定了默认值,这也就意味着如果在调用函数的时候如果没有传入对应参数的值时将使用该参数的默认值,所以在上面的代码中我们可以用各种不同的方式去调用add
函数,这跟其他很多语言中函数重载的效果是一致的。
其实上面的add
函数还有更好的实现方案,因为我们可能会对0个或多个参数进行加法运算,而具体有多少个参数是由调用者来决定,我们作为函数的设计者对这一点是一无所知的,因此在不确定参数个数的时候,我们可以使用可变参数,代码如下所示。
# 在参数名前面的*表示args是一个可变参数 # 即在调用add函数时可以传入0个或多个参数 def add(*args): total = 0 for val in args: total += val return total print(add()) print(add(1)) print(add(1, 2)) print(add(1, 2, 3)) print(add(1, 3, 5, 7, 9))
事实上,Python查找一个变量时会按照“局部作用域”、“嵌套作用域”、“全局作用域”和“内置作用域”的顺序进行搜索,前三者我们在上面的代码中已经看到了,所谓的“内置作用域”就是Python内置的那些隐含标识符min
、len
等都属于内置作用域)。
def foo(): global a a = 200 print(a) # 200 if __name__ == '__main__': a = 100 foo() print(a) # 200
我们可以使用global
关键字来指示foo
函数中的变量a
来自于全局作用域,如果全局作用域中没有a
,那么下面一行的代码就会定义变量a
并将其置于全局作用域。同理,如果我们希望函数内部的函数能够修改嵌套作用域中的变量,可以使用nonlocal
关键字来指示变量来自于嵌套作用域,请大家自行试验。
在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用,除此之外全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被垃圾回收。事实上,减少对全局变量的使用,也是降低代码之间耦合度的一个重要举措,同时也是对迪米特法则的践行。减少全局变量的使用就意味着我们应该尽量让变量的作用域在函数的内部,但是如果我们希望将一个局部变量的生命周期延长,使其在函数调用结束后依然可以访问,这时候就需要使用闭包。