parameter:形参
argument:实参
python补漏
- try-finally语句中,finally中的return优先级高于try中的
- 找出程序耗时过程
python -m dis demo.py
- python package offline doc
python -m pydoc -p 5200
- python环境信息
python -m sysconfig
内置函数
int() | |
---|---|
bin() | 转换成2进制 |
oct() | 转换成8进制 |
hex() | 转换成16进制 |
abs(), pow(), float(), sum(), min(), max() | _ |
round() | 四舍五入 |
操作符
== 对比的值
is 对比的变量地址
运算次序
括号>函数>算术运算符>关系运算符>逻辑运算符
三元运算符
value1 if condition else value2
长度不得超过一行
对象
对象三要素
id
type
value
对象类型
-
不可变对象:num,string,tuple,重新赋值会再次分配地址
-
可变对象:list,dict,set
list_eg = [[1,2]] list_eg = list_eg * 4 print(list_eg) list_eg[2][1] = 128 print(list_eg) > [[1, 2], [1, 2], [1, 2], [1, 2]] [[1, 128], [1, 128], [1, 128], [1, 128]] #可变对象改值的时候,对原来的变量地址上的数据改动 #可变对象复制的时候,复制的是地址,所以只要相同地址的值变了,所有引用该地址的值都会变
为了避免以上问题,谨慎使用可变对象复制
若要使用列表复制,参考列表-属性-copy操作
字符串
字符串格式
%d | 10进制数 |
---|---|
%s | 字符串(string) |
%x | 16进制(hex) |
%o | 8进制(oct) |
%f | 浮点数 |
前缀字符
r或R | 包含的文本不转义 |
---|---|
b或B | bytes类型 |
字符串格式转换
str转bytes | string.encode() |
---|---|
bytes转str | string.decode() |
str转ASCII | ord(string) |
ASCII转str | chr(number) |
字符串运算
str1 + str2 | 连接 |
---|---|
str1 * num | 复制连接 |
max(str), min(str) | ASCII最大/ 最小 |
len(str) | 长度 |
常用字符串属性
str.capitalize() | 首字母大写,其余小写 |
---|---|
str.counter(char) | substr字符个数 |
str.format() | 格式化输出 |
str.lower() | 变成小写 |
str.upper() | 变成大写 |
str.strip() | 删除两边所有空 |
str.split(char) | 以char分割 |
str.title() | str的所有字母都大写 |
str.center(num,char) | 在str两边各填充num/2个char |
str.ljust(num,char) | 在str右边填充num个char |
str.rjust(num,char) | 在str左边填充num个char |
'test'.center(50,'-')
>'-----------------------test-----------------------'
'test'.ljust(50,'-')
>'test----------------------------------------------'
'test'.rjust(50,'-')
>'----------------------------------------------test'
列表
属性
list.append() | 追加 |
---|---|
list.insert(index,item) | 指定位置插入 |
list.remove(item) | 删除指定值 |
list.index(item) | 返回item的索引 |
list.count(item) | 返回item个数 |
list.clear() | 清空 |
list.reverse() | 逆序 |
list.sort(reverse) | reverse:bool类型,默认False,True降序,False升序 |
list.copy() | 复制列表,重新分配地址赋值 |
列表解析
#简单
[i**2 for i in range(10)]
>[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
#复合
[i**2 for i in range(10) if i % 2 ==0]
>[0, 4, 16, 36, 64]
#复合
[x * y * z for x in [2,3] for y in [5,7] for z in [11,13]]
>[110, 130, 154, 182, 165, 195, 231, 273]
元组
注意
(1,)是元组
(1)是数字
类型转换
# 集合转换元组
sets = {1,'name',(1,2,3)}
tuple(sets)
>(1, 'name', (1, 2, 3))
# 字典转元组
dic = {'name':'charls','age':20}
tuple(dic)
>('name', 'age')
#只记录keys的值
集合
集合性质
无序,唯一
用{}包括,但不能用{}初始化,要使用set()初始化
集合操作
交集 | set1 & set2 或 set1.intersection(set2) |
---|---|
并集 | set1 | set2 或 set1.union(set2) |
是否有交集 | set1.isdisjoint(set2) |
差集 | set1-set2 或 set1.difference(set2) |
是否子集 | set1 < set2 或 set1.issubset(set2) |
是否父集(超集) | set2 > set1 或 set2.issuperset(set1) |
对称差集(不同元素集合) | set1 ^ set2 或 set1.sysmmetric_difference(set2) |
set.add(item) | 增加单个元素 |
---|---|
set.update(item1,item2,item3…) | 增加多个元素 |
set.remove(item) | _ |
set.pop() | 随机删除一个 |
set.clear() | _ |
可迭代对象传入集合的时候,可迭代对象会被拆开
集合运算
- 两集合的对称差集与交集的并集=两集合的并集
- 两集合的并集与交集的差集=两集合的对称差集
字典
性质
- 键唯一,值不唯一
- 键必须是不可变类型(字符串,数字,元组),值可以是任何类型(数字,函数,类,各种结构都行)
def func1():
print(123)
def func2():
print(456)
a = {1:func1,2:func2}
print(a[1]())
>123
None
#func1输出123,返回None
查,删
dict1[key] # key不存在,会抛出异常
dict1.get(key) # key不存在,会返回None
del dict1[key] # 删除键值对
dict1.pop(key) # 删除键值对,返回删除值
属性
dict.values() | _ |
---|---|
dict.keys() | _ |
dict.items() | _ |
dict1.update(dict2),dict.copy() | 结果一样 |
dict.clear() | _ |
字典解析
a = {1:1,2:2,3:3,4:4}
b = {key:value for key,value in a.items() if value % 2 == 0}
b
>{2: 2, 4: 4}
函数
关键字传参
在函数传参的过程中,如果某一个位置以关键字传参,那么后面的位置只能以关键字传参。
def func(a,b,c):
pass
func(1,c=2,3)
func(1,b=2,3)
#都是错的
默认参数
默认参数只能位于所有未指定形参的后面
def func(a=1,b,c):
pass
func(1,2)
func(b=2,c=3)
#都是错的
不定长参数
-
元组型形参*args将所有传过来的值当作一个元组来处理
-
字典型形参**kwargs将所有传过来的值当作一个字典来处理
-
元组型形参位于一般参数后面,字典型形参位于元组型形参后面
def func(name,age,career,*args,**kwargs):
pass
func(item1,item2,item3,item4,item5,dict1,dict2,dict3)
#name=item1,age=item2,carre=item3
#args=(item4,item5)
#kwargs={dict1,dict2,dict3}
局部变量和全局变量
- 函数内部无法引用,修改全局变量
- 加上global之后才能引用,修改
a = 1
def func():
a += 1
func()
a
#错误
a = 1
def func():
global a
a += 1
func()
a
>2
函数里的函数
函数里的内部函数只能引用外部函数的变量,但是不能修改
def func():
a = 1
def func1():
print(a)
func1()
func()
>1
内部函数要想修改外部函数的变量,只能加nonlocal。内部函数可以引用全局变量,但无法修改全局变量
def func():
a = 1
def func1():
nonlocal a
a += 1
func1()
print(a)
func()
>2
闭包
- 存在函数嵌套
- 内部函数引用外部函数的变量
- 内部函数不能引用全局变量
- 外部函数的返回值必须是内部函数的函数名
def outer_func():
out = 123
def inner_func():
print(out)
return inner_func
def outer(num1,num2):
num = num1 + num2
def inner():
inner_str = '{}+{}={}'.format(num1,num2,num)
return inner_str
return inner
test = outer(1,2)
print(test())
>1+2=3
闭包特有属性
闭包都有__closure__属性,该属性返回外部函数的变量内存地址,类型为元组
如果不是闭包,则返回None
通过打印.__closure__[index].cell_contents来获取外部函数变量的值
print(test.__closure__)
print(test.__closure__[0].cell_contents)
print(test.__closure__[1].cell_contents)
print(test.__closure__[2].cell_contents)
>(<cell at 0x00000278E01E4B80: int object at 0x00007FF86A9D2760>, <cell at 0x00000278E01E4B20: int object at 0x00007FF86A9D2720>, <cell at 0x00000278E01E49D0: int object at 0x00007FF86A9D2740>)
3
1
2
return
无return的时候,默认返回None
高阶函数
把函数1的函数名作为参数传递给函数2,函数2返回函数1的函数名
import time
def get_info():
information = 'Entered show_infor'
return information
def execution(func):
start = time.time()
for i in range(1000000):
info = func()
end = time.time()
print(info)
print('Cost {:.2f}s'.format(end-start))
execution(get_info)
>Entered show_infor
Cost 0.09s
#重构execution
def execution(func):
start = time.time()
for i in range(1000000):
info = func()
end = time.time()
print(info)
print('Cost {:.2f}s'.format(end-start))
return func
#返回函数名
info = execution(get_info)
#执行函数
info()
>Entered show_infor
Cost 0.08s
'Entered show_infor'
函数装饰器@
用于装饰函数,为函数增加附加功能
1.被装饰函数无参无返回
import time
def timer(func):
def execution():
start = time.time()
func()
end = time.time()
print('Cost {:.2f}s'.format(end-start))
return (execution)
@timer
def info():
information = 'Entered info'
print(information)
info()
>Entered info
Cost 0.00s
# 1.timer(info)
# 2.返回了execution,先执行execution(),execution()可以访问外部函数的func
# 3.先访问func,后输出cost
2.被装饰函数有参有返回
import time
def timer(func):
def execution(*args,**kwargs):
start = time.time()
ret = func(*args,**kwargs)
end = time.time()
print('Cost:{:.2f}'.format(end-start))
return ret
return execution
@timer
def info(name,age):
info_str = "my name is {} and i'm {} years old".format(name,age)
print(info_str)
return ('info函数返回')
info('Charles',20)
>my name is Charles and i'm 20 years old
Cost:0.00
print(info('Charles',20))
> my name is Charles and i'm 20 years old
Cost:0.00
info函数返回
# 和1一样,最后print输出了info的返回值
3. 装饰器和被装饰函数都有参
def decorator(*dargs,**dkwargs):
def middle(func):
def inner(*args,**kwargs):
print('装饰器参数',dargs,dwargs)
print('函数参数',args,kwargs)
return func(*args,**kwargs)# func被调用了
return inner
return middle
# 一步步调用内部函数
@decorator()
def test1(name,age):
info = '{}-{}'.format(name,age)
return info
@decorator(1,2,city='shenzhen')
def test2():
print('这是测试2函数体')
return('这是测试2返回值')
@decorator('python','java',level='preliminary')
def test3(city,province,*args,**kwargs):
info = '{} in {}'.format(city,province)
print(info)
print(args)
print(kwargs)
test1('charles',20)
>装饰器参数 () {}
函数参数 ('charles', 20) {}
test2()
>装饰器参数 (1, 2) {'city': 'shenzhen'}
函数参数 () {}
这是测试2函数体
test3('shenzhen','guangdong','china',year=2100)
>装饰器参数 ('python', 'java') {'level': 'preliminary'}
函数参数 ('shenzhen', 'guangdong', 'china') {'year': 2100}
shenzhen in guangdong
('china',)
{'year': 2100}
生成器、迭代
from collections import Iterable,Iterator
可迭代对象(Iterable)
可以被循环取值的对象
- 容器:字符串,列表,字典,集合
- 生成器(generator)以及带有yield的函数
判断
isinstance(obj,Iterable)
迭代器(Iterator)
可以被next()函数调用(具有__next__()方法),可以不断返回下一个值的对象
- 所有迭代器均为可迭代对象
- 不是所有可迭代对象都是迭代器
判断
isinstance(obj,Iterator)
读取迭代器内容
- next()或__next__(),当所有值都读完再运行__next__()会抛出StopIteration异常
- for 循环
生成器(Generator)
是一种特殊的迭代器
生成器一定是迭代器
类型
- 生成器表达式(Generator Expression),类似列表生成式,只是将**[]换成了()**
- 生成器函数(Generator Function),类似函数,但函数体中带有yield。yield相当于普通函数的return,下一次读值将从上一次的yield读取
递归
-
在函数内部调用函数自身,而且有可以达成的终止条件,不是死循环
-
理论上,所有递归函数都可以写成循环的方式
-
递归最大深度是1000,超过递归上限会抛出
RuntimeError:maximum recursion depth exceeded
模块
包
要导入包,必须得带有__init__.py文件(现在不确定,我试了一下,不带init文件也能导入)
导入包路径
sys.path | 查看路径 |
---|---|
sys.path.append(path) | 路径列表追加路径 |
sys.path.insert(index,path) | 追加路径时,指定路径列表中搜索优先级 |
__file__ | 给出当前文件绝对路径(有些编译器是相对路径) |
os.path.abspath(__file__) | 绝对路径 |
os.path.dirname(__file__) | 当前文件夹的绝对路径 |
标准库
内置模块是用C语言写的 python标准库官方docs
私有方法和私有属性
名字前带有__的属性名和方法无法在外部直接访问
class Test():
def __init__(self,params):
self.__params = params
test = Test(123)
test.__params
>AttributeError: 'Test' object has no attribute '__params'
访问私有属性
- 通过类内方法传值
class Test():
def __init__(self,params):
self.__params = params
def get_params(self):
return self.__params
test = Test(123)
test.get_params()
>123
- 通过对象名._类名__私有属性名访问
class Test():
def __init__(self,params):
self.__params = params
def get_params(self):
return self.__params
test = Test(123)
test._Test__params
>123
访问私有方法
通过对象名._类名__私有方法名()访问
class Test():
def __init__(self,params):
self.__params = params
def __inner(self):
print('enter __inner')
test = Test(123)
test._Test__inner()
>enter __inner
继承
TODO:
类的方法
静态方法@staticmethod
使用函数修饰器@staticmethod
这种方法与类无关,虽然在类里,但是无法调用类的属性,而且不用self,相当于把一个函数直接缩进移到类里
调用方式
使用类名调用或者使用实例名调用
class Test():
def __init__(self):
pass
@staticmethod
def func():
print('123')
test = Test()
test.func()
Test.func()
>123
123
类方法@classmethod
使用函数修饰器@classmethod
只能调用类的属性,无法访问实例化后的属性,也就是无法访问__init__()里面的内容
class Test():
name = 'Charles'
age = 20
def __init__(self,name,age):
self.name = name
self.age = age
@classmethod
def func(self):
# 类方法的self.arg 实际上访问不到,还是会访问类的arg
print(self.name)
print(self.age)
print(Test.name)
test = Test('Bob',30)
test.func()
>Charles
20
Charles
属性方法@property
适用场景:在外部修改类属性的时候,无法同时检查值是否合理,针对改的值做出提醒
使用@property,可以将与属性名相同的方法当作属性来调用,同时添加操作
使用@attr.setter,修改属性attr的时候,调用的是被修饰的函数
@attr.deleter,删除属性attr的时候,调用的是被修饰的函数
class Person():
def __init__(self,name,age):
self.__name = name
self.__age = age
@property
def name(self):
return self.__name
@property
def age(self):
return self.__age
@name.setter
def name(self,name):
self.__name = name
@age.setter
def age(self,age):
if age < 0 or age > 100:
raise ValueError('age must in [0,100]')
else:
self.__age = age
@name.deleter
def name(self):
del self.__name
@age.deleter
def age(self):
del self.__age
pe = Person('Charles',100)
pe.name
pe.age
>'Charles'
100
pe.name = 'Bob'
pe.age = 10
pe.name
pe.age
>'Bob'
10
pe.name
del pe.name
pe.name
>'Bob'
AttributeError: 'Person' object has no attribute '_Person__name'
pe.name = 'Sam'
pe.age = -10
>ValueError: age must in [0,100]
使用stu.__dict__可以看到stu只有两个属性,{’_Person__age’: 10, ‘_Person__name’: ‘Bob’},并不是__name和__age
类的特殊成员方法
__doc__
打印描述信息
class Person():
'''
一个关于人的类
'''
def __init__(self):
pass
Person.__doc__
>'\n 一个关于人的类\n '
__module__和__class__
__module__会返回所属模块的模块名
__class__会返回所属类的类名相关信息
./hello.py
class Hello():
def __init__(self):
ret = 'hello'
./test.py
from hello import Hello
ret = Hello()
print(Hello.__module__)
print(ret.__module__)
print(Hello.__class__)
print(ret.__class__)
>hello
hello
<class 'type'>
<class 'hello.Hello'>
# class type是未实例化的类的类型,注意在这里是type类型的意思,不是class类型
__init__
实例化时自动触发
__del__
当对象在内存中释放时,自动触发
__call__
实例化后调用自动触发
class Test():
def __init__(self):
print('enter init')
def __call__(self):
print('enter call')
test = Test()
test()
test()
>enter init
enter call
enter call
__dict__
类和实例都能调用,会打印类或者实例的所有属性
class Test():
def __init__(self,name,age):
self.name = name
self.age = age
test = Test('charles',20)
Test.__dict__
test.__dict__
>mappingproxy({'__module__': '__main__',
'__init__': <function __main__.Test.__init__(self, name, age)>,
'__dict__': <attribute '__dict__' of 'Test' objects>,
'__weakref__': <attribute '__weakref__' of 'Test' objects>,
'__doc__': None})
{'name': 'charles', 'age': 20}
__str__
在打印的时候自动调用
class Test():
def __init__(self):
pass
def __str__(self):
ret = 'enter str'
return ret
test = Test()
print(test)
print(Test())
>enter str
enter str
__getitem__,__setitem__,__delitem__
__getitem__一般用来获取数据,__setitem__一般用来改变数据,__delitem__一般用来删除数据,删除后的序列数据顺位向前移动
如果将着三种方法重构一下,将这三种方法的功能互换一下,也能运行,但是强烈不建议这样做
class Test():
def __init__(self):
self.data = list(range(100))
def __getitem__(self,index):
print('进入getitem')
return (self.data[index])
def __setitem__(self,index,value):
print('进入setitem')
self.data[index] = value
def __delitem__(self,index):
print('进入delitem')
del self.data[index]
>进入getitem
15
进入setitem
100
进入delitem
进入getitem
IndexError: list index out of range
类生成过程
__new__ -> __init__ ->__call__
反射
getattr
getatrr(name,attr/method(),default)
相比于直接使用name[attr]的方法,可以判断有没有方法,而且即使属性或者方法不存在也不会报错,而是会返回默认值(如果不指定默认值,属性或者方法不存在时会报错)
a = {'name':123,'age':456}
getattr(a,'dsd',[147,258])
a['dsd']
>[147, 258]
hasattr
hasattr(实例名,属性/方法())
返回True/False
setattr
在添加属性时,功能和name[attr]=value重复
在类中添加其他类的方法
class Cat():
def __init__(self):
pass
def sleep(self):
print('sleeping')
def wake(self):
print('waking')
class Dog():
def __init__(self):
pass
cat = Cat()
dog = Dog()
setattr(dog,'sleep',cat.sleep)
setattr(dog,'wake',cat.wake)
dog.sleep()
dog.wake()
>sleeping
waking
delattr
delattr(实例名,属性名)
异常处理
try:
pass
except <code>:
pass
else:
pass
finally:
pass
执行逻辑:先执行try下的,有异常跳到except,没异常跳到else。无论有没有异常都会执行finally
- except和finally必须用一个或者都用
- 所有异常都能用Exception代替
try:
open('./data.pdf')
except IndexError as e:
print('frist assert',e)
except Exception as e:
print('万能异常',e)
else:
print('不可能进入')
finally:
print('test完毕')
>万能异常 [Errno 2] No such file or directory: './data.pdf'
test完毕
常见异常
触发异常
raise Exception('有异常')
自定义异常
class MyException(Exception):
def __init__(self,message):
self.message = message
try:
raise MyException("错误原因")
except MyException as e:
print(e)
>错误原因
IO
获取输入
message = input(‘input what you want’)
操作
-
查看变量所占内存大小
a.__sizeof__()
-
查看内建名称空间的内容
dir(obj):返回参数和方法列表
dir() >['In', 'Out', '_', '__', '___', '__builtin__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '_dh', '_i', '_i1', '_ih', '_ii', '_iii', '_oh', 'autopep8', 'exit', 'get_ipython', 'json', 'quit']
dir([]) >['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
import builtins dir(builtins)