type(1)
输出1的数据类型type(!*1.1111)
type(2/2)
得到的是一个float,type(2//2)
得到的是一个intbin(10)
bin(0o7)
bin(0xE)
int(0b11)
hex(888)
oct(0x777)
bool(11)=True
bool(0)=False
只有0才会表示boolean假,其余的所有正数或者负数都表示真bool('abc')=True
bool('')=False
bool([])=False
bool({1,2,3})=True
bool({})=False
bool(None)=False
'let 's go
出现错误,"let's go"
就没有问题,反之外单内双也是可以的let"s go
'let\'s go'
也是正确的,\ 叫做转义字符三引号输入字符串的时候可以换行
'''
hello
hello
hello
'''
三个单引号和三个双引号的效果是一样的
在字符串中 \n 表示的是回车的意思
print("""hello \n hello""")
打印出字符串,显示换行
换行输入
>>>'hello\ // 在idle中测试,输出的结果是'hello world'
world'
print('hello \\n world')
输出的结果是hello \n world,将\进行转义print(r'hello \n world')
加上一个 r 表示原始字符串,不再是一个普通字符串了,但是引号的问题没法用 r 解决"hello"+"world"
拼接字符串"hello"*3
其中乘法表示hello重复3次"hello[0]"
输出的是h,这样获取字符串中的某一个字符,数组下标"hello[-1]"
输出的是o,倒着数1次获取到的字符"hello world"[0:5]
截取到 hello ,到最后要截取的字符的下一位"hello world"[0:-1]
输出的结果是 hello worl,将d给排除掉了,负数表示步长,这里表示从0开始到字符串从末尾往回数1个字符"hello world"[6:]
不输入结尾的数字表示截取从第6开始到字符串的结尾"hello world"[-5:]
输出的是world"hello world"[:-5]
输出的是hellotype([1,2,3,4,5,6])
查看是否是列表类型[123,"hello",true]
[[1,2],[true,false]]
列表中可以嵌套列表,也就是java中的二位数组,在python中叫做嵌套列表["技能1","技能2","技能3","技能4"][1]
输出技能2,得到字符串["技能1","技能2","技能3","技能4"][0:2]
输出[“技能1”,“技能2”],得到的是一个列表["aaa","bbb"]+["ccc"]
两个列表相加得到["aaa","bbb","ccc"]
["aaa","bbb"]*3
重复三次列表中的元素["aaa","bbb","aaa","bbb","aaa","bbb"]
(1,'-1',true)
type((1,2,3))
元组是tuple类型type((1))
最后的到的结果是int型,不是tuple型,当元组的元素是一个的时候,输出的类型就是元素本身的类型,只是做了数学运算而已有序
如何定义只有一个元素的元组(1,)
,加上逗号假装后边还有
type(())
输出结果是tuple类型
str,list,tuple序列
对序列的截取叫做切片"hello world"[2:4]
序列的一些操作
3 in [1,2,3]
表示3是否在这个列表中,结果是True3 not in [1,2,3]
表示3不在这个序列中,结果是Falselen([1,2,3])
查看列表中的元素个数,结果是3max([1,2,3])
求最大元素,结果是3min([1,2,3])
求最小元素,结果是1ord('w')
查看w字母的ASCII码type({1,2,3})
输出结果set{1,1,2,2,3}
输出的结果是{1,2,3}len({1,2,3})
输出长度31 in {1,2,3}
结果True1 not in {1,2,3}
结果False{1,2,3,4,5,6} - {3,4} // 这个用到了 - 号,表示求差值
{1,2,3,4,5,6} & {3,4}
{1,2,3,4,5,6} | {3,4,7}
set()
,使用type(set())
输出setKey Value 通过Key找到Value的值,键值对
一个字典由很多的key 和 value 组成,也是集合类型的,不是序列
定义字典的方式{key1:value1,key2:value2}
type({1:1,2:2,3:3})
结果是dict
什么情况下使用字典dict
{'q':'技能1','w':'技能2','e':'技能3','r':'技能4'}
{'q':'技能1','w':'技能2','e':'技能3','r':'技能4'}['q']
通过key获取到value,输出技能1
字典中的key不能重复
字典的key键可以是字符串,也可以是数字等,字符1和数字1会识别成不一样的key,key必须是不可变的类型,如int ,str类型等是可以的,但是key不能是可变的列表类型,这只是一个例子,具体自己理解
value可以随便取值
{'q':{1:'技能1',2:'hello'},'w':'技能2','e':'技能3','r':'技能4'}
空的字典怎么表示{}
空的花括号就可以表示空的字典
A = [1,2,3,4,5,6]
其中 = 表示赋值符号,之后就可以多个变量计算A*3 + B + A
a=1
a=1,b=a,a=3
输出b结果是1,a=[1,2,3],b=a,a[0]='1'
输出b的结果是[‘1’,2,3],这个地方类似于java中的引用类型int,str,tuple(不可改变) 是值类型,list,set,dict(可变)就是引用类型
区别
a="hello"
a=a+"python"
print(a) // 输出的结果是hellopython
id(a) // 查看内存地址
id(a)
这个函数可以查看,加法之后地址发生改变,说明是一个新的字符串,没有违背不可改变的原则"python"[0]='o'
这个代码执行时错误的,因为字符串类型时不可改变的类型a=[1,2,3] // 列表
id(a) // 输出内存地址hen(id(a))使用十六进制表示内存地址
a[0]='1'
id(a) // 输出的内存地址和第一次时一样的,在同一个地址上被修改,所以时可变的
a=(1,2,3)
a[0]='1' // 代码执行出现错误,元组不可改变
b=[1,2,3]
b.append(4) // 在b列表中追加一个元素,但是对于元组时不可以追加和修改元素的
print(b)
为什么要有元组
a = (1,2,3,[1,2,3])
a[3][2] // 输出的结果时3,注意多维元组元素的获取
a[3][2]='4' // 这个时可以的,因为这个元组中改变的是列表元素,不是改变的元组
>
<
>=
<=
b=1
b+=b>=1
print(b) // 输出的结果是2,数字可以和bool相加的,bool是Number下边的一种
int(True) // 输出结果是1
'a'>'b'
结果是False,97和98,ascii码的比较
'abc'<'abd'
结果是True,ord(a)这个函数可以查询到a的ascii码
[1,2,3]<[1,2,4]
结果是True
(1,2,3)<(1,3,2)
结果是True
and(且,与)
True and True
TrueTrue and False
Falseor(或)
True or False
TrueFalse and False
Falsenot(非)
not False
Truenot True
False1 and 1 // 1
'a' and 'b' // 'b'
'a' or 'b' // 'a'
not 'a' // False
int,float取0的时候表示false,非0的时候表示的是ture
逻辑运算操作的两个类型可以用非bool类型表示,结果也可以是非bool类型,但是最终的规则就是True或者False
1 and 0 // 0
0 and 0 // 0
// 下边两个返回的结果是最后比较的那个,注意理解,涉及到计算机的解析流程
1 and 2 // 2
2 and 1 // 1
1 or 2 // 1
a=1
a in [1,2,3,4,5] // True
b=6
b not in [1,2,3] // True
b='a'
b in {'c':1} // False
b=1
b in {'c':1} // False
b='c'
b in {'c':1} // True
a=1
b=2
a is b // False
a=1
b=1
a is b // True
a=1
b=1.0
a is b // False
a == b // True 比较的是取值,1和1.0是相等的
a={1,2,3}
b={2,3,1}
a == b // True 集合是无序的
a is b // False 内存地址是不一样的
c=(1,2,3)
d=(2,1,3)
c == d // False 元组有序的
c is d // False 内存地址是不一样的
a='hello'
type(a) == str // True
isinstance(a,str)
是否是strisinstance(a,(int,str,float))
判断是否三种当中的一种&
按位与
a=2
b=3
a & b // 2,10和11按位与之后是10
|
按位或
a=2
b=3
a | b // 3,10和11按位或之后是11
^
按位异或
a=2
b=3
a ^ b // 10和11相同位值不同则为1,相同位置相同则为0
~
按位取反
a=2
~a // 10将0和1全部取反
<<
左移动
a=2
b=3
a << b // 将a转换成二进制10左移b位,后边添加b个0,最后的结果是a乘以2的b次方
>>
右移动
a=2
b=3
a >> b // 将a转换成二进制10右移b位,去掉b位,最后的结果是a除以2的b次方(取整数)
表达式Expression是运算符operator和操作数operand所构成的序列
a=1+2*3
a+2
c = int('1')+2
a=1
b=2
c = a and b or c
有优先级顺序
a or (b and c)
a or b and c 先计算b and 从,再和a计算,因为and的优先级要高于or
a + b * c
python优先级
** 指数运算(次幂)
~ + - 补码,一元加减(最后两个的方法名称是+@和-@)
* / % // 乘法 除法 取模 整除
+ -
>> << 向右向左移位
& 按位与
^
|
<= < > >= 比较运算符
<> == != 等于运算符
= %= /+ //= -= += **= 赋值运算符
is is not 身份运算符
in not in 成员运算符
not or and 逻辑运算符,and 的优先级高于 c
解析器默认的解析顺序
3+2-1
a or b and c
先计算b and c,再和a计算,c=a+b
这个就是右结合,先计算右边,有 = 号要考虑右结合c = a or b
这个也是右结合,注意理解(not a) or ((b + 2) == c)
注意优先级比较 not > and > or
以前学的是基本类型与基本概念
可以再idle中的file中写代码,ctrl+n快捷键
a=1
b=2
c=3
print('hello world')
将编写代码的文件保存成hello.py
执行hell.py
python hello.py
保存的时候要保存成.py扩展名的文件
开发工具(IDE:继承开发环境)
语句的结束可以不用机上 ;
不需要 { }区分代码,而是通过缩进的方式进行区分
if else for while 这四个都有,没有switch
单行注释:# 注释内容
使用快捷键 ctrl + /
多行注释:''' 注释内容 '''
快捷键alt + shift + a
条件控制
mood = True
if mood :
print('go to left')
print('back away')
print('没有包含在if语句中')
mood = True
if mood :
print('go to left')
else :
print('go to right')
python建议使用下划线分割两个单词组合
支持表达式的条件
a=1
b=2
c=2
if a or b +1 == c:
print('left')
else:
print('right')
简单的用户登陆
account = 'qiyue'
password = '123456'
# input() 命令行输入的函数
print('please input account:')
user_account = input()
print('please input password:')
user_password = input()
if user_account == account and user_password == password:
print('success')
else:
print('fail')
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python==3.4.0.12
解决速度问题查看规范介绍https://www.ibm.com/developerworks/cn/linux/l-cn-pylint/
安装pylint
python ez_setup.py
python get-pip.py
python -m pip install pylint
"python.linting.pylintPath": "C:/Users/安装路径/Python/Python37/Scripts/pylint.exe"
规范代码
'''
模块说明
'''
ACCOUNT = 'qiyue'
PASSWORD = '123456'
# input() 命令行输入的函数
print('please input account:')
# pylint认为不是在函数和类中定义的变量都是常量,形式常量就需要大写
user_account = input()
print('please input password:')
user_password = input()
# :前边不能有空格
# 比较运算符前边应该有空格
if ACCOUNT == user_account and PASSWORD == user_password:
print('success')
else:
print('fail')
# 程序的末尾是需要一个空行的
snippet 片段,快速构建代码的片段,其实就是代码片段的提示,是用tab键进行位置的跳转
if 可以单独的使用,可以不用配合else
pass 是空语句,占位语句
if True:
pass # 如果没有写pass,空着的话就会报错
区分if else或者if的结构体
嵌套分支
if condition:
if condition:
pass
else:
pass
else:
if condition:
pass
else:
pass
伪代码和代码块(code1、code2),代码块中同一级别的一行代码被执行,所有的代码都会被执行,注意理解
if condition:
code1
code2
else:
pass
python中没有goto关键字的用法
养成号的代码封装成函数的习惯,特别是在分支结构中的使用
缩进相同的代码属于同一个代码块
a = 1
if a == 2:
print('2')
elif a == 1:
print('1')
else:
print('other')
解决分支的问题和代码的简洁,python中没有switch,官方提倡使用字典的方式代替别的语言中的switch
input()接受到的是字符串,所以在比较数字的时候可能出现问题
a = input()
a = int(a) # 通过转换将输入的字符串转变成数字整型
注意各种语言的缺点,有点和缺点的理解
如何写出优美得代码
a = 1
b = 0
# a 和 b不可能同时位False
a or b # 这里使用 or 比使用 if else 更加的好
解决问题的思维模式
while和for
while
CONDITION = True
while CONDITION:
print('i am while')
condition = 0
while condition <= 10:
print(condition)
condition += 1
else:
print('EOF')
在使用递归的场景下边使用while的时候比较多
代码结构
for target_list in expression_list:
pass
for主要用来遍历或者循环序列、集合、字典的元素
a = [['apple','orange','banana','grape'],(1,2,3)]
for x in a:
for y in x:
print(y)
print(y,end='')
# 如果不想换行打印,需要添加一个end=’'参数for 也可以和else结合使用,当遍历完成之后执行else
跳出循环
a = [1,2,3]
for x in a:
if x == 2:
break
print(x)
跳过当前循环
a = [1,2,3]
for x in a:
if x == 2:
continue
print(x)
for循环中加入了break之后就不会执行后边的else了,continue是会执行else的
a = [1,2,3]
for x in a:
if x == 2:
break
print(x)
else:
print('end')
在嵌套的循环中使用break,跳出的只是内部嵌套的循环,而外部的循环还在执行,外部循环执行结束之后还会去执行else语句
类似于其他语言中的for中的i++
# 表示的是0到9,从0开始10个偏移量
for x in range(0,10):
print(x)
输出0,2,4,6,8有2的相差,递增的等差数列
for x in range(0,10,2):
print(x)
以行的方式打印出来,同时使用 | 分割开来
for x in range(0,10,2):
print(x,end=' | ')
递减的等差数列
for x in range(10,0,-2):
print(x,end=' | ')
对于一个列表打印出相差的间隔元素出来
for x in range(10,0,-2):
print(x,end=' | ')
比for循环更简单的取有间隔的元素
a = [1,2,3,4,5,6,7,8]
b = a[0:len(a):2] # 2表示的是间隔
for x in range(0,len(b)):
print(b[x],end=' | ')
_init_.py
,这个文件夹就是一个包了讲公用或者重复的东西提取到一个模块当中,其他模块中去引用就行了
导入,引入的时候要遵循先后顺序
import module_name // 在一个模块中定义变量,另外一个模块中引入这个模块,必须注意顺序
print(module_name.变量) // 引入之后使用变量
import只能引入模块
import t.c7 as m // 重命名 命名空间
print(m.a)
from module import a,def
// 引入变量或者函数
from t.c7 import a // 从t.c7中引入a这个变量
print(a)
引入模块
from t import c7
print(c7.a)
引入多个变量
a=1 // t文件夹下的c7.py文件中定义三个变量
b=2
c=3
from t.c7 import *
print(a)
print(b)
print(c)
导入指定的变量 a、b
_all_ = ['a','b'] // 被称为模块的内置属性,变量
a=1 // t文件夹下的c7.py文件中定义三个变量
b=2
c=3
from t.c7 import *
print(a)
print(b)
print(c) // 打印c的时候报错,因为c没有被引入
_init_.py
的用法在vscode中排除显示一些文件 files.exclude,将其中的pycache设置成true,缓存文件夹就不显示了
引入变量
from c9 import a,b,c
加入需要导入的变量特别多,解决换行的方法 \,不推荐
from c9 import a,b,\
c
加上括号换行
from c9 import (a,b,
c)
init 文件
a = 'this is a init file'
print(a)
import t // 引入这个包就可以了,执行c11.py这个文件的时候就会自动的去执行 init 文件中的代码
说明:无论是导入的包还是包下边的模块,init 文件中的代码都会运行
在模块中使用 _all_
可以决定哪些变量被导出,在 init 文件中可以使用_all_
决定包中的哪些模块被导出,以下是限制只能导出 c7 这个模块的 init 文件代码
_all_ = ['c7'] // init 文件代码
from t import * // 将t包下的所有模块导入
print(c7.a)
print(c8.a) // 因为限制了c7可以导出,所以 c8 会报错
批量的导入多个模块可以在 init 文件中导入,然后在别的模块导入包就行了
import sys // init 文件中导入多个模块
import io
import t // 在别的模块中导入包 t 就可以使用这些模块了
print(t.sys.path)
模块只是视作文件,不是真实的文件
a=1
b=2
c=3
infos = dir() // dir 函数就是打印出这个模块中的变量的
print(infos)
关注带有下划线的变量,这些都是系统定义好的内置的变量
'''
this is a doc
'''
print('name:'+__name__)
print('package:'+__package__)
print('doc:'+__doc__)
print('file:'+__file__)
'''
this is a doc
'''
print('name:'+__name__)
print('package:'+ (__package__ or '当前模块不属于任何包'))
print('doc:'+__doc__)
print('file:'+__file__)
注意入口文件和普通模块的内置变量的比较,这两者是不一样的
_name_
的经典应用dir 函数的用法
import sys
infos = dir(sys)
print(infos)
_name_
让这个模块脚本文件不仅可以被其他模块调用,还可以自己单独执行,再代码的逻辑处理上要有一定的处理
if __name__ == '__main__':
print('作为一个入口文件')
print('this is a module')
python -m 命名空间.module.py
通过参数 -m 将一个可执行的文件当作一个模块来执行,但是这个文件必须是属于模块身份的,即在包的下边
注意什么是顶级包,根据可执行文件的路径有关系
绝对路径:从顶级包一直往下找
相对路径: . 当前目录 … 上上级目录 … 上上上级目录
import不能使用相对导入
from .module import b
相对导入
from .package2.package4.m2 import m
引入超过顶级包的包会报错,入口文件没有包
入口文件中不能使用相对路径导入包
在入口文件的上一级将入口文件作为模块运行
python -m demo.main.py // 在demo的上一级目录运行这个目录
a = 1.12386
result = round(a,2) // 保留小数点后两位,能进行四舍五入,round是内置函数
help(round)
查看内置函数,输入import this
会出现一些优美的语句def funcname(parameter_list): // def 关键字,参数名称,参数列表
pass // 空语句函数体,注意缩进
def add(x,y):
result = x + y
return result
def print_code(code):
print(code)
a =add(1,2) // 调用函数,参数的顺序和取值
b = print_code('python')
print(a,b) // print可以传递多个参数,只要是需要打印的东西就可以
// 执行的结果是,注意理解代码执行的顺序
python
3 None
import sys
sys.setrecursionlimit(100000) // 设置自己的允许的递归长度
def damage(skill1,skill2):
damage1 = skill1 *3
damage2 = skill2 * 5
return damage1,damage2
damages = damage(3,4)
print(type(damages)) // 返回的类型是元组tuple
print(damages)
如何使用元组类型的返回结果?
print(damages[0],damages[1]) // 通过下标获取元组的元素,但是这种方式不好
# 推荐的获取返回结果的方法
skill1_damage,skill2_damage = damages(3,4) // 两个变量接受两个返回结果
print(skill1_damage,skill2_damage)
a = 1
b = 2
c = 3
# 三行的代码可以使用这样一行替换
a,b,c = 1,2,3
d = 1,2,3
print(type(d)) // 结果是 tuple
序列解包就是将tuple分拆成单独的值
d = 1,2,3
print(type(d)) // 结果是 tuple
a,b,c = d // 这样就实现了tuple的拆分,也就是序列解
补充
a = 1
b = 1
c = 1
a,b,c = 1,1,1
a = b = c = 1
必须参数
def damage(skill1,skill2):
damage1 = skill1 *3
damage2 = skill2 * 5
return damage1,damage2
damages = damage(3,4) // 两个参数都要传递
关键字参数(不用考虑参数传递的顺序),明确告诉实参是给那个形参使用的
def add(x,y):
result = x + y
return result
c = add(y=3, x=2) // 明确指定实参和形参对应,可以不用考虑传递的顺序了
必须参数和关键字参数的区别是在函数的调用上
可以让参数有一个默认的值
def print_students_files(name,gender='男',age=18,college='人民小学'):
print('我叫' + name)
print('今年' + str(age))
print('我是' + gender)
print('我在' + college)
print_students_files('名字') // 调用有默认参数的函数
print_students_files('名字','女') // 调用有默认参数的函数,对不需要的默认参数传值
默认参数的坑
print('a','b','c')
这样的调用就是可变参数
定义一个拥有可变参数的函数
def demo(*param): // *parame可变参数列表
print(param)
print(type(param))
demo(1,2,3,4)
def demo(param):
print(param)
print(type(param))
demo((1,2,3,4)) // 自己组装
可变参数的特性
def demo(*param): // *parame可变参数列表
print(param)
print(type(param))
a = (1,2,3,4)
demo(*a) // 使用 *a 就是解包作用,将元素平铺出来作为参数传递
def demo(param1,*param,param2=2): // 必须参数,*parame可变参数列表, 默认参数
print(param1)
print(param)
print(param2)
demo('a', 1,2,3 ,param2 = 'param') // 在调用的时候将默认参数采用关键字参数的方式进行值得传递
再定义函数的时候保证形参列表的简单
编写一个求平方和的函数
def squsum(*param):
sum = 0
for i in param:
sum += i*i
print(sum)
squsum(1,2,3)
任意个数的关键字参数
def city_temp(**param):
print(param)
for key,value in param.items(): // 这样就能遍历字典
print(key,':',value)
print(type(param)) // 结果是 字典dict
city_temp(bj='32',xm='45',sh='31')
a = {'bj':'32','xm':'45'}
city_temp(**a) // 传入字典dict
city_temp() // 如果什么都不传递的话就是传递的空的字典
a=''
,之后在函数的内部对值进行引用,其实就是使用全局变量全局变量不仅仅只是作用域模块中的,可以在整个应用程序中都能引用
局部变量很容易覆盖全局变量
将局部变量变成全局变量
关键字global
def demo():
global c
c = 2
demo() // 至少要先调用一下函数,后边才能打印 c
print(c)
通过global定义的全局变量可以在整个应用程序中进行使用
python没有代码块作用域
类 = 面向对象
关键字 class
类的命名规则
StudentName
,区别变量名字的命名类中可以定义若干个变量
类中可以定义函数
类的实例化以及使用
class Student():
name = ''
age = 0
def print_file(self): // 必须加上固定的关键字
print('name:' + self.name) // 调用类中的变量需要使用self这个参数
print('age:' + str(self.age))
student = Student()
student.print_file()
总结
在另外一个模块中去调用定义好的类
from c1 import Student
student = Student()
student.print_file()
id(?)
查看内存地址
构造函数_init_
class Student():
name = ''
age = 0
def _init_(self): // 构造函数
pass
def print_file(self): // 必须加上固定的关键字
print('name:' + self.name) // 调用类中的变量需要使用self这个参数
print('age:' + str(self.age))
student = Student()
student.print_file()
a = student._init_()
print(type(a)) // 如果显示的调用构造函数就和一般的方法没有什么区别了
构造函数的作用
class Student():
name = ''
age = 0
def _init_(self,name,age): // 构造函数
name = name
age = age
student = Student('name',18) // 这样就类似于在直接调用构造函数_init_
print(student.name,str(student.age)) // 访问对象的属性,结果什么都没有,因为有局部变量的作用域有关系
类变量和类关联在一起
实例变量和实例关联在一起的
保存对象的特征值(定义实例变量),区别类变量的定义,self可以随便起名字
class Student():
name = 'qiyue' // 定义类变量
age = 0
def _init_(self,name,age): // 构造函数
self.name = name // 定义实例变量
self.age = age
student = Student('name',18) // 这样就类似于在直接调用构造函数_init_
print(Student.name,str(Student.age)) // 类的变量
print(student.name,str(student.age)) // 访问对象的属性
类抽象,对象具体
python易于上手难于精通的语言
查看实例对象中的变量
student = Student()
print(student.__dict__) // 实例对象
print(Student.__dict__) // 类
访问实例变量的变量的时候,先去实例中查找,如果没有查找到,就会去类中去找
class Student():
sum = 0
def _init_(self,name,age): // 构造函数
self.name = name // 定义实例变量
self.age = age
print(self.name,self.age) // 实例方法中访问实例变量
self.__class__.sum += 1
print('创建对象的个数:' + self.__class__.sum) // 实例方法中访问类变量
student = Student('name',18) // 这样就类似于在直接调用构造函数_init_
self.变量名
Student.name
,在实例方法中访问类变量也是Student.name
self.__class__.name
如何定义一个类方法@classmethod
,这个是装饰器,类方法操作类变量
class Student():
sum = 0
def _init_(self,name,age):
self.name = name
self.age = age
#self.__class__.sum += 1
#print('当前班级学生人数:' + str(self.__class__.sum))
def do_homework(self):
print('homework')
@classmethod // 增加了这个装饰器,这个方法就称为了类方法
def plus_sum(cls):
cls.sum += 1 // 操作类变量
print(cls.sum)
student = Student()
student.do_homework()
Student.plus_sum()
类方法和实例方法的区别
调用类方法
类名.类方法
:Student.plus_sum()
静态方法的调用@staticmethod
装饰器的使用
class Student():
sum = 0
def _init_(self,name,age):
self.name = name
self.age = age
#self.__class__.sum += 1
#print('当前班级学生人数:' + str(self.__class__.sum))
def do_homework(self):
print('homework')
@classmethod // 增加了这个装饰器,这个方法就称为了类方法
def plus_sum(cls):
cls.sum += 1 // 操作类变量
print(cls.sum)
@staticmethod // 装饰器指定静态方法
def add(x,y): // 不需要传递过来一个self或者cls
print(Student.sum) // 静态方法调用类变量
print('static method')
student = Student()
student.do_homework()
Student.plus_sum()
Student.add(1,2)
student.add(2,4)
和实例方法和类方法的区别
静态方法和类方法访问实例变量要报错
不要经常使用静态方法,和面向对象没有太大联系
外部的调用就是在类的外边调用类中的方法
内部调用就是在类的内部,方法之间的调用
class Student():
sum = 0
def _init_(self,name,age):
self.name = name
self.age = age
def do_homework(self):
print('homework')
self.do_chinese_homework() // 内部调用
def do_chinese_homework(self):
print('chinese homework')
student = Student()
student.do_homework() // 外部调用
安全正确的操作内部变量,通过方法操作实例变量是安全的
class Student():
sum = 0
def _init_(self,name,age):
self.name = name
self.age = age
self.score = 0
def marking(self,score): // 通过方法操作类内部的变量
if(score < 0):
self.score = 0
self.score = score
print(str(self.score))
student = Student()
student.marking(33)
所有类下边的变量的更改通过方法的方式进行修改,不要直接调用,因为可以在方法中对数据进行一定的保护
阻止类的外部直接访问变量,
公开的public,外部可以直接访问,
私有的private,外部无法访问,双下划线 _ _
,变量名或者方法名字前边加上双下划线就可以成为私有的了
class Student():
sum = 0
def _init_(self,name,age): // 构造函数是特有的函数,有了双下滑线 _ _ 也可以松外部访问
self.name = name
self.age = age
self.__score = 0 // 变成了私有变量
def __marking(self,score): // 双下划线__定义私有方法
if(score < 0):
self.__score = 0
self.__score = score
print(str(self.__score))
student = Student()
student.__marking(33) // 变成了私有的了,无法访问
student.__score = -1 // 不会报错
类似于构造函数__init__
这种下划线开始和下划线结束的函数,python不会认为是私有的,只有在开始的时候使用了下划线才会是私有的__marking
上边调用私有方法就会报错,但是访问私有变量__score没有报错,是为什么呢?
student.__score = -1
由于动态语言的特性,这里属于给student新添加了一个实例变量,这里有赋值所以没出错,但是这里的__score
和原来的__score
是不一样的接着上边如果是以下的代码就会报错
stu = Student()
print(str.__socre) // 这里没有赋值,所以这是去访问原来的私有变量,无法访问报错
私有变量加上下划线之后,使用Student.__dict__
查看之后,出现了**_Student__score**,这就是私有的了,python对私有的变量进行了更改,属于对私有变量的保护,可以通过student._Student__score
对私有变量进行访问
避免定义重复的方法和变量
代码示例(建议一个模块一个类)
# 模块 c6.py
class Human():
sum = 0
def __init__(self,name,age):
self.name = name
self.age = age
def get_name(self):
print(self.name)
# 模块 c5.py
form c6 import People
class Student(Human): // 继承:Peopel是弗雷,Student是子类
def __init__(self,school,name,age):
self.school = school
Human.__init__(self,name,age) // 显示的调用父类的构造函数,需要传递 self,只是普通方法调用的方式
def do_something(self):
print('do something')
student = Student('小学','xiao lei',23)
pirnt(student.sum) // 0
pirnt(student.name) // xiao lei
pirnt(student.age) // 23
pirnt(Student.sum) // 0
pirnt(student.get_name) // xiao lei
父类
在python中是允许一个子类可以有多个父类
上一节中子类调用父类的构造函数的手段不是太好
通过类名调用方法Student.do_something(student)
,这样调用可以,但是不太好知道吗,self 变成了一个普普通通的参数
使用super调用父类的方法,以后优先使用super
# 模块 c6.py
class Human():
sum = 0
def __init__(self,name,age):
self.name = name
self.age = age
def get_name(self):
print(self.name)
def do_something(self):
print('do something 父类')
''' '''
# 模块 c5.py
form c6 import People
class Student(Human): // 继承:Peopel是弗雷,Student是子类
def __init__(self,school,name,age):
self.school = school
super(Student, self).__init__(name,age) // 通过super关键字调用父类的方法
def do_something(self):
super(Student, self).do_something() // 子类的方法中调用父类的方法
print('do something 子类')
student = Student('小学','xiao lei',23)
pirnt(student.sum) // 0
pirnt(student.name) // xiao lei
pirnt(student.age) // 23
pirnt(Student.sum) // 0
pirnt(student.get_name) // xiao lei
student.do_something()
# do something 父类
# do something 子类
定义:是一个特殊的字符序列,一个字符串是否与我们所设定的字符序列相匹配
快速检索文本,实现一些替换文本的操作
用途举例
使用(优先使用内置函数)
检查是否包含了Python
a = 'C|C++|Java|Python'
a.index('Python') > -1 // True 使用python的内置函数
print('Python' in a) // True, in 操作符也能判断
re 模块操作内置函数
import re
a = 'C|C++|Java|Python'
r = re.findall('Python',a) // 在a中搜索Python,返回的是列表list的形式
if len(r) > 0:
print('字符串中包含了 Python')
else:
print('not found')
正则表达式的灵魂在于规则
提取数字
import re
a = 'C6C++2Java3Python'
r = re.findall('\d',a) // \d 表示数字
print(r) // ['6','2','3']
'Python'
普通字符,'\d'
元字符,正则表达式是由元字符来表示
元字符:百度百科正则表达式可以查看,分析业务需求再找单个的意义,最后组合起来
找出中间是c或者是f的单词,字符集用中括号包含 [ ]
import re
s = 'abc,acc,cdc,aec,afc,ahc'
r = re.findall('a[cf]c',s)
print(r)
找出中间不是c或者不是f的单词
import re
s = 'abc,acc,cdc,aec,afc,ahc'
r = re.findall('a[^cf]c',s) // ^ 表示取反的意思
print(r)
匹配中间是c到f
import re
s = 'abc,acc,cdc,aec,afc,ahc'
r = re.findall('a[c-f]c',s) // - 表示c到f
print(r)
\d
就是一个概括字符集,表示所有的阿拉伯数字0到9,\D
非数字\d
=[0-9]
,\D
=[^0-9]
\w
字母和数字和下划线等字符,相当于[A-Za-z0-9_]
\W
匹配非单词字符\s
匹配['','\t','\n','r']
等这一类空白字符,\S
非空白字符匹配单词,数量词表示单个字符的数量
import re
s = 'python 111java 3434php'
r = re.findall('[a-z]{3,6}',s) // 匹配字符长度是3到6的单词,3,4,5,6个的都可以
print(r)
r = re.findall('[a-z]{3,6}?',s)
,这样就 pyt 结束,然后 hon 就这样匹配下去python*
表示匹配0次或者无限多次 ***** 号前边的字符npython+
表示匹配1次或者无限多次 ***** 号前边的字符n,就是至少出现一次python?
表示匹配10次或者无限多1次 ***** 号前边的字符n,用来去重复比较好用^
从字符串的开始匹配,$
从字符串的末尾开始匹配,这两个字符一前一后
验证qq号,4到8位之间
import re
qq = '100007891'
r = re.findall('^\d{4,8}$',qq) // ^ 开始 $ 结束
print(r)
判断是否包含3个python
import re
qq = 'pythonpythonpythonpython'
r = re.findall('(python){3})',qq) // () 括号就是一个组
print(r)
[]
或关系和()
且关系,区分开
re.findall(param1,parame,param3)
param3是匹配模式
忽略大小写
import re
qq = 'pythonC#pythonpythonpython'
r = re.findall('c#',qq,re.I) // re.I 就是一种忽略大小写的模式
print(r)
多个模式的使用r = re.findall('c#',qq,re.I | re.S)
,| 在这里表示且的关系,其中re.S就是指明.
号可以匹配所有的字符包括换行符\n
import re
qq = 'pythonC#\npythonpythonpython'
r = re.findall('c#.{1}',qq,re.I | re.S) // C#\n 会被匹配到
print(r)
.
匹配除换行符 \n
之外的其他字符
字符串的替换r = re.sub(正则表达式,替换成的字符串,搜索的源字符串,最大的替换次数,匹配模式)
将C#替换成Go
import re
qq = 'pythonC#\npythonpythonpython'
r = re.sub('C#','Go',qq,1) // 替换一次 C#
print(r)
lan = qq.replace('C#','Go') // 新生成的 lan
print(lan)
sub强大的地方是第二个参数可以是一个函数,将函数作为参数
import re
qq = 'pythonC#\npythonpythonpython'
# 这个value是object对象,告诉的是匹配到的字符串在源字符串中的位置,span=(6,8)表示前边有6个字符,从第7个开始到8是匹配的字符
def convert(value):
matched = value.group() // 获取到匹配到的字符串
return '!!' +mathced+ '!!' // 被动态替换
r = re.sub('C#',convert,qq,1) // 将匹配到的结果作为convert的参数传递过去,返回结果作为替换
print(r)
找出字符串中的所有数字,将大于等于6的数字替换成9,小于6替换成0
import re
s = 'A8C3721D86'
def convert(value):
matched = value.group()
if int(matched) >= 6: // 将字符转换成数字
return '9' // 返回的替换值必须是字符串形式
else:
return '0'
r = re.sub('\d',convert,s)
print(r)
函数做参数,处理过程很灵活
这两个函数匹配成功一个就立刻停止了
match从字符串的首字母开始匹配
import re
s = 'A8C3721D86'
# 找到所有的数字
r = re.match('\d',s)
print(r.span) // 返回位置
print(r) // 开始不是数字,返回空
search搜索整个字符串,返回搜索到的位置object对象
import re
s = 'A8C3721D86'
# 找到所有的数字
r = re.search('\d',s)
print(r.group) // 8
print(r) // 第一个数字是8,返回结果object:span=(0,1) ...
分组的概念
提取life和python之间的字符和两个python之间的字符串
import re
s = 'life is short,i use python,i love python'
r = re.search('life(.*)python(.*)python',s) // 结果有两个分组
print(r.group(0)) // 0 是组号,默认是 0,始终记录的是完整的匹配结果
# life is short,i use python,i love python
print(r.group(1)) // 正式获取组需要从 1 开始
# is short,i use
print(rr.group(2))
# ,i love
print(r.group(0,1,2))
# ('life is short,i use python,i love python','is short,i use',',i love')
print(r.groups()) // 只有中间匹配的结果,没有完整的了
# ('is short,i use',',i love')
rr = re.findall('life(.*)python',s) // 这里的结果也是组中的结果
print(rr)
# ['is short,i use']
什么是JSON:JavaScript Object Notation,JavaScript对象标记
本质:是一种轻量级的数据交换格式
字符串是JSON的表现形式
符合JSON格式的字符串叫JSON字符串(载体)
JSON VS XML
JSON的优势
XML
<note>
<to>Toveto>
<from>Janifrom>
<heading>Reminderheading>
<body>
Dont forget me this weekend!
body>
note>
JSON应用场景
json字符串转换成python数据结构
import json
json_str = '{"name":"qiyue","age":18}' // 符合json规范的字符串
student = json.loads(json_str) // 转换
print(type(student)) // dict 字典类型
print(student['name']) // 访问得到数据
不同的语言把json解析成不同的数据结构,如javascript中是对象,python中是字典dict也可能是别的,针对json数据的结构
json 小写的 false 解析成大写的 False
json和python的解析
json | python |
---|---|
object | dict |
array | list |
string | str |
number | int |
number | float |
true | True |
false | False |
null | None |
序列化就是转换成json格式的数据
import json
student = {
{'name':'xiao hua','age':11},
{'name':'xiao lei','age':12}
}
json_str = json.dumps(student)
print(type(json_str))
print(json_str)
枚举的本质是一个类,python中的枚举是Enum的子类
from enum import Enum
class VIP(Enum): // 继承Enum类
YELLOW = 1
GREEN = 2
BLACK = 3
RED =4
print(VIP.YELLOW) // VIP.YELLOW 打印出的结果和普通的类是有区别的
没有枚举怎么表示(最大的缺陷就是可变、没有防止相同标签的功能)
yellow = 1
green = 2
# dict
a = {'yellow':1,'green':2}
class TypeDiamond():
yellow = 1
green = 2
枚举特点
获取枚举具体的数值.value属性
.name获取得到标签的名字
from enum import Enum
class VIP(Enum): // 继承Enum类
YELLOW = 1
GREEN = 2
BLACK = 3
RED =4
print(VIP.YELLOW) // VIP.YELLOW 打印出的结果和普通的类是有区别的
print(VIP.YELLOW.value) // 通过.value访问得到具体的值 1
print(VIP.YELLOW.name) // 通过.name访问得到标签的名字 YELLOW
# 通过type()查看得到类型
print(VIP['GREEN']) // VIP.GREEN 打印枚举本身
注意:
枚举的遍历
from enum import Enum
class VIP(Enum): // 继承Enum类
YELLOW = 1
GREEN = 2
BLACK = 3
RED =4
for v in VIP:
print(v) // 通过遍历获取到枚举下边每一种类型
支持的比较
不支持的比较
from enum import Enum
class VIP(Enum): // 继承Enum类
YELLOW = 1
YELLOW_ALIAS = 1 // 只是YELLOW的别名,不能代表独立的枚举类型
GREEN = 2
BLACK = 3
RED =4
result = VIP.YELLOW == VIP.GREEN // 等值比较
result = VIP.YELLOW is VIP.YELLOW // 身份比较
不能出现相同的标签
允许不同标签的数值相同,第二个标签只是第一个标签的别名
有相同值得时候遍历不会打印别名
需要打印别名得遍历
from enum import Enum
class VIP(Enum): // 继承Enum类
YELLOW = 1
YELLOW_ALIAS = 1 // 只是YELLOW的别名,不能代表独立的枚举类型
GREEN = 2
BLACK = 3
RED =4
for v in VIP.__members__:
print(v) // 得到所有标签得名字,包括别名
for v in VIP.__members__.items():
print(v) // 通过遍历获取到枚举下边每一个类型,得到得结果是元组(标签名称,取值)
理解可读性
from enum import Enum
class VIP(Enum): // 继承Enum类
YELLOW = 1
GREEN = 2
BLACK = 3
RED =4
a = 1
print(VIP(a)) // VIP.YELLOW 获取得到枚举的类型
IntEnum 强制枚举下边全部是数字
from enum import IntEnum
class VIP(IntEnum): // 继承IntEnum类
YELLOW = 1
GREEN = 2
BLACK = 3
RED =4
限制枚举的值不能相同
from enum import IntEnum,unique
@unique
class VIP(IntEnum): // 继承IntEnum类
YELLOW = 1
GREEN = 1
BLACK = 3
RED =4
# 运行程序之后就会报错,因为YELLOW和GREEN的值相同了
枚举实现是单例模式,不能对枚举进行实例化
了解23种设计模式
淡化函数式编程
函数
其他语言
python一切皆对象(结构)
a = 1 // 赋值的类型不指定
a = '2'
a = def
闭包的概念和作用域有关
函数的作用域
def curve_pre():
a = 25 // 环境变量
def cureve(x):
return a*x*x
return cureve // 函数作为返回结果
a = 10
f = curve_pre() // 函数赋值给变量
f(2) // 100
闭包
f.__closure__
内置的变量里边的f.__closure__[0].cell_contents
闭包的意义保存的是一个环境,函数调用的现场保存下来了,环境变量在函数中只能用于引用,而不能去赋值
def f1():
a = 10
def f2():
a = 20 // 这个语句的存在,此时的a不是去引用外部的环境变量,而是一个局部变量,所以这不是闭包
print(a)
print(a)
f2()
print(a)
f1()
# 10
# 20
# 10
以上代码不是闭包
def f1():
a = 10
def f2():
a = 20 // 这个语句的存在,此时的a不是去引用外部的环境变量,而是一个局部变量,所以这不是闭包
return c = 20 * a // 环境变量只能被引用不能被赋值
return f2
f = f1()
print(f.__closure__)
不用闭包
origin = 0
def go(step):
gobal origin // 进行全局声明,没有全局声明就会报错
new_pos = origin + step
origin = new_pos
return origin
# 预期结果
print(go(2)) // 2
print(go(3)) // 5
print(go(6)) // 11
闭包实现(函数式编程)
origin = 0
def factory(pos):
def go(step):
nonlocal pos // nonlocal 强制声明pos不是本地的局部变量
new_pos = pos + step
pos = new_pos
return new_pos
return go
tourist = factory(origin)
print(tourist(2))
print(tourist(3))
print(tourist(5))
# 2 5 10
print(tourist.__closure__[0].cell_contents) // 打印闭包的环境变量
闭包记忆住了上一次调用的状态
强调函数
匿名函数:在定义函数的时候不需要定义函数名字
# 普通函数
def add(x,y):
return x+y
# 匿名函数
lambda parameter_list: expression // expression只是简单的表达式
# 没有名字,没有参数列表,没有return,:后边的表达式作为返回结果
f = lambda x,y: x+y // 将匿名函数赋值给一个变量
a = f(1,2)
print(a)
lambda定义的函数——> lambda 表达式
表达式版本的if else 语句
题目:x,y中 x>y取x 否则取y
其他语言
x > y ? x : y
python版本
# 伪代码
条件为真时返回的结果 if 条件判断 else 条件为假时返回的结果
x = 2
y = 1
r = x if x > y else y
print(r) // 2
也是推荐的函数式编程的方式,有列表x的值,求y的值
list_x = [1,2,3,4,5,6,7,8]
def square(x):
return x*x
for x in list_x:
square(x)
list_x = [1,2,3,4,5,6,7,8]
def square(x):
return x*x
r = map(square,list_x) // 对每一个x传到square函数中去
print(r) // map object
print(list(r)) // 将map对象转换成list
map真正的使用方式,结合lambda表达式使用
list_x = [1,2,3,4,5,6,7,8]
list_y = [2,2,2,3,4,1,2,4]
r = map(lambda x,y: x*x+y, list_x, list_y) // 使用lambda替换square函数
print(r) // map object
print(list(r)) // 将map对象转换成list
导入reducefrom functools import reduce
reduce的使用
from functools import reduce
list_x = [1,2,3,4,5,6,7,8]
r = reduce(lambda x,y: x+y, list_x)
print(r)
m = reduce(lambda x,y: x+y, list_x, 10) // 第三个参数10是作为初始值,计算第一次就是10+1,第二次计算11+2
print(r)
(((1+2)+3)+4)...
reduce做连续计算,连续调用lambda表达式
map/reduce编程模型 (映射、归约),大数据中的并行计算
过滤
lambda 表达式返回的结果必须是能代表True或者False的,
filter通过返回的boolean值决定元素是否还被保留在集合里
list_x = [1,0,0,1,1,0]
r = filter(lambda x: True if x ==1 else False, list_x)
print(list(r)) // [1,1,1]
m = filter(lambda x: x, list_x)
print(list(m)) // [1,1,1]
装饰器就是java中的注解
import time
def f1():
print(time.time())
print('this is a function')
# unix 时间戳
f1()
如果有很多函数需要打印时间怎么办?解决这个问题,专门编写一个函数打印时间
import time
def print_current_tiem(func):
print(time.time())
func()
def f1():
print('this is a function')
def f2():
print('this is a function')
print_current_tiem(f1)
print_current_tiem(f2)
对修改时封闭的,对扩展是开放的(原则)
unix 时间戳
装饰器只是一种模式
import time
def decorator(func): // 装饰
def wrapper(): // 封装
print(time.time())
func()
return wapper
def f1():
print('this is f1')
f = decorator(f1)
f()
语法糖 @ 真正体现了装饰器
import time
def decorator(func): // 装饰
def wrapper(): // 封装
print(time.time())
func()
return wapper
@decorator // 使用语法糖 @,保证原来的调用不变
def f1():
print('this is f1')
f()
ES6中可以只用class定义javascript类
支持一个参数的装饰器
import time
def decorator(func): // 装饰
def wrapper(func_name): // 封装
print(time.time())
func(func_name)
return wapper
@decorator // 使用语法糖 @,保证原来的调用不变
def f1(func_name):
print('this is f1' + func_name)
f1('test')
支持多个参数的装饰器
import time
def decorator(func): // 装饰
def wrapper(*args): // 参数列表
print(time.time())
func(*args)
return wapper
@decorator // 使用语法糖 @,保证原来的调用不变
def f1(func_name):
print('this is f1' + func_name)
@decorator
def f2(func_name1,func_name2):
print('this is f1' + func_name1 +':'+ func_name2)
f1('test')
f2('test1','test2')
优化
import time
def decorator(func): // 装饰
def wrapper(*args, **kw): // 参数列表
print(time.time())
func(*args, **kw)
return wapper
@decorator
def f2(func_name1,func_name2,**kw): // ** 表示任意个关键字参数
print('this is f1' + func_name1 +':'+ func_name2)
print(kw)
f2('test1','test2', a=1,b=2,c='123')
装饰器的基本思想通过装饰器改变函数的行为,而不去改变实现
装饰器体现了代码的复用,不需要破坏代码的实现
代码欣赏
# 使用flask框架
@api.route('/get',methods=['GET'])
def test_javascript_http():
p = request.args.get('name')
return p,200
@api.route('/psw',methods=['GET'])
@auth.login_required
def get_psw():
p = request.args.get('psw')
r = generate_password_hash(p)
return 'aaaaaa',200
...
...
主播姓名40.5万
观看人数root_parttern = '([\s\S]*?)'
name_pattern = '([\s\S]*?)'
名字number_pattern = '([\s\S]*?)'
人数sorted(需要排序的立标, key = 指定的排序关键字, reverse = 是否将顺序反转)
'''
模块注释:爬虫例子
'''
import re
from urllib import request
class Spider():
'''
类注释:爬虫类
'''
# 网页
url = 'https://www.panda.tv/cate/lol'
'''
爬取的位置匹配
'''
root_parttern = '([\s\S]*?)'
name_pattern = '([\s\S]*?)'
number_pattern = '([\s\S]*?)'
def __fetch_content(self):
'''
方法的注释:爬取网页
'''
r = request.urlopen(Spider.url)
htmls = r.read()
htmls = str(htmls, encoding='utf-8')
return htmls
def __analysis(self, htmls):
'''
分析方法
'''
root_html = re.findall(Spider.root_parttern, htmls)
anchors = []
for html in root_html:
name = re.findall(Spider.name_pattern, html)
number = re.findall(Spider.number_pattern, html)
anchor = {'name': name, 'number': number}
anchors.append(anchor)
return anchors
def __refine(self, anchors):
'''
精练(去掉空格换行符,列表转换)
'''
l = lambda anchor: {
'name':anchor['name'][0].strip(),
'number':anchor['number'][0]
}
return map(l, anchors)
def __sort(self, anchors):
'''
排序
'''
# 默认是升序排列,revers 参数调整
anchors = sorted(anchors, key = self.__sort_seed, reverse = True)
return anchors
def __sort_seed(self, anchor):
'''
对排序指定的key编写比较的函数,比较的种子
'''
# 提取数字
r = re.findall('\d*', anchor['number'])
number = float(r[0])
if '万' in anchor['number']:
number *= 10000
return number
def __show(self, anchors):
'''
展示数据
'''
for rank in range(0, len(anchors)):
print('rank---' + str(rank + 1)
+ '---' + anchors[rank]['name']
+ '---' + anchors[rank]['number'])
def go(self):
'''
总控方法
'''
htmls = self.__fetch_content()
anchors = self.__analysis(htmls)
anchors = list(self.__refine(anchors))
anchors = self.__sort(anchors)
self.__show(anchors)
# 实例化对象
spider = Spider()
# 测试爬虫
spider.go()
day = 0
def get_sunday():
return 'Sunday'
def get_monday():
return 'Monday'
def get_tuesday():
return 'Tuesday'
def get_default():
return 'Unknow'
switcher = {
0: get_sunday,
1: 'Monday',
2: 'Tuesday',
}
day_name = switcher.get(day, get_default)() // get方法第二个参数指定没有day值的时候,类似于default,这里返回的是方法,所以最后需要加上括号
day_name = switcher.get(day, 'unknow') // 注意字典得取值是方法或者是值的区别
a = [1,2,3,4,5,6,7,8]
b = [i**2 for i in a] // 这就是列表推导式i**2表示i的2次方
print(b) // 结果是列表
c = [i**2 for i in a if i >= 5] // 有条件的筛选,对i>=5的i操作
print(c) // 结果是列表
a1 = {1,2,3,4,5,6,7,8}
d = {i**2 for i in a1 if i >= 5} // 使用[]得到列表,{}得到集合
print(d) // 结果是集合
student = {
'喜小乐':12,
'小明子':18
}
b = {value:key for key,value in student.items()} // 颠倒字典
c = (key for key,value in student.items()) // 得到元组,不建议元组,建议列表[]
for x in c:
print(x)
a==None
,而是推荐if a
或者if not a
None 对应的是False
自定义对象
class Test():
def __len__(self):
return 0
test = Test()
if test:
print('s') // 不会打印出来,即使test是一个实例化对象,test对象存在也有可能被转换成false
class Test():
pass
test = Test()
if test:
print('s') // s
和类中定义的两个方法有关系
__len__
与__bool__
内置方法没有bool和len方法的时候默认是True
class Test():
pass
test = Test()
if test:
print('s') // s
定义了boo和len
class Test():
def __bool__(self):
return False
def __len__(self):
return 0 // 取非0的时候就是True,这里可以返回整形数字或者boolean值True、False
test = Test()
len(test) // 0 调用内置的len函数的时候会去调参数内部的len方法
if test:
print('s') // 根据具体情况判断是false还是true
如果类中没有定义bool,定义了len,最后是true还是false是由len决定的
两者都存在的时候由bool方法决定对象的取值
装饰器改变了函数名字
import time
def decorator(func):
def wrapper():
print(time.time())
func()
return wapper
@decorator
def f1():
print('this is f1')
print(f1.__name__)
f() //注释掉装饰器 # @decorator 的时候打印出 f1
// 加了装饰器之后, 函数的名字叫 wrapper 了,函数名字被改变会影响代码
函数的描述出现问题
import time
def decorator(func):
def wrapper():
print(time.time())
func()
return wapper
@decorator
def f1():
'''
描述
'''
print('this is f1')
print(f1.__name__)
print(helo(f1)) // 由于增加了装饰器,查看不到函数的描述文档了
如何解决装饰器的副作用 @wraps(func)
// 这个装饰器很重要
import time
from functools import wraps
def decorator(func):
@wraps(func) // 这个装饰器很重要
def wrapper():
print(time.time())
func()
return wapper
@decorator
def f1():
'''
描述
'''
print('this is f1')
print(f1.__name__)
print(helo(f1)) // 这样就变正确了