高级语言,不需要如何考虑如何管理你的程序使用的内存一类的底层细节等;
可移植性,由于python开源的特性,它已经被移植到许多平台上;
面向对象的,python不仅支持面向过程的编程,也支持面向对象的编程;
可扩展性,python编辑的程序可以直接调用用部分c或者c++开发的程序;
可嵌入性,可以把python嵌入c/c++程序,从而向程序用户提供脚本功能;
丰富的库:python庞大的标准库可以帮助我们处理各种工作,几乎无所不能;
规范的代码:python不需要编译成二进制代码的强制缩进方式,使得代码具有较好的可读性。
总结:语言本身简洁,功能强大,跨平台性强,从桌面应用到web开发,再到自动化运维、爬虫、人工智能、大数据都可以做。
C语言由于其底层操作特性和历史的积累,在嵌入式领域是当之无愧的。php跨平台,性能优越,和linux结合比和windows结合性能强45%。开发成本低,php5已经有了成熟的面向对象特性,适合开发大型项目。java是简单的、面向对象的语言。具有健壮、跨平台、高性能(自动垃圾回收机制)、多线程、动态和安全等特性。
编译性语言:编译型语言在执行前需要经过编译器的编译处理,将程序翻译成机器语言。因为在执行前编译型语言就已经被翻译成机器语言,所以在执行的时候会很快。例如C和C++是编译型语言。
解释型语言:解释型语言是在运行的时候将程序翻译成机器语言,所以运行速度相对于编译型语言要慢一些。例如:Python、Java、C#、JavaScript是解释型语言。
CPython解释器:由C语言开发,所以叫CPython,在命令行的下面运行python,启动的就是CPython解释器,CPython是使用最广的python解释器。
Jython:运行在java平台上的python解释器,直接把python代码编译成java字节码执行。
IPython:IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互上有所增强,但是执行代码的功能和CPython是完全一样的。
位是计算机存储信息的最小单位,二进制中一个0或1是一位。计算机存储容量最的单位是字节,8个二进制位组成一个字节,一个标准的英文字母占用一个字节,一个标准的汉字占用两个字节。
8b = 1B
1024B = 1KB
1024KB = 1MB
1024MB = 1GB
1. 4个空格的缩进,不使用Tab,更不能混合使用Tab和空格。
3. 类中的方法定义之间空一行
4. 在一段代码前增加的注释,在'#'后加一空格
5. 逗号,冒号前不加空格
6. 函数的左括号前不要加空格
7. 序列的左括号前不要加空格
8. 操作符左右各加一个空格
9. 函数默认参数使用的赋值符号左右省略空格
10.不要将多个语句写在同一行,允许使用分号
11. if、for、while语句中即使执行语句只有一句,也必须另起一行
12. 类的方法第一个参数必须是self,而静态方法第一个参数必须是cls
1. 二进制转换成十进制:v = "0b1111011"
In [1]: v = '0b1111011'
In [2]: ret = int(v,2)
In [3]: print(ret)
123
2. 八进制转换成十进制:v = "0o11"
In [5]: v = '0o11'
In [6]: ret = int(v,8)
In [7]: print(ret)
9
3. 十六进制转换成十进制:v = "0x12"
In [9]: v = '0x12'
In [10]: ret = int(v,16)
In [11]: print(ret)
18
4. 十进制转换成二进制:v = 18
In [12]: v = 18
In [13]: val = bin(18)
In [14]: print(val)
0b10010
5. 十进制转换成八进制:v = 30
In [15]: v = 30
In [16]: val = oct(v)
In [17]: print(val)
0o36
6. 十进制转换成十六进制:v = 87
In [18]: v = 87
In [19]: val = hex(v)
In [20]: print(val)
0x57
首先需要将每个十进制数分别转换成二进制数再将这些二进制数拼接在一起,然后转换成十进制整数。我们可以在vim编辑器编写代码如下
def ip_zh(ip):
ip_list = ip.split('.')
# print(ip_list)
sum = ''
for item in ip_list:
# print(type(int(item)))
# print(bin(int(item)))
# print(type(bin(int(item))))
ret = bin(int(item))[2:]
if len(ret) < 8:
ret = (8 - len(ret)) * '0' + ret
# print(ret)
sum += ret
return int(sum,2)
print(ip_zh('10.3.9.12'))
python中默认递归限制的最大次数是1000层,查看默认最大层数:
In [21]: import sys
In [22]: sys.getrecursionlimit
Out[22]: <function sys.getrecursionlimit>
In [23]: sys.getrecursionlimit()
Out[23]: 3000
1、v = 1 or 3 # 如果1是真结果就是1,否则是3。所以,本题结果是1
2、v = 1 and 3 # 如果1是假,结果就是1,如果1是真,结果就是3。所以,本题结果是3
3、v = 0 and 2 and 1 # 从前到后计算,先看前一个and,因为0是假,所以结果是0。后一个and,0是假,所以结果是0
4、v = 0 and 2 or 1 # 因为0是假,所以前两个的结果是0, 0是假但是1是真,所以结果是1
5、v = 0 and 2 or 1 or 4 # 因为0是假,所以前两个结果是0。对于0 or 1,0是假,但是1是真,所以结果是1。对于1 or 4,1是真结果就是1。
6、v = 0 or Flase and 1 # 因为0是假,所以结果是False。对于False and 1因为False是假,所以结果是False
ASCII:使用一个字节编码,所以它的范围基本是只有英文字母、数字和一些特殊符号 ,只有256个字符,使用8位二进制表示信息。
Unicode:使用32位表示信息,Unicode一般用于计算机内存中做计算。
GBK:只用来编码汉字的,GBK全称《汉字内码扩展规范》。使用双字节编码,一个中文占2个字节。
UTF-8:压缩Unicode,使用8位二进制表示信息,用尽量少的位数来表示信息,节省存储空间。UTF-8中一个中文占3个字节,UTF-8一般可用于网络传输和数据存储。
字节码是一种已经经过编译需要通过翻译后才能成为机器码的中间码,字节码通常不像源码一样可以让人阅读。字节码主要是为了实现特定软件的运行与软件环境和硬件环境无关的,字节码的实现方式是通过编译器和虚拟机。编译器将源码编译成字节码,特定平台上的虚拟机把字节码可以直接翻译成可执行的指令。字节码典型的应用是java语言。总而言之,字节码是一种中间状态的二进制代码(中间码),需要直接翻译才能成为机器码。
机器码是计算机可以直接执行并且执行速度最快的代码,由0和1组成的二进制代码序列。
print。在python2中print被视为一条语句,而不是一个函数。如果在python2中输出一个字符串,不要加括号。但是,在python3中,print被视为函数。输出的字符串需要放到print函数中。【python3使用print必须以小括号包裹打印内容,python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容。】
python2中range函数返回列表,而python3返回迭代器,节约内存。
python2中使用ASCII编码,python3中使用UTF-8编码。
python2中Unicode表示字符串,str表示字节。而python3中str表示字符串,byte表示字节。【python2 中的 unicode 类型是 python3 中的 str 类型,python2中的str类型是 python3 中的bytes类型。所以对于网络传输,python2使用str类型,python3使用bytes类型。】
python2中为正常显示中文,引入coding声明,python3中可以不用声明。
python2中的raw_input()函数是python3中input()函数
对包的定义,python2中必须要有_ _ init _ _.py文件;python3中不是必须使用这个文件
对于map和filter:python2中返回列表,python3中返回迭代器
``
python2中有int和long类型,但是python3已经废弃了long类型,统一使用int类型。
a , b = b , a
range和xrange都在循化中使用,输出的结果一样
range返回的是list对象,而xrange返回的是一个生成器对象(xrange object)
xrange不会直接生成一个list,而是每次调用返回其中的一个值,内存空间使用极少,因而性能高
python3中已经去掉了xrange函数,全部用range代替。
二者使用相同,但返回值类型不同,xreadlines返回的是一个生成器,readlines返回的是list
0,None,空(空字符串、空列表、空字典、空元组)
pass可作空语句,表示什么也不做;也可以保证格式的完整,保证语义的完整。
# 可做空语句,表示什么也不做
if true:
pass
else:
pass
# 保证格式的完整
def foo():
pass
# 保证语义的完整
while True:
pass
args不支持关键字传参,只支持位置传参,可以接收任意个数的位置参数,并将参数转换成元组
kwargs可以接收任意数量的关键字参数,并将参数转换为字典。
==用于比较值是否相等,is用于比较内存地址是否相等。
可变类型内部不能被修改的,只能重新赋值,如 int、str、bool、tuple
不可变类型的内部可以被修改的,如list、set、dict
django、flask、pip、pygame、pymysql、numpy、pandas、hashlib、json、datetime、time、os、sys、logging等等……
装饰器的写法:
def x(func):
def inner(*args,**kwargs):
data = func(*args,**kwargs)
return data
return inner
应用场景:在flask框架和django框架中都有应用,如路由、权限等
python中,安装第三方模块,是通过setuptools这个工具完成的。python有两个封装了setuptools的包管理工具:easy_install和pip,目前官方推荐使用pip。
jinjia2、requests、、、、
对于字符串"1,2,3"转换成[1,2,3],可以使用split(',')方法以逗号分割将字符串分割成列表[1,2,3],然后把每个list的元素转换成int类型。
对于[1,2,3]转换成"1,2,3"可以先见列表中每个元素转换成字符串,然后使用列表的join方法以逗号的方式将元素连接成字符串。
1 or 2 # 1
1 and 2 # 2
1 < (2==2) # 比较大小的时候要转换成bool类型,2==2是真为True,1< True等价于True < True,所以为False
1 < 2 = 2 # 1 < 2 为真得True,True = 2等价于True = True,所以为True
[i**2 for i in range(1,11)],考察的是列表生成式。
list(set([1,2,1,2]))
[1,2,3] 列表和 [(1),(2),(3)] 列表是等价的,元素都是整型。[(1,),(2,),(3,)] 列表中的元素都是元组类型。
将可变对象作为默认参数,若多次调用时使用默认参数,默认参数会保留上次调用时的状态。可以在函数体中判断如果b不是空列表就让为空列表,即:if b:b=[]
[ i % 2 for i in range(10) ] # 是一个列表:[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
( i % 2 for i in range(10) ) # 是一个元组,所以结果是一个生成器对象
在函数的内部,通过global声明,使在函数内部中设置一个全局变量,这个全局变量可以在任意的函数中进行调用。
贪婪匹配是尝试匹配尽可能多的字符,非贪婪匹配是尝试匹配尽可能少的字符。
import re
code = 'thanlonkikuthanlon'
ret1 = re.findall('a.*lon', code) # 贪婪匹配
print(ret1) # ['anlonkikuthanlonlon']
ret2 = re.findall('a.*?lon', code) # 非贪婪匹配
print(ret2) # ['anlon', 'anlon']
loggin模块的作用:可以更好的管理我们的日志,并且可以将标准输入输出保存到日志文件,而且利用logging模块可以部分代替debug的功能,给程序排错。
应用场景:设置登录日志,将系统错误信息写入日志等等。
match函数在字符串第一个位置(0索引)匹配成功才会返回,不是第一个位置匹配成功则返回None:
In [1]: import re
In [2]: re.match('thanlon','thanlonlovekiku')
Out[2]: <re.Match object; span=(0, 7), match='thanlon'>
search函数会扫描整个字符串返回第一个成功匹配:
In [3]: re.search('thanlon','kikulovethanlon')
Out[3]: <re.Match object; span=(8, 15), match='thanlon'>
'''
基于列表实现栈
'''
class Stack(object):
def __init__(self):
self.data = []
def push(self, val):
self.data.append(val)
def pop(self):
return self.data.pop()
def top(self):
return self.data[-1]
stack = Stack()
stack.push('Thanlon')
stack.push('Kiku')
print(stack.data)
print(stack.pop())
print(stack.pop())
'''
['Thanlon', 'Kiku']
Kiku
Thanlon
'''
引用计数可以用于跟踪和回收垃圾。标记清除,解决容器对象可能产生的循环引用问题。分代回收,以空间换取时间进一步提高垃圾回收的效率。
可变类型:可变类型有list、dict,可变类型的内部是可以被修改的。不可变类型只要值相同就不会指向同一地址。
不可变类型:不可变类型有int、string和tuple,不可变类型的内部是不可以被修改的。可变类型只要值相同就指向同一个内存地址(除非进行复制操作,那么他们将会指向同一个地址)。
==用于比较值是否相等
is用于比较内存地址是否相等
filter是对序列中的元素进行筛选,最终获取符合条件的序列。
map是用同样方法把所有数据都改成别的。
reduce是用某种方法依次把所有数据丢进去最后得到一个结果。
os模块可以获取与操作系统相关的数据,是一个用于访问操作系统功能的模块;sys模块中包含pthon解释器相关的数据,用于提供对python解释器相关的操作。
使用random函数可以生成一个随机数,如:
随机整数:random.randint(a,b),得到值x在a<=x<=b
返回一个范围在start和stop之间且步长为step的随机整数,不包括结束值:random.randrange(start,stop,step)
返回0到1之间的浮点数:random.random( )
返回指定范围内的浮点数:random.uniform(a,b)
可以使用python内置模块 shutil 中的 rmtree 方法,也可以使用os.remove(path)来删除文件。
一般我们认为在类中是方法,写在外面的是函数。其实,这样判断是函数还是方法是不精准的。方法和函数的区分,不仅和定义的位置有关系,还和方法或函数的调用者有关系。如果通过“对象.xxx”调用,那么xxx就是方法。如果通过“类.xxx”调用或者直接执行xxx,那么xxx就是个函数。
__init__、__new__、__call__、__enter__、__exit__、__getitem__、__ setitem__、__ delitem__、 __ add __
__new__是一个静态方法,__init__是一个实例方法。__new__方法会返回一个创建的实例,而__init__什么都不返回。只有在__new__返回一个类的实例时,后面的__init__才能被调用。当创建一个新实例时调用__new__,初始化一个实例时用__init__。
functools模块用于高阶函数,是作用于函数或者返回其他函数的函数。使用过functools模块中的reduce函数,用某种方法依次把所有数据丢进去最后得到一个结果。
functools的作用是提供一种用于对函数固定属性的函数。
super不是指父类(基类),而是按照类的继承顺序指下一个类。可以写一个帮助理解的程序:
# coding:utf-8
class Base(object):
def f1(self):
print('Base.f1()')
pass
class Foo1(object):
def f1(self):
super().f1()
class Foo2(object):
def f1(self):
print('Foo2.f1()')
class Info(Foo1, Foo2):
pass
obj = Info()
obj.f1()
'''
先找Info类中有无f1方法,确认Info类中没有f1方法
下面按照类的继承顺序,找下一个类Foo1
Foo1中找到f1方法,Foo1中的f1方法执行super().f1()
super().f1()即:按照Info类的继承顺序找下一个类(注意:并不是去Foo1的基类object中找f1),看有无f1方法
下一个类是Foo2,在Foo2中找到了f1方法,所以执行Foo2类中的f1方法
'''
静态方法:如果方法无需使用对象中封装的值,那么就可以使用静态方法。写静态方法时,方法上方需要写@staticmethod,方法中参数可有可无,参数中不可以用self会出错,解释器执行时也不会将self自动传入参数列表。
类方法:如果在方法中会使用到当前类,那么就可以使用类方法。定义类方法时,方法上方写@classmethod,方法中至少有一个参数cls。定义类方法时,方法上方写@classmethod,方法中至少有一个参数cls。
判断对象是否是某一个指定类或其及父类的实例。
可以设置 json 模块的 dumps 函数里的参数 ensure_ascii=False,默认 ensure_ascii = True。json.dumps(v, ensure_ascii=False)
int、bool、str、list、dict、tuple、None(除了集合)
将datetime类型通过字符串的 strftime 方法转换成字符串类型,然后序列化字符串。
1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
3、核心模块用Cython、PyPy等,提高效率
4、使用多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率。
yield:生成器每次循环都会获取yield返回的值。
yield from:从当前生成器跳到另一个生成器。
需要使用到os模块,
import os
res = os.walk(r'E:\pycharmProjects\practice')
for a, b, c in res:
'''
a:正在查看的目录
b:此目录下的文件夹
c:此目录下的文件
'''
# print(a)
# print(b)
# print(c)
'''
E:\pycharmProjects\practice
['.idea', 'test']
['test.py']
E:\pycharmProjects\practice\.idea
[]
['misc.xml', 'modules.xml', 'practice.iml', 'workspace.xml']
E:\pycharmProjects\practice\test
[]
['index.html', 'log.txt']
'''
for item in c:
path = os.path.join(a, item)
print(path)
'''
E:\pycharmProjects\practice\test.py
E:\pycharmProjects\practice\.idea\misc.xml
E:\pycharmProjects\practice\.idea\modules.xml
E:\pycharmProjects\practice\.idea\practice.iml
E:\pycharmProjects\practice\.idea\workspace.xml
E:\pycharmProjects\practice\test\index.html
E:\pycharmProjects\practice\test\log.txt
'''
字符串:len、join、split、strip、upper、lower、replace、isdigit、startwith、endwith、format
列表:len、append、insert、pop、remove、clear、expend、reverse、sort
元组:len
字典:keys、values、items、get、pop、update
第一种:print('%s,%s'%('thanlon','kiku')),最方便的,需要一个个格式化。
第二种:print('{},{}'.format('thanlon','kiku'))、print('{first},{second}.format(first='thanlon',second='kiku')'),最先进的,可读性强
第三种:print('%(first)s,%(second)s'%{'first':'thanlon','second':'kiku'}),最好用的,不需要一个个格式化,可以用字典的方式,缩短时间。
迭代器:访问集合元素的一种方式,从集合的第一个元素开始访问,直到所有元素被访问结束。其优点是不需要事先准备好整个迭代过程中的所有元素,仅在迭代到某个元素时才开始计算该元素。适合遍历比较巨大的集合。__iter__方法返回迭代器本身, __next__方法用于返回容器中下一个元素或数据。
生成器:带有yield的函数不再是一个普通函数,而是一个生成器。当函数被调用时,返回一个生成器对象。不像一般函数在生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行状态。【生成器用来一点一点产生数据的。生成器只有被for循环时,生成器函数内部的代码才会被执行,生成器每次循环都会获取yield返回的值。】
可迭代对象:可以被for循环且对象中具有__iter__方法,还要返回一个迭代器(或生成器)
反射:实质上是利用字符串的形式去对象(模块)中操作(查找/删除/添加)成员,是一种字符串的时间驱动。【反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。python面向对象中的反射就是通过字符串获取模块、对象或类的属性,进行操作。】
应用场景:需要执行对象中的某个方法或者调用对象中的某个变量,但是种种原因无法确定方法或变量是否存在。
num = 0
for i in range(1, 6):
for j in range(1, 6):
for k in range(1, 6):
if i != j and i != k and j != k:
num += 1
print(num) # 60
v = dict.fromkeys(['k1','k2'],[])
v['k1'].append(666)
print(v)
v['k1'] = 777
print(v)
v = dict.fromkeys(['k1', 'k2'], []) # {'k1': [], 'k2': []}
v['k1'].append(666)
print(v) # {'k1': [666], 'k2': [666]}
v['k1'] = 777
print(v) # {'k1': 777, 'k2': [666]}
三元运算规则:对于v = value1 if 条件 else value2,如果条件成立,v = value1,否则 v = value2。
三元运算应用场景:简单的 if else 结构
lambda表达式格式:函数名 = lambda 参数:函数返回
lambda表达式的应用场景:lambda可以用来定义一个匿名函数,可以用来解决简单的函数
优点:1. 建造系统中的类,避免重复操作。2. 新类经常是基于已经存在的类,这样就可以提升代码的复用程度。
特点:1. 在继承中基类的构造方法(__init__)不会被自动调用,它需要在其派生类的构造中方法中专门调用;2. 在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。3. python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。
面向对象中有封装、继承、多态、
所谓的面向对象的封装就是将我们的程序模块化,对象化,把具体事物的特性属性和通过这些属性来实现一些动作的具体方法放到一个类里面,这就是封装。封装是我们所说的面相对象编程的特征之一。【面向对象中的最重要的是封装,可以将实现归类和打包。归类:将相似功能的函数放到一个类中;打包:可以将数据打包放到对象中。】
继承是实现代码的复用,一个类可以继承另外一个类,被继承的类称为父类,继承的称为字类。面向对象里的继承也就是父类的相关的属性,可以被子类重复使用,子类不必再在自己的类里面重新定义一回。需要用到的新的属性和方法时,子类也可以自己来扩展。增加了类的耦合性,使得代码更加规范化、合理化。
多态:在子类里面把父类里面定义的方法在子类里面重新实现一遍,多态包含了重载和重写。 重载就是类里面相同方法名,不同形参的情况,可以是形参类型不同或者形参个数不同,或者形参顺序不同,但是不能使返回值类型不同。重写很简单就是把子类从父亲类里继承下来的方法重新写一遍,覆盖父类的方法。
闭包:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成了一个闭包。闭包为函数创建一块区域为其维护自己的数据,以后执行时方便调用。闭包的应用场景之一就是装饰器。下面是闭包的例子:
def outer(): # 外部函数
b = 10
def inner(): # 内部函数
print(a+b) # 调用外部函数的形式参数
return inner # 返回内部函数
一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
__init__:类名(),自动执行__init__方法
__call__:对象(),自动执行__call__方法
__getitem__:对象[],自动执行__getitem__方法
__setitem__:对象['xxx']=xx,自动执行__setitem__方法
__delitem__:del 对象,自动执行__delitem__方法
__add__:对象+对象,自动执行__add__方法
__enter__与__exit__:with 对象,自动执行__enter__和__exit__方法
__new__:类(),其实是先执行__new__方法,再执行__init__方法