一、概述
1、含义
Python是一个面向对象的解释型的交互式高级脚本语言。Python被设计成一种高可读性的语言,因为它大量地使用了英语中的单词作为关键字,而且不像其他语言使用标点符号构成复杂的语法结构,Python的语法结构非常少。
Python是一种带有对象、模块、线程、异常和内存自动管理的编程语言。
2、优缺点
(1)优点
在于它简单易用,可移植,可扩展,内置数据结构,并且它是一个开源的
- 解释性
- 动态特性
- 面向对象
- 语法简洁
- 可移植性好
- 开源
- 丰富的社区资源
(2)缺点
- 执行速度不够快,代码效率低
- GIL锁限制并发
- Python2与Python3不兼容
3、Django和flask的区别
(1)Django
- 大而全,功能极其强大,是Python web框架的先驱,用户多,第三方库极其丰富。
- 非常适合企业级网站的开发,但是对于小型的微服务来说,总有“杀鸡焉有宰牛刀”的感觉,体量较大,非常臃肿,定制化程度没有Flask高,也没有Flask那么灵活
(2)flask
- 小巧、灵活,让程序员自己决定定制哪些功能,非常适用于小型网站。
- 对于普通的工人来说将毛坯房装修为城市综合体还是很麻烦的,使用Flask来开发大型网站也一样,开发的难度较大,代码架构需要自己设计,开发成本取决于开发者的能力和经验
4、PEP 8
PEP 8是一个编码约定,一组推荐,关于如何编写Python代码更具可读性
5、标识符
标识符不建议使用下划线开头:因为在 Python 中以下划线开头的变量为私有变量
标识符就是一个名字,它的主要作用就是作为变量、函数、类、模块以及其他对象的名称。Python 标识符的命名不是乱来的,而是要遵守一定的命令规则:
-
标识符是由字母(A--Z 和 a--z)、下划线和数字组成。如果标识符中出现除了这 3 类字符之外的其他字符,就肯定是不合法标识符。
-
标识符的第一个字符不能是数字。
-
标识符不能和 Python 关键字相同。
-
标识符中的字母是严格区分大小写的。
-
以下划线开头的标识符有特殊含义,除非特定场景需要,应避免使用以下划线开头的标识符。
-
标识符可以是汉字。但我们应尽量避免使用汉字作为标识符,这会避免遇到很多没必要的错误。
二、关键字和函数
1、深拷贝和浅拷贝的区别
- 浅拷贝:copy模块里面的copy方法实现。浅拷贝后,改变原始对象中为可变类型的元素的值,会同时影响拷贝对象;改变原始对象中为不可变类型的元素的值,不会响拷贝对象。浅拷贝是将对象的引用复制给另一个对象。因此,如果我们在副本中进行更改,则会影响原对象
- 深拷贝:copy模块里面的deepcopy方法实现。深拷贝,除了顶层拷贝,还对子元素也进行了拷贝。经过深拷贝后,原始对象和拷贝对象所有的可变元素地址都没有相同的了。深拷贝是将对象本身复制给另一个对象。这意味着如果对对象的副本进行更改时不会影响原对象。
2、迭代器和生成器的区别
- 迭代器:是一个可以记住遍历的位置的对象,包含iter()和 next(),
>>> list=[1,2,3,4]
>>> it = iter(list) # 创建迭代器对象
>>> print (next(it)) # 输出迭代器的下一个元素
1
>>> print (next(it))
2
2. 生成器:使用了 yield 的函数被称为生成器,在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
import sys
def fibonacci(n): # 生成器函数 - 斐波那契
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
输出:0 1 1 2 3 5 8 13 21 34 55
3、字典、列表、元组、集合的区别
(1)字典
字典存储键值对数据
lists = {1:'a',2:'b',3:'c'}
#字典最外面用大括号,每一组用冒号连起来,然后各组用逗号隔开。
#字典最大的价值是查询,通过键,查找值。
(2)列表
特点就是:可重复,类型可不同。python里的列表用“[]”表示
lst = ['arwen',123]
print(lst[0])
print(st[1])
lst[0] = 'weiwen'
(3)元组
元组和列表在结构上没有什么区别,唯一的差异在于元组是只读的,不能修改。元组用“()”表示
tup = ('arwen',123)
print(tup[0])
print(tup[1])
(4)集合
集合最好的应用是去重。集合没有特殊的表示方法,而是通过一个set函数转换成集合
lst = [ 1, 1, 0]
lst_set = set( lst ) #lst_set 为1 , 0
tup = (2, 2, 1)
tup_set = set( tup) # tup_set为2 , 1
for item in lst_set:
print(item)
4、列表和数组的区别
列表中元素是可以不同类型的,数组中为同一类型
5、lambda和filter
(1)lambda
Python使用lambda来创建匿名函数。
- lambda只是一个表达式,函数体比def简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
func=lambda x:x+2
print(func(1))
print(func(2))
#以上lambda等同于以下函数
def func(x):
return(x+2)
(2)filter
filter(函数,序列)函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
def is_odd(n):
return n%2==1
newlist = filter(is_odd,[1,2,3,4,5,6,7,8,9,10])
print(newlist)
Python3.6结果:<filter object at 0x00000184ED881358>
上面lambda和filter合在一起:
newlist = list(filter(lambda n:n%2==1,[1,2,3,4,5,6,7,8,9,10]))
print(newlist)
结果:[1, 3, 5, 7, 9]
6、装饰器
装饰器是修改其他函数的功能的函数,有助于使得代码更简短。
Python 内置的 3 种函数装饰器,分别是 @staticmethod、@classmethod 和 @property,其中 staticmethod()、classmethod() 和 property() 都是 Python 的内置函数。
#funA 作为装饰器函数
def funA(fn):
print("C语言中文网")
fn() # 执行传入的fn参数
print("http://c.biancheng.net")
return "装饰器函数的返回值"
@funA
def funB():
print("学习 Python")
等价于:
def funA(fn):
#...
fn() # 执行传入的fn参数
#...
return '...'
def funB():
#...
funB = funA(funB)
#输出结果:
C语言中文网
学习 Python
http://c.biancheng.net
通过比对以上 2 段程序不难发现,使用函数装饰器 A() 去装饰另一个函数 B(),其底层执行了如下 2 步操作:
- 将 B 作为参数传给 A() 函数;
- 将 A() 函数执行完成的返回值反馈回 B
7、局部变量和全局变量
局部变量:如果在函数体内的任何位置为变量分配了一个新值,则假定它是本地的
全局变量:仅在函数内引用的那些变量是隐式全局变量
变量调用的顺序是先找局部作用域,如果找不到,再往外层找,然后在找全局作用域
name="gouguoqi"
def change_name():
global name
name="miaoye"
print ("111",(name))
change_name()
print(name)
结果:
111 miaoye
miaoye
global name,就代表调用全局的变量name。专业的说法是global 后面的name是一个指针,一个内存地址,直接调用的那个内存地址,调用之后在子程序(局部程序)里面再次给name赋值的话就修改了全局变量name了
8、pass
pass是Python中的空操作语句,或者说,它是一个复杂语句中的一个空间占位符,只是用来表示空白,什么都不用写
9、*args和**kwargs
如果我们不知道将多少个参数传递给函数,比如当我们想传递一个列表或一个元组值时,就可以使用*args。
当我们不知道将会传入多少关键字参数时,使用**kwargs 会收集关键字参数。
使用 args 和 kwargs 作为参数名只是举例,可以任意替换
类似的 break 语句可以跳出循环,continue 语句可以跳到下一轮循环
三、内存管理
1、管理方式
Python内存由Python私有堆空间管理。所有Python对象和数据结构都位于私有堆中。程序员无权访问此私有堆,解释器负责处理此私有堆。
Python对象的Python堆空间分配由Python内存管理器完成。核心API提供了一些程序员编写代码的工具。
Python还有一个内置的垃圾收集器,它可以回收所有未使用的内存并释放内存并使其可用于堆空间。
Python不需要显式内存管理,因为解释器本身会将内存分配给新变量并自动释放它们
2、释放
当退出 Python 时是否释放所有内存分配,答案是否定的。那些具有对象循环引用或者全局命名空间引用的变量,在 Python 退出是往往不会被释放,另外不会释放 C 库保留的部分内容
四、多线程
1、如何实现
线程是轻量级的进程,多线程允许一次执行多个线程。众所周知,Python 是一种多线程语言,它有一个多线程包。
GIL(全局解释器锁)确保一次执行单个线程。一个线程保存 GIL 并在将其传递给下一个线程之前执行一些操作,这就产生了并行执行的错觉。但实际上,只是线程轮流在 CPU 上。当然,所有传递都会增加执行的开销。
2、多线程优点
多线程类似于同时执行多个不同程序,其优点:
- 使用线程可以把占据长时间的程序中的任务放到后台去处理。
- 用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。
- 程序的运行速度可能加快。
- 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等
五、运算
1、解释 Python 中的//,/,%和**运算符
- //运算符执行地板除法,7//2返回结果的整数部分 (向下取整),为3
- 用/符号除法结果为 3.5
- **符号表示取幂. a**b 返回 a 的 b 次方
- % 是取模符号。返回除法后的余数
2、Python有几种运算符
在 Python 中有7中运算符:算术运算符、关系 (比较) 运算符、赋值运算符、逻辑运算符、位运算符、成员运算符、身份运算符。
(1)算术运算符
算术运算符包括+、-、*、/、//(地板除法)、%(取模)、**(取幂)
(2)关系运算符
关系运算符用来比较两个对象,包括<、>、<=、>=、==、!=
(3)赋值运算符
一般将算数运算符和赋值符号用在一起,包括+=、-=、*=、/=、**=、//=、%=
(4)逻辑运算符
Python中有三个逻辑运算符:and、or、not
(5)位运算符
位运算符按二进制位对值进行操作。
- 与 (&) 返回按位与结果。A与B值均为1时,A、B与的运算结果才为1,否则为0
- 或 (|) 返回按位或结果。A或B值为1时,A、B或的运算结果才为1,否则为0
- 异或 (^) 返回按位异或结果。A与B不同为1时,A、B的预算结果才为1,否则为0
- 取反 (~) 返回按位取反结果
- 左移位 (<<) 将符号左边数的二进制左移右边数位
- 右移位 (>>)与左移位方式相同,但方向相反
(6)成员运算符
使用 in 和 not in 运算符我们可以判断某个值是否在成员中
(7)身份运算符
is 和 is not 运算符可以判断两个对象是否相同