文章目录
- 基础知识
- max,min也可以支持key参数
- 列表
- 元组
- 对象
- 模块
- 小tips
- —属性—
- 获取对象类型
- 列表生成式
- 生成器表达式
- 迭代器
- 序列解包
- 函数
- 字符串
- str.format()
- **encode()和decode()函数**
- str.islower()、str.isspace()
- join(),ljust(),rjust(),center()
- find(),rfind(),index(),rindex(),count(),split(),rsplit(),partition(),rpartition()
- replace(),maketrans(),translate()
- s.isdigit、isdecimal 和 s.isnumeric 区别
- **strip()、rstrip()、lstrip()、startswith()、endswith()**
- 字符串内置函数
- 字符串常量
- 函数参数
- 排序算法
- 类
Python是脚本语言
脚本语言(Scripting language)是电脑编程语言。以简单的方式快速完成某些复杂的事情通常是创造脚本语言的重要原则,基于这项原则,使得脚本语言通常比 C语言、C++语言 或 Java 之类的系统编程语言要简单容易。
一个脚本可以使得本来要用键盘进行的相互式操作自动化。一个Shell脚本主要由原本需要在命令行输入的命令组成,或在一个文本编辑器中,用户可以使用脚本来把一些常用的操作组合成一组串行。主要用来书写这种脚本的语言叫做脚本语言。很多脚本语言实际上已经超过简单的用户命令串行的指令,还可以编写更复杂的程序。
IDLE是一个Python Shell,shell的意思就是“外壳”,基本上来说,就是一个通过键入文本与程序交互的途径!像我们Windows那个cmd窗口,像Linux那个黑乎乎的命令窗口,他们都是shell,利用他们,我们就可以给操作系统下达命令。同样的,我们可以利用IDLE这个shell与Python进行互动。
想具体查看某个 BIF(built in function内置函数) 的功能 help( )让系统告诉你 括号里面的东西有什么作用
C:\Users\HUAWEI>conda activate base #进入环境
(base) C:\Users\HUAWEI>python
Python 3.8.5 (default, Sep 3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> dir(__builtins__) #显示内置函数和内置对象,其中小写的就是 BIF
[ 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max'....]
>>> exit() (or Ctrl-Z)
(base) C:\Users\HUAWEI>conda deactivate #退出环境
C:\Users\HUAWEI>
基础知识
提前预热一下,不懂的后面还会讲解。
a='abc'
isinstance(a,str)
# 输出:True
优先级: 幂运算>正负号>加减乘除> == != > >= >逻辑运算符
not and or 逻辑运算符3<4<5 ture
三元操作符 a=x if x<y else y
pthon内置的数字类型有整数,实数,复数
对于实数的运算可能会有一定的误差,尽量避免在实数直接进行相等性测试,而是以两者之差的绝对值是否足够小作为是否相等的依据
>>> 0.4-0.3
0.10000000000000003
>>> 0.4-0.3==0.1
False
>>> abs(0.4-0.3-0.1)<1e-6
True
#复数 x=3+4j
abs(x) #5
x.imag #4.0
x.real #3.0
x.conjugate #(3-4j)
python中字符也是字符串
'1,2,3'+'4,5' #连接两个字符串'1,2,3,4,5'
[1,2,3]+[4,5] #[1,2,3,4,5]
*除了乘法运算,还可以表示序列的重复
[1,2,3]*3#[1,2,3,1,2,3,1,2,3]
'abc'*3 #'abcabcabc'
python不支持++ --运算 ++i解释为两个正号,i值不变,i++直接报错,所以直接i+=1,i-=1用着就行
>>> bin(555) #二进制
'0b1000101011'
>>> oct(555) #八进制
'0o1053'
>>> hex(555) #十六进制
'0x22b'
ord()<->chr() 返回单个字符的Unicode码<->返回Unicode的字符
eval()用来计算字符串的值,有时候可以实现类型转换 eval('9') #转化为int与int('9')等效
用户不管输入什么内容,input()一律作为字符串对待,顾我们需要对输入内容进行转化
>>> x=input('please')
please[1,2,3]
>>> x
'[1,2,3]'
>>> list(x)
['[', '1', ',', '2', ',', '3', ']']
>>> eval(x)
[1, 2, 3]
python中的正无穷或负无穷
使用float (“inf”)或float ("-inf")来表示。 这里有点特殊,写成:float (“inf”),float (“INF”)或者float (‘Inf’)都是可以的。 当涉及 > 和 < 比较时,所有数都比无穷小float ("-inf")大,所有数都比无穷大float (“inf”)小。
print(float('inf'))
print(complex('inf'))
print(float('inf')*0)
print(math.isnan(float('nan'))) #还有math.isinf()判断是不是无穷
print(float('inf')*float('-inf')) #-inf
#输出
inf
(inf+0j)
nan
True
assert 断言 此关键字后面条件为假,程序自动崩溃报错
int()函数
它可以将给定的数值转换成十进制整数,转换时可以指定以几进制的方式解析给定的数。例如:
# 以10进制解析123,并转换成10进制整数
int(``"123"``) ``123` `
# 以2进制解析10101,并转换成10进制整数
int``(``"10101"``, base``=``2``) ``21` `
# 以13进制解析"abc12c",并转换成10进制整数
`int``(``"abc12c"``, base``=``13``) ``4053672
max,min也可以支持key参数
print(max(['2','111'],key=len)) #111
l = [[random.randint(1, 10) for i in range(5)] for j in range(10)] # 包含生成10个子列表,每个列表有5个介于[1,10]的整数的列表
print(len(l))
print(max(l, key=sum))
print(max(l,key=lambda x:x[1])) #按第二个大小排序
print(max(l,key=lambda x:(x[1],x[3])))# 先按第二个数比,若比不出来,再按第四个数比
**sorted()**和reversed()一样都是python的内置函数,与list.sort(),list.reverse()不一样,她两是list自带函数
reduce()
将接受两个参数的函数以迭代累积的方式从左到右依次作用到一个序列或迭代器对象的所有元素上
```python
from functools import reduce
print(reduce(lambda x,y:x+y,[1,2,3,4])) #10 (1+2)+3....
random.sample()
从指定序列中随机获取指定长度的片断并随机排列,结果以列表的形式返回.choice() 方法返回一个列表,元组或字符串的随机项。randrange() 方法返回指定递增基数集合中的一个随机数,基数默认值为1。
# 输出 100 <= number < 1000 间的偶数
print "randrange(100, 1000, 2) : ", random.randrange(100, 1000, 2)# 976
eval 方法能使字符串本身的引号去掉,保留字符的原本属性。
**exec():
不同于eval ()函数只能执行计算数学表达式的结果的功能,exec ()能够动态地执行复杂的Python代码
x = 'name = "Bill"\nprint(name)'
exec(x)
#输出Bill
>>>exec 'print "Hello World"' #外面双引号也行
Hello World
exec(source,globals=None,locals=None)
列表
#这里点号前面都应该是一个list
dir(list)#查看list属性
#加 append,追加 insert extend
.insert # 可以确定加入的位置 member.inesrt(1,"哈哈哈")
.extend # 可以加一个列表 member.extend(["hhhhh","jjjjjjjj"]) or list1.extend(list2)
.remove(x) # 删第一次出现的x,如果没有就抛出异常
.pop()# 默认删最后一个 or .pop(1)删第二个元素
.clear() # 清空
del list[1]# 采用关键字的形式
len(列表名) # 列表元素个数
.count(x) # 某元素出现次数
.sort()# 原地排序,默认升序,key指定排序规则 reverse=True降序
.reverse()# 原地翻转
# 一些例子
>>> list(range(5))
[0, 1, 2, 3, 4]
>>> tuple(_) #一个下划线表示上一次正确的输出结果
(0, 1, 2, 3, 4)
>>> list(str([1,2,3]))
['[', '1', ',', ' ', '2', ',', ' ', '3', ']']
>>> e=list(range(11))
>>> e
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> sorted(e,reverse=True)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> sorted(e,key=lambda i:(len(str(i))))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> sorted(e,key=lambda i:(len(str(i))),reverse=True)
[10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list({'a':3,'b':4})) #['a', 'b']
print(list({'a':3,'b':4}.items())) #[('a', 3), ('b', 4)]
print(list({'a':3,'b':4}.values())) #[3, 4]
x=list()
del x
print(x) # NameError: name 'x' is not defined
a[ : ] 可以拷贝列表
元组
元组是轻量级列表,常量级列表。元组的访问速度比列表快,还具有安全性、
若创建一个只有一个元素的元组 ,在后面加逗号 eg:tuple=(1,) tuple=1, 甚至不用括号>>> 8*(8,)得到(8,8,8,8,8,8,8,8)
temp=(‘哈哈哈’,‘不不不’,‘时代的’,‘十大)
temp=temp[:2]+('sdsad',)+temp[2:]
temp
(‘哈哈哈’,‘不不不’,'sdsad',‘时代的’,‘十大)
.index("") # 得索引
set('111222333') #创建可变集合,自动去除重复 {'1','2','3'}
>>> import keyword 关键字
>>> print(keyword.kwlist)
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', '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']
导入模块后,在模块名称后敲.再按tab键,会显示该模块所有函数
>>> import random
>>> random.Tab
random.BPF random.betavariate( random.lognormvariate( random.setstate(#删了点
>>> random.randint(1,3) #[1,3]的随机整数
1
random.random() #【0,1)随机小数
random.randrange(1,100) #[1,100)随机整数
光标置于函数调用处ctrl+q可查看函数注释
函数之前最好空两行
def ahb():
"""打招呼"""#前面有tab缩进
#也可以点击函数名,出现小灯泡,点击,再点insert document string stub插入
print("hello python")
ahb()|ctrl+q
对象
print(range(100)) #range(0, 100)
# 以下都是可迭代对象 zip,enumertae,map,filter
# 列表元组那些是容器对象
zip() 打包 压缩
把多个可迭代对象对应位置上的元素压缩到一起,返回一个可迭代的zip对象
原型:zip([iterable,…]) 参数iterable为可迭代对象,该函数返回一个以元组为元素的列表(换种说法:将多个迭代器取元素组合成一个新的迭代器),第i个元组包含每个参数列表的第i个元素,
import numpy as np
a=[1,2,3,4,5]
b=(1,2,3,4,5)
c=np.arange(5)
d="zhang"
zz=zip(a,b,c,d)
print(list(zz)) #输出[(1, 1, 0, 'z'), (2, 2, 1, 'h'), (3, 3, 2, 'a'), (4, 4, 3, 'n'), (5, 5, 4, 'g')]
#我本来最后一行是print(zz) 输出<zip object at 0x0000017C0D2FBE80>是因为大部分返回list的函数不在返回list,而是返回一个支持遍历的对象 如下
$ python3
>>> a = map(abs, [1, 2, -3])
>>> a
<map object at 0x100707ed0>
>>> list(a) # 如果不习惯,可以自己手动转化为list,也是写兼容代码需要注意的地方,看上面,我就是这样改的
>>>[1,2,3]
$ python2
>>> a = map(abs, [1, 2, -3])
>>> a
[1, 2, 3]
#每个参数列表元素个数不一样时,返回的列表都被截断为最短参数序列的长度
#只有一个参数时
zz=zip(a) #输出[(1,), (2,), (3,), (4,), (5,)]
#zip()应用:矩阵加减,点乘
m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
n = [[2, 2, 2], [3, 3, 3], [4, 4, 4]]
print([x*y for a, b in zip(m, n) for x, y in zip(a, b)])
print([x+y for a, b in zip(m, n) for x, y in zip(a, b)])# 输出[2, 4, 6, 12, 15, 18, 28, 32, 36]
# [3, 4, 5, 7, 8, 9, 11, 12, 13]
#*zip()函数是zip()的求逆过程
a=[1,2,3,4,5]
b=(1,2,3,4,)
d="zhang"
zz=zip(a,b,d)
#print(list(zz))
x, y, z = zip(*zz)
print(x)
print(y)
print(z)
a=dict(zip('1234','abcd')) #创建字典 {'3':'c','1':'a','2':'b','4':'d'}
enumerate()用来枚举*可迭代对象*中的元素
每个元素都是包含索引和值的元组
print(enumerate([1,2,3])) # <enumerate object at 0x0000013235763B00>
>>> a=[1,2,3,4,5]
>>> list(enumerate(a))
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
>>> list(enumerate(['abc','aaa'])) #列表
[(0, 'abc'), (1, 'aaa')]
>>> list(enumerate('aaa','bbb'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer
>>> list(enumerate(('aaa','bbb'))) #元组
[(0, 'aaa'), (1, 'bbb')]
map()映射函数
把一个函数依次映射到序列的每个元素上,并且返回一个可以迭代的map对象,原序列不修改
print(map(str, range(5))) #<map object at 0x0000020251726730>
print(list(map(str, range(5)))) #['0', '1', '2', '3', '4']
def add5(v):
return v + 5
print(list(map(add5, [1, 2, 3]))) #[6,7,8]
def add2(x, y):
return x + y
print(list(map(add2, [2, 2, 2], [3, 3, 3]))) #[5,5,5]
a,b=map(int,input('请输入两个数字').split())#input默认输出字符串格式,需要int一下
filter()过滤函数
将单参数函数作用到序列上,返回使得函数返回为True的元素组成的filter对象。
print(filter(None,[1,2,3,False])) #<filter object at 0x000001D4D9876730>
print(list(filter(None,[1,2,3,False])) #[1,2,3] 函数为None时,返回序列中为True的元素
print(list(filter(lambda x:x.isalnum(),['1','a','asa','?']))) #isalnum是字符串的方法,用于测试x是否是字母或数字 ['1', 'a', 'asa']
reversed()
reversed()是python自带的一个方法,准确说,应该是一个类;
在经过reversed()的作用之后,返回的是一个把序列值经过反转之后的迭代器,所以,需要通过遍历,或者List,或者next()等方法,获取作用后的值;
a="asdf"
print(''.join(reversed(a))) #字符串的反转 别的方法print(a[::-1])
print(tuple(reversed(a))) #元组的反转
print(list(reversed(a))) #列表的反转
range()
该函数返回具有惰性求值特点的range()对象,[start,stop)内以step为步长的整数
模块
在模块中定义的全局变量,函数都是模块能够提供给外界直接使用的工具
模块的导入顺序:标准库,扩展库,自定义库
要引入自己创建的库,项目右键,new个dictionary,里面写库
pip 库名 安装库或者setting里 project interpreter的+,搜索需要安装的库,install package
小tips
ctrl+?多层注释,与取消注释,还有进入typora源代码功能
.pyc 是编译过的文件,二进制文件
—属性—
name
可以识别程序的使用方式
若作为模块导入,__name__属性的值自动设置为模块名,如果作为程序导入,__name__属性值被自动设置为字符串"main"
#在hello.py文件中
def main():
if __name__=="__main__":
print("this program is run directly")
elif __name__=="hello":
print("this program is used as a module")
main() #调用上面函数
获取对象类型
1、type()函数·
>>> type(123)
<class 'int'>
>>> type(123)==int
True
>>> type(None)
<class 'NoneType'>
>>> type(abs)
<class 'builtin_function_or_method'>
>>> import types
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x:x)==types.LambdaType
True
2、isinstance()函数
明确class的继承关系,type()不方便。
#可以判断一个变量是否为某些类型中的一种
>>> isinstance([1,2,3],(list,tuple))
True
>>>isinstance(animal,Dog)
False
>>>isinstance(dog,Dog)
True
>>>isinstance(dog,Animal)
True
3、dir()函数
获得一个对象的所有属性和方法使用dir()函数,返回一个list
列表生成式
[n+1 for n in range(3)]
list=['a','b','c']
['app_%s'%n for n in list] # ->['app_a','app_b','app_c']
[n for n in range(3) if n%2==0]
[s for s in list1 if s.endswith('.txt')]
[i for i in lista if i in listb]# 取两个列表交集
[i for i in lista if i not in listb and (i%2==1)]# 在a不在b
[m+n for m in 'abc' for n in 'xyz'] #两重循环 一共9项
[i for first in vector for i in first] #二重循环
# 找出列表最大值的下标
from random import randint
x=[randint(1,10) for i in range(20)]
print(x)
m=max(x)
y=[index for index,value in enumerate(x) if value==m]
print(y)
#输出
[8, 3, 7, 9, 6, 8, 3, 6, 9, 9, 4, 9, 7, 6, 5, 5, 8, 2, 1, 9]
[3, 8, 9, 11, 19]
[(x,y) for x in [1,2,3] for y in [8,9]] #[(1, 8), (1, 9), (2, 8), (2, 9), (3, 8), (3, 9)]
[(x,y) for x in [1,2,3] if x==1 for y in [3,4] if x!=y]
生成器表达式
通过列表生成式,直接创建一个列表,如果创建一个很大的列表浪费了很大的空间,而我们只需要访问前面几个元素,那后面都浪费了,所以要用到生成器。
生成器表达式的结果是一个生成器对象,具有惰性求值的特点,只在需要的时候生成新元素,比列表推导式更高效。
使用生成器对象的方法:根据需要转化为列表或元组,或者生成器对象的____next____()方法或内置函数next()进行遍历或者for循环。
只能从前往后正向访问每个元素,不能再次访问已访问过的元素,也不支持下标访问元素,遍历结束后若要重新访问就要重新创建生成器对象。
# 第一种方法:类似列表生成式
g=(x*x for x in range(3))
next(g)# 访问下一个元素,next(iterater[,default]) 指定迭代结束后继续迭代时返回的默认值
######################
g=(i for i in range(3))
print(g)
print(next(g,'没下一个了'))
print(next(g,'没下一个了'))
print(next(g,'没下一个了'))
print(next(g,'没下一个了'))
#输出:
<generator object <genexpr> at 0x0000022794B06580>
0
1
2
没下一个了
#####################
for n in g:
print(n)
# 第二种方法:基于函数
def factor(max_num):
# 这是一个函数 用于输出所有小于max_num的质数
factor_list = []
n = 2
while n<max_num:
find = False
for f in factor_list:
# 先看看列表里面有没有能整除它的
if n % f == 0:
find = True
break
if not find:
factor_list.append(n)
yield n #用于构造生成器。抛出n然后继续向下执行
n+=1
# 练习 斐波那契数列
def feb(max_num):
n_1 = 1
n_2 = 1
n = 0
while n<max_num:
if n == 0 or n == 1:
yield 1 #yield相当于抛出,不是保存
n += 1
else:
yield n_1 + n_2
new_n_2 = n_1
n_1 = n_1 + n_2
n_2 = new_n_2
n += 1
g = feb(20)
for n in g:
print(n)
迭代器
- 迭代器访问与
for
循环访问非常相似,但是也有不同之处。对于支持随机访问的数据结构如元组和列表,迭代器并无优势。因为迭代器在访问的时候会丢失数据索引值,但是如果遇到无法随机访问的数据结构如集合时,迭代器是唯一访问元素的方式; - 迭代器仅仅在访问到某个元素时才使用该元素。在这之前,元素可以不存在,所以迭代器很适用于迭代一些无法预先知道元素总数的巨大的集合;
- 迭代器提供了一个统一的访问集合的接口,定义
iter()
方法对象,就可以使用迭代器访问。
可直接作用于for
循环的数据类型如list
、tuple
、dict
等统称为可迭代对象:Iterable
。使用isinstance()
可以判断一个对象是否是可迭代对象。例如:
from collections import Iterable
result = isinstance([],Iterable)
print(result)
result = isinstance((),Iterable)
print(result)
result = isinstance('python',Iterable)
print(result)
#输出
True
True
True
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。next()
函数访问每一个对象,直到对象访问完毕,返回一个StopIteration
异常。使用isinstance()
可以判断一个对象是否是**Iterator
对象**。例如:
from collections import Iterator
result = isinstance([],Iterator)
print(result)
result = isinstance((),Iterator)
print(result)
result = isinstance((x for x in range(10)),Iterator)
print(result)
#输出
FalseFalseTrue
所有的Iterable
都可以通过iter()
函数转化为Iterator
。
序列解包
# 对对象进行序列解包
x,y,z=range(3)
x,y,z=map(str,range(3))
# 对zip对象解包
for k,v in zip(['a','b'],[1,2]):
print(k,v) #zip的每一个元素k,v=(a,1) k,v=(b,2)
# 对列表进行序列解包
x,y,z=[1,2,3]
# 对字典的键,值,对进行序列解包
x,y,z={'a':1,'b':2,'c':3}
x,y,z={'a':1,'b':2,'c':3}.items()
x,y,z={'a':1,'b':2,'c':3}.values()
# 字符串序列解包
x,y,z='abc'
函数
形参:位置参数,默认值参数,可变长度参数
实参:关键参数
# 默认参数放在位置参数的后面
def demo(a,b,c=1):
print(a,b,c)
# 可变长度参数:*parameter用来接受多个位置实参放在一个元组里。然后对这些参数像对待元组一样操作(什么叫像,人家本来就是元组,哼唧唧)
#**parameter用来接受多个关键字参数并放在字典中,同上
# 将序列作为实参需要解包
seq=[1,2,3]
demo(*seq)
dict={1:'a',2:'b',3:'c'}
demo(*dict)
def demo1(*args):
print(args)
demo1(1,2,3,3,4) #(1,2,3,4)
dict={1:'a',2:'b',3:'c'}
demo1(*dict) #(1,2,3)
# 实参是字典时,可以使用一个或者两个*进行解包
# 对于**的要求实参字典中所有键都必须是函数的形参名称,或者与函数中两个*的可变长度参数相对应
def demo1(*args):
print(args)
def demo(a,b,c):
print(a,b,c)
def demo2(**kwargs):
print(kwargs)
dict = {'a': 1, 'b': 2, 'c': 3}
demo1(*dict)
demo(**dict)
demo2(**dict)
输出:('a', 'b', 'c')
1 2 3
{'a': 1, 'b': 2, 'c': 3}
字符串
utf8所有字符都是一个字节,
注意字符串是不可变的,任意的修改只是返回新的,本来字符串都没有改变。
str.format()
是字符串的格式化方法
# 可以使用命名索引 {price}、编号索引{0}、甚至空的占位符 {} 来标识占位符。
print("网站名:{name}, 地址 {url}".format(name="菜鸟教程", url="www.runoob.com"))
print('{:.2f}'.format(3.1415))
print("{1} {0} {1}".format("hello", "world")) # 设置指定位置
site = {"name": "菜鸟教程", "url": "www.runoob.com"}# 通过字典设置参数
print("网站名:{name}, 地址 {url}".format(**site)) # 这是解包当中多个参数的用法,下面是当做一个参数的用法
print('网站名:{0[name]},地址{0[url]}'.format(site)) # 也可
my_list = ['菜鸟教程', 'www.runoob.com'] # 通过列表索引设置参数
print("网站名:{0[0]}, 地址 {0[1]}".format(my_list)) # "0" 是必须的,这个0是传参的顺序在看
print("网站名:{0[0]}, 地址 {1[1]}{2[1]}".format(my_list,my_list,my_list))# 输出网站名:菜鸟教程, 地址 www.runoob.com菜鸟教程
# 也可以向 str.format() 传入对象:
class AssignValue(object):
def __init__(self, value):
self.value = value
my_value = AssignValue(6)
print('value 为: {0.value}'.format(my_value)) # "0" 是可选的
print("For only {price:.2f} dollars!".format(price = 49))
2、进阶用法
(1)< (默认)左对齐、> 右对齐、^ 中间对齐、= (只用于数字)在小数点后进行补齐
(2)取位数“{:4s}”、"{:.2f}"等
print('{:10s} and {:>10s}'.format('hello', 'world')) # 取10位左对齐,取10位右对齐
print('{:^10s} and {:^10s}'.format('hello', 'world')) # 取10位中间对齐
print('{0} is {0:>10.2f}'.format(1.123)) # 取2位小数,右对齐,取10位
# 输出
hello and world
hello and world
1.123 is 1.12
3、多个格式化
‘b’ - 二进制。将数字以2为基数进行输出。
‘c’ - 字符。在打印之前将整数转换成对应的Unicode字符串。
‘d’ - 十进制整数。将数字以10为基数进行输出。
‘o’ - 八进制。将数字以8为基数进行输出。
‘x’ - 十六进制。将数字以16为基数进行输出,9以上的位数用小写字母。
‘e’ - 幂符号。用科学计数法打印数字。用’e’表示幂。
‘g’ - 一般格式。将数值以fixed-point格式输出。当数值特别大的时候,用幂形式打印。
‘n’ - 数字。当值为整数时和’d’相同,值为浮点数时和’g’相同。不同的是它会根据区域设置插入数字分隔符。
‘%’ - 百分数。将数值乘以100然后以fixed-point(‘f’)格式打印,值后面会有一个百分号。
>>> print('{0:b}'.format(3))
11
>>> print('{:c}'.format(65))
A
>>> print('{:d}'.format(20))
20
>>> print('{:o}'.format(20))
24
>>> print('{:x}'.format(20))
14
>>> print('{:e}'.format(20))
2.000000e+01
>>> print('{:g}'.format(20.1))
20.1
>>> print('{:f}'.format(20))
20.000000
>>> print('{:n}'.format(20))
20
>>> print('{:%}'.format(20))
2000.000000%
name='fzh'
print(f'my name sji{name}') # 用f格式化字符串常量
print(r'wsb\n\t') # 用r使得转义字符不转义
f'{1+2}' #f'{ 表达式 }'
>>>'3'
x=1
print(f'{x+1=}') #输出结果'x+1=2' python3.8可以使用=来拼接运算表达式与结果
encode()和decode()函数
bytes.decode(encoding=“utf-8”, errors=“strict”)decode() 方法以指定的编码格式解码 bytes 对象。默认编码为 ‘utf-8’。会返回新的编码后的值,不会改变自身,因为字符串是不可变类型。
encode和decode分别指编码和解码。在python中,Unicode类型是作为编码的基础类型,Unicode不是编码格式,而是字符集。这个字符集包含了世界上目前所有的符号。
errors – 设置不同错误的处理方案。默认为 ‘strict’,意为编码错误引起一个UnicodeError。 其他可能得值有 ‘ignore’, ‘replace’, ‘xmlcharrefreplace’, ‘backslashreplace’ 以及通过 codecs.register_error() 注册的任何值。
>>> u = '中文' # 指定字符串类型对象u
>>> str1 = u.encode('gb2312') # 以gb2312编码对u进行编码,获得bytes类型对象
>>> print(str1)
b'\xd6\xd0\xce\xc4'
>>> u1 = str1.decode('gb2312') # 以gb2312编码对字符串str进行解码,获得字符串类型对象
>>> print('u1')
'中文'
>>> u2 = str1.decode('utf-8') # 报错,因为str1是gb2312编码的
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 0: invalid continuation byte
>>>"hello".encode("hex") #字符串转化为16进制
'68656c6c6f'
str.islower()、str.isspace()
1、字符串中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True 。str. issupper()相反
2、空白符包含:空格、制表符(\t)、换行(\n)、回车(\r)等,空串不算空白符。
print('\t\r\n '.isspace()) #True
print(''.isspace()) #False
join(),ljust(),rjust(),center()
后三个返回指定宽度的新字符串
>>> '-'.join('菜鸟教程') # 将字符串进行拼接
'菜-鸟-教-程'
>>>print('菜鸟教程'.ljust(6,'*'))
'菜鸟教程**' # 左对齐,相反的str.rjust()是控制右对齐
>>>'菜鸟教程'.ljust(3,'*') # 超过范围,输出原串
'菜鸟教程'
print('我爱中国'.center(6,'*')) # *我爱中国*
find(),rfind(),index(),rindex(),count(),split(),rsplit(),partition(),rpartition()
1,2是用来查找字符串在另一个字符串指定范围(默认整个字符串)首次和最后一次出现的位置,不存在则返回-1。3,4和1,2差不多,就是找不到会报错。5返回字符串在另一个字符串出现的次数,不存在则返回0。6,7以指定字符为分隔符,从字符串从左到右(从右到左)分割成为多个字符串,返回分割结果的列表。8,9是分成三部分。
s = '2001-4-5'
print(s.split('-'))
print(s.partition('-')) #('2001', '-', '4-5')
print(s.rpartition('-')) # ('2001-4', '-', '5')
print(list(map(int, s.split('-'))))
print(s.split('-',1)) # 指定拆分数,返回n+1个元素
s='\n\na\t b \n c'
print(s.split()) # 未指定分隔符,默认所有空白符号都作为分隔符,而且自动删除字符串两侧空白字符
s='\t \t a b \t'
print(s.split('\t')) # 输出['', ' ', ' a b ', '']空,空格,字符串,空
# split()和 join()可以删除字符串中多余的空白字符,连续多个空白字符只保留一个(只是join里面是空格的情况,我这里join是空串)
x='a bb c '
print(''.join(x.split())) #abbc
addr = "123@163.com"
print(addr.split('@')) # ['123', '163.com']
usr, web = addr.split('@') # 123 163.com
strtemp='ab2b3n5n2n67mm4n2'
print(len(strtemp.split('n'))-1) # 4 小应用:统计字符串中n出现的次数
replace(),maketrans(),translate()
s='abcasbca'
print(s.replace('a','我爱中国')) # 替换
table = ''.maketrans('ab','#@') # 生成字符映射表
print(s.translate(table)) # 根据映射表定义的对应关系转换字符串并替换其中字符,replace无法满足这要求
# 生成
我爱中国bc我爱中国sbc我爱中国
#@c#s@c#
s.isdigit、isdecimal 和 s.isnumeric 区别
isdigit()
True: Unicode数字,byte数字(单字节),全角数字(双字节)
False: 汉字数字,罗马数字,小数
Error: 无
isdecimal()
True: Unicode数字,,全角数字(双字节)
False: 罗马数字,汉字数字,小数
Error: byte数字(单字节)
isnumeric()
True: Unicode 数字,全角数字(双字节),汉字数字
False: 小数,罗马数字
Error: byte数字(单字节)
num = "1" #unicode
num.isdigit() # True
num.isdecimal() # True
num.isnumeric() # True
num = "1" # 全角
num.isdigit() # True
num.isdecimal() # True
num.isnumeric() # True
num = b"1" # byte
num.isdigit() # True
num.isdecimal() # AttributeError 'bytes' object has no attribute 'isdecimal'
num.isnumeric() # AttributeError 'bytes' object has no attribute 'isnumeric'
num = "IV" # 罗马数字
num.isdigit() # False
num.isdecimal() # False
num.isnumeric() # False
num = "四" # 汉字
num.isdigit() # False
num.isdecimal() # False
num.isnumeric() # True
print(“转换为二进制为:”, bin(dec))
print(“转换为八进制为:”, oct(dec))
print(“转换为十六进制为:”, hex(dec))
print( c + " 的ASCII 码为", ord©)
print( a , " 对应的字符为", chr(a))
items()以列表返回可遍历的元组数组
>>> params = {"a":"1", "b":"2", "c":"3"}
>>> ["%s=%s" % (k, v) for k, v in params.items()]
['a=1', 'c=3', 'b=2']
>>> ";".join(["%s=%s" % (k, v) for k, v in params.items()]) #";".join(params)也行
'a=1;c=3;b=2'
利用re模块分割含有多种分割符的字符串
strip()、rstrip()、lstrip()、startswith()、endswith()
来分割前缀和网址。 两侧,右侧,左侧 s.strip(‘a’)
s="beautiful is better"
print(s.endswith('er'))
print(s.endswith('er',10)) # True
import os
[filename for filename in os.listdir(r'D:\\') if filename.endswith(('.jpg','.gif'))] # 接受一个**元组**作为后缀,找出指定文件夹下所有扩展名为这些的东西
字符串内置函数
x='我爱 中国'
print(len(x)) # 输出字符串长度
print(max(x)) # 最大字符
print(min(x)) #最小字符
print(list(zip(x,x))) # 字符串也可以像序列一样,它也可以切片,但只能读取,不能修改
print(sorted(x)) # 进行排序,返回列表
print(x)
print(''.join(reversed(x))) # 翻转字符串
print(enumerate(x)) # 枚举字符串
print('3+4')
a=3
b=4
print(eval('a+b'))
# 输出
5
爱
[('我', '我'), ('爱', '爱'), (' ', ' '), ('中', '中'), ('国', '国')]
[' ', '中', '国', '我', '爱']
我爱 中国
国中 爱我
<enumerate object at 0x000002205F5A3B40>
3+4
7
字符串常量
string
模块包含了我们常用的一些常量字符串:
- 大小写字母:
string.ascii_letters
- 小写字母:
string.ascii_lowercase
- 大写字母:
string.ascii_uppercase
- 数字0-9:
string.digits
- 十六进制数字:
string.hexdigits
- 常见特殊符号:
string.punctuation
- 看起来像空格的字符:
string.whitespace
这可以是表示一条或者多条python语句的字符串,也可以是compile()返回的代码对象,globals必须是一个字典,而locals可以是任何映射,{用help查的}
创建二维列表
a=[[1,2],[3,4]] #直接定义
a=[]
for i in range(3):
a.append([]) #[ [] ]
for j in range(3):
a[i].append(i*3+j+1) #循环嵌套定义
a=[ [i*3+j for j in range (1,4)] for i in range(3)] #通过列表推导式
# 正则表达式
使用预定义的模式去匹配一类具有共同特征的字符串
函数参数
-
默认参数要放在所有必选参数的后面;
-
默认参数必须指向不变对象。
-
可变长度参数在定义函数时有两种形式,*,**,前者用来接收多个位置参数并将其放在一个元组中,后者接收多个关键字参数并将其放在字典中。
def a(**p): for item in p.items:#当字典在用 print(item) >>>a(b=1,c=2,d=3)#('b',1)('c',2)('d',3)
可变参数
在有些情况下,我们在定义函数的时候,还不能确定函数应该包含多少个参数,这时我们可以使用可变参数,可变参数就是传入的参数数量是可变的。例如:
# 定义plus函数,完成的功能是返回输入的整数之和。
# 参数numbers是可变参数,表示输入的参数个数可以为任意值
def plus(*numbers):
add = 0
for i in numbers:
add += i
return(add)
# 调用3次plus函数,每次的参数个数都不相同
d1 = plus(1,2,3)
d2 = plus(1,2,3,4)
d3 = plus(1,3,5,7,9)
# 向函数中可以传递任意参数,包括0个参数
d4 = plus()
# 输出结果
print(d1)print(d2)print(d3)print(d4)
输出结果:
6
10
25
在上面的例子中,numbers
就是一个可变参数,可变参数前面加一个标识符*
。在函数内部,可变参数numbers
接收到的值是一个tuple
。我们在调用参数是可变参数的函数时,可以给该函数传递任意个数的参数,包括0
个参数。
关键字参数
可变参数允许我们在调用函数时传入任意个参数,这些可变参数在函数调用时自动组装为一个tuple
。而关键字参数允许我们传入任意个含参数名的参数,这些关键字参数在函数调用时自动组装为一个dict
。也就是说,关键字参数将长度任意的键-值对,作为参数传递给函数。例如:
# 定义一个包含关键字参数的函数,返回值为参数值
def plus(**kw):
return kw
# 调用plus函数,参数值为空
d1 = plus()
# 调用plus函数,参数值为
x=1
d2 = plus(x=1)
# 调用plus函数,参数值为
x=1,y=2
d3 = plus(x=1, y=2)
# 输出d1,d2,d3
print(d1)print(d2)print(d3)
输出结果:
{}{'x': 1}{'x': 1, 'y': 2}
在上面的例子中,kw
就是一个关键字参数,关键字参数前面加**
表示。关键字参数可以扩展函数功能,使传递参数过程更为简便。例如:
# 定义一个plus函数,有3个参数,返回值是3个参数之和
def plus(x,y,z):
return x+y+z
# 有一个dict列表,当中3个键的值分别为1,2,3
dict = {'x':1, 'y':2, 'z':3}
# 将dict列表中的3个值传入plus函数中,得到返回值
dd = plus(dict['x'],dict['y'],dict['z'])# 输出dprint(d)
输出结果:
6
但在上述例子中,将字典中的值向plus
函数中传递参数的方法过于累赘,可以采取关键字参数的方法。例如:
# 定义一个plus函数,有3个参数,返回值是3个参数之和
def plus(x,y,z):
return x+y+z
# 有一个dict列表,当中3个键的值分别为1,2,3
dict = {'x':1, 'y':2, 'z':3}
# 用关键字参数的方法将dict列表中的3个值传入plus函数中,得到返回值
dd = plus(**dict)
# 输出dprint(d)
输出结果:
6
使用关键字参数**dict
的方法,可以大大提高参数传递的效率。
参数组合
我们在函数定义过程中,可以同时用到必选参数、默认参数、可变参数、关键字参数中的一种或几种。但是需要特别注意的是,这四种参数在使用的过程中是有顺序的,顺序依次应该是必选参数、默认参数、可变参数和关键字参数。例如:
# 定义一个包含必选参数、默认参数、可变参数和关键字参数的函数plus
def plus(x, y, z=0, *args, **kw):
print('x=',x)
print('y=',y)
print('z=',z)
print('args=',args) p
rint('kw=',kw)
# 调用函数plus,输入两个参数1,2
plus(1,2)
输出结果:
x= 1y= 2z= 0args= ()kw= {}
上面这个例子中,向plus
函数中传入了两个必选参数1
和2
。必选参数必须得提供值,但是默认参数、可变参数和关键字参数可以不用提供值,我们还可以给默认参数、可变参数和关键字参数传递值。例如:
# 定义一个包含必选参数、默认参数、可变参数和关键字参数的函数plus
def plus(x, y, z=0, *args, **kw):
print('x=',x)
print('y=',y)
print('z=',z)
print('args=',args)
print('kw=',kw)
# 调用函数plus,输入参数x=1,y=2,z=3,args=(4,5,6),kw={}
plus(1,2,3,4,5,6)
print('\n')
# 调用函数plus,输入参数x=1,y=2,z=3,args=(4,5,6),kw={'k':7, 'm':8}
plus(1,2,3,4,5,6,k=7,m=8)
输出结果:
x= 1y= 2z= 3args= (4, 5, 6)kw= {}x= 1y= 2z= 3args= (4, 5, 6)kw= {'k': 7, 'm': 8}
小结
- 不同类型的参数是有顺序的,依次是必选参数、默认参数、可变参数和关键字参数;
- 默认参数一定要用不可变对象,用可变对象容易产生逻辑错误;
*args
表示的是可变参数,*args
接收的是一个元组;**kw
表示的是关键字参数,**kw
接收的是一个字典。
接下来总结一些排序算法,参考了菜鸟教程和一些博文,没给出代码请大家自行搜索。
排序算法
冒泡排序(Bubble Sort)
arr = [3, 2, 5, 6, 1]
def bubble_sort(arr):
for i in range(1,len(arr)): #一共需要进行n-1次排序,
for j in range(len(arr)-i): #在进行第i次排序的时候,需要排序的元素有n-i个,j的取值为(0,n-i-1)因为j+1得在范围内
if arr[j]>arr[j+1]: #这是按升序
arr[j],arr[j+1]=arr[j+1],arr[j]
归并排序(Merge Sort)
归并排序,是创建在归并操作上的一种有效的排序算法。算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。
快速排序(Quick Sort)
def quit_sort(arr, low, high):
if low >= high:
return arr
i = low # 首下标
j = high # 尾下标
pivot = arr[i] #选取第一个数为基准
while (i < j): #当i!=j时
while (i < j and arr[j] > pivot): #把arr[low]取走了,看做为空,从j那向左走,找小于基准值的填补空处
j -= 1
if i<j:
arr[i] = arr[j]
i += 1#填补后,i向右走一位
while (i < j and arr[i] < pivot): #替换之后arr[j]空了,从i那向右走,找大于基准值的填补空处
i += 1
if i<j:
arr[j] = arr[i]
j -= 1
arr[i] = pivot #最后把基准值还给最后i=j且为空的地方
quit_sort(arr, low, j - 1) #基准值左右部分分别递归排序
quit_sort(arr, j + 1, high)
return arr
low = 0
high = len(arr) - 1
quit_sort(arr, low, high)
print(arr)
插入排序(Insertion Sort)
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序和冒泡排序一样,也有一种优化算法,叫做拆半插入。
def insertionSort(arr):
for i in range(len(arr)):
preIndex = i-1
current = arr[i]
while preIndex >= 0 and arr[preIndex] > current:
arr[preIndex+1] = arr[preIndex]
preIndex-=1
arr[preIndex+1] = current
return arr
print(insertionSort(arr))
希尔排序(Shell Sort)
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
- 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;
def shellSort(arr):
import math
gap=1
while(gap < len(arr)/3):
gap = gap*3+1
while gap > 0:
for i in range(gap,len(arr)):
temp = arr[i]
j = i-gap
while j >=0 and arr[j] > temp:
arr[j+gap]=arr[j]
j-=gap
arr[j+gap] = temp
gap = math.floor(gap/3)
return arr
桶排序(Bucket Sort)
基数排序(Radix Sort)
堆排序(Heap Sort)
选择排序(Selection Sort)
def findsmall(arr):
smallest = arr[0]
smallest_index = 0
for i in range(1, len(arr)):
if arr[i] < smallest:
smallest = arr[i]
smallest_index = i
return smallest_index
def selection_Sort(arr):
newArr=[]
for i in range(len(arr)):
smallest_index=findsmall(arr)
newArr.append(arr.pop(smallest_index))
return newArr
print(selection_Sort(arr))
计数排序(Counting Sort)
类
class Person():pass
class Person(object):pass #object代表是, Person继承于哪一个类, 如果不知道继承哪个类, 就写object;
class Person:pass #定义类 如果这个类既不是别的类的父类也不是基类,他就不用写object,被继承就得写
xiaofan=Person() #实例化
定义类时,添加一个魔法方法____init____()为每一个实例统一加上以下属性。
class Person(object):
location='china' #类属性 实例属性优先级高于类属性
__hobby='eat' #类私有属性,两个下划线,不能被外部访问的属性,报错
def __init__(self,name,sex,age):
self.name=name #实例化时xiaofan=Person('xiaofan','girl')
self.sex=sex #访问时 print(xiaofan.name)
self.__age=age #实例私有属性
@classmethod # 修饰器,声明类方法,一般以cls作为第一个参数
def set_hobby(cls,hobby):
cls._hobby=hobby
@classmethod
def get_hobby(cls):
return cls._hobby #在class中定义类方法这么写。
@staticmethod # 修饰器,声明静态方法
def classshow(): # 静态方法,可以没有参数
print(Person._hobby)
def set_age(self,age)
self._age=age #允许外部代码修改age。
def get_age(self):
return self._age #允许外界代码获得age。get_age(self)是一个实例方法,在实例方法里可以操作私有属性,它的第一个参数是self
# def __init__(self,name,sex,age):也可看做一个特殊的实例方法,方法就是类的内部函数。注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
print(Person.location) #china类变量
p=Person('xiaozhu','girl',18)
print(p.get_age()) #18
# 静态方法和类方法可以通过类名和对象名调用,但这两种方法中不能直接访问属于对象的成员,只能访问属于类的成员。
print(Person.get_hobby()) #eat
Person.set_hobby('listen')
print(Person.get_hobby()) #listen
通过定义实例方法来操作私有属性的这种方法是推荐的,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。
方法
在 Python 类中有3种方法,即静态方法(staticmethod),类方法(classmethod)和实例方法:
- 对于实例方法,在类里每次定义实例方法的时候都需要指定实例(该方法的第一个参数,名字约定成俗为self)。这是因为实例方法的调用离不开实例,我们必须给函数传递一个实例。假设对象a具有实例方法 foo(self, *args, **kwargs),那么调用的时候可以用 a.foo(*args, **kwargs),或者 A.foo(a, *args, **kwargs),在解释器看来它们是完全一样的。
- 类方法每次定义的时候需要指定类(该方法的第一个参数,名字约定成俗为cls),调用时和实例方法类似需要指定一个类。
- 静态方法其实和普通的方法一样,只不过在调用的时候需要使用类或者实例。之所以需要静态方法,是因为有时候需要将一组逻辑上相关的函数放在一个类里面,便于组织代码结构。一般如果一个方法不需要用到self,那么它就适合用作静态方法。
和普通的函数相比,在类中定义的对象函数(还有静态方法,类方法)只有一点不同,就是第一个参数永远是实例变量self,并且,调用时不用传递该参数。
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__age是因为Python解释器对外把
__age变量改成了_Person__age,所以,仍然可以通过__age变量改成了
_Person__age变量. 即用p._Person__age获得 。 强烈建议不要这么干,因为不同版本的Python解释器可能会把__name改成不同的变量名。在类的外部: 对象._类名__属性名 查找{name mangling的技术(名字改编,名字重整)}
总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉。
以一个下划线开头的实例变量名,比如_name
,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
**init()**是构造方法,实例化类实例时默认调用的方法,用于接收参数。开头和末尾各有两个下划线,这是一种约定,用于避免默认方法与普通方法发生名称冲突。
Python调用这个__init__()方法来创建Person实例时,将自动传入实参self。每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
class Animal(object):
def __init__(self,name,age):
self.name=name
self.age=age
self.color = 'black' # 给属性指定默认值
def info(self):
return 'name={},age={}'.format(self.name,self.age)
def setage(self,age)
self.age=age
dog=Animal('xuzelong',20)
dog.tall=180 # 增加类的属性
dog.tall=190 # 改变类的属性
del dog.tall # 删除类的属性
print(hasattr(dog,'tall')) # True 判断是否有某个属性
Animal.info() #报错,不能通过类名访问实例方法TypeError: info() missing 1 required positional argument: 'self'就是他缺少实例
print(Animal.info(dog)) # 可以这样
hasattr(emp1, 'age') # 如果存在 'age' 属性返回 True。
getattr(emp1, 'age') # 返回 'age' 属性的值
setattr(emp1, 'age', 8) # 添加属性 'age' 值为 8
delattr(emp1, 'age') # 删除属性 'age'
继承
**super()**是一个特殊函数,帮助Python将父类和子类关联起来,
子类中定义了和父类同名的方法,子类的方法就能覆盖父类的方法。super关键字实现了对父类方法的改写
class Animal(object):
def __init__(self,name):
self.name=name
def greet(self):
print('hello,i am %s'%self.name)
class Dog(Animal):
def __init__(self,name,age):
super(Dog,self).__init__(age)
self.age=age
def greet(self):
super(Dog,self).greet()
print('wangwang...')
dog=Dog('mike')
dog.greet() #输出hello,i am mike \r wangwang...
MRO: method resoulution order 方法解析顺序,每一个类都有一个MRO列表(相册)
class Car():
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self): # 返回汽车的描述信息
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
"year需要转化为字符串才能使用title()函数"
return long_name.title()
def read_odometer(self): # 打印汽车的里程
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self, mileage): # 更新汽车的里程
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles): # 增加汽车里程
self.odometer_reading += miles
class ElectricCar(Car): # 必须在括号内指定父类的名称
"""电动汽车的独特之处"""
def __init__(self, make, model, year): # 接受创建Car实例所需的信息
"""初始化父类的属性"""
super().__init__(make, model, year) # 帮助Python将父类和子类关联起来
self.battery_size = 70 # 给子类定义新属性
def get_descriptive_name(self): # 重写父类的方法
long_name = str(self.year) + ' ' + self.make + ' ' + self.model + ' ' +str(self.battery_size)
return long_name.title()
"这里重写了父类的get_descriptive_name()方法,所以子类调用该方法时,Python将忽略Car类中的get_descriptive_name()方法。"
my_tesla = ElectricCar("tesla", "model s", 2016)
print(my_tesla.get_descriptive_name())
将实例用作属性:self.battery = Battery()
继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。
再来一个普通的继承代码
class Vehicle(object):
def __init__(self, wheels, weight):
self.__wheels = wheels
self.__weight = weight
def display(self):
print(self.__wheels, self.__weight)
def getWheels(self):
return self.__wheels
def setWheels(self, wheels):
self.__wheels = wheels
def getWeight(self):
return self.__weight
def setWheels(self, weight):
self.__weight = weight
class Car(Vehicle):
def __init__(self, wheels, weight, passenger_loader=4):
super(Vehicle, self).__init__(wheels, weight)
self.__passenger_loader = passenger_loader
def display(self):
#先调用父类的同名方法,显示从父类中继承来的数据成员
super(Vehicle,self).display()
print( self.__passenger_loader)
def getPassenger_loader(self):
return self.__passenger_loader
def setPassenger_loader(self, passenger_loader):
self.__passenger_loader = passenger_loader
动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的。不一定需要传入Animal
类型class abc(Animal)。我们只需要保证传入的对象有一个run()
方法就可以了: class abc(object):def run(self):
给对象和类绑定方法
(1)给对象绑定方法
from types import MethodType
a = A()
#a.func = MethodType(方法名,对象名)
a.func = MethodType(func,a)
(2) 给类绑定方法
#类名.属性名 = 函数名
A.func = func
- 给对象绑定属性或者方法 只有当前对象有
- 给类绑定属性或者方法 所有当前类的实例化的对象 都会拥有
lambda函数
普通函数用def关键字,定义匿名函数用lambda,在python中,通常使用它作为高阶函数(一个接受其他函数作为参数的函数)的一个参数,lambda函数与filter(),map()等内置函数一起使用。
python写一些执行脚本时,使用lambda就可以省下定义函数的过程。比较抽象并且整个程序执行下来只需要调用一两次的函数,懒得起名字的函数就可以使用lambda,
(1)和filter一起使用的示例
a=list(filter(lambda x:(x%2 == 0),[1,2,3,4,5]))
print a
输出
[2,4]
# 当函数计算结果为true时,将该项加入新列表,新列表作为filter函数的返回值。 过滤器
(2)和map一起使用的示例
a=list(map(lambda x: x*2,[1,2,5,4]))
print a
输出
[2,4,10,8]
# 列表的每一项都会调用被传入的函数,计算结果组成的新列表作为map函数的返回值。
一些例子:
filter(none,[1,0,false,true])
打出来了<filter object at 0x7sfd656>这样的filter对象,filter对象是可迭代的,因此我们可以用for循环,也可以用list()将其转化为列表。
list(filter(none,[1,0,false,true]))
[1,true]
print (list (filter (lambda x:x[0].lower()in "aeiou", ['sammy','ash','olly'])))
输出
['ash','olly']
将列表每一项声明为x,并以x[0]的方式访问每一个字符串的第一个字符,并且转化为小写,确保与‘aeiou’匹配