记:2020-10-06
==》python基本数据类型:
python基本数据类型- 为什么字符串、列表和元组成为序列,因为它们支持切片和下标索引取值
------> 数字:
9 // 4 // 取整,2
9%4 // 取余, 1
9 /3 // 3.0 除数返回默认为double float类型
- 注:这边布尔类型判断,跟js判断空数组有区别 =>
boolean([]) // true
bool('') // 0
bool([]) // False
bool({}) // False
bool(()) // False
bool(None) // False
- 不同进制的表示及转换
0b10 // 2
0x 10 // 16
0o 10 // 8
bin(10) // 0b1010
int(0b10) // 2
oct(10) // 0o12
hex(10) // 0xa
------> 字符串:
'字符串' + '拼接' // '字符串拼接'
'字符串取值'[-1] // '值'
'字符串取值'[3:] // '取值'
'''字符串换行''' // '字符串换行'
r'字符串特殊字符,不让其转义,如文件地址 D:\xampp' // '字符串特殊字符,不让其转义,如文件地址 D:\\xampp'
R'C:\Windows' // 'C:\\Windows'
'字符串乘数'*2 // '字符串乘数字符串乘数'
"hellow world"[0:8:2] // 'hlo '
------> set:
- 无序性
- 无重复性
{1,2,3} - {2} // {1,3} 求差
{1,2,3} & {2} // {2} 交集
{1,2,3} | {2} // {1,2,3} 并集
A={1,2,3,4,5,6}
A.add(7)
print(A) // {1,2,3,4,5,6,7}
A={1,2,3,4,5,6}
A.discard(6)
print(A) // {1,2,3,4,5}
------> tuple:
- 不支持增加、删除、编辑
temp = (1,2,3,True,False)
temp[2] // 3
temp.index(2) // 1
temp.index(True) // 永远返回0
temp.index(False) // 4
------> 常用方法:
in、 not in、 ord、chr
3 in {1,2,3} // True
3 not in (1,2,3) // False
ord('w') // 119 返回对应字符的ascii码
chr(119) // 'w'
------> 字典:
- key值必须是不可变类型
- key值不能重复(如果重复,后面的覆盖前面的)
- 不属于序列类型
type({}) // <class 'dict'>
注: 有时候会觉得字典跟我们js的对象有点傻傻分不清,js的对象可以通过obj.name
或者obj['name']
访问;而python的字典只能通过dict['name']
访问,实例只能通过obj.name
访问。
------> 杂:
- python变量命名: 小写字母 加 下划线
- python 每个文件就是一个模块 规范的模块起始 需要加注释
- python缩进(tab)必须4个空格,否则会报错
- pass:空语句(占位语句),用于保持代码完整性
- if else的简写方法:
if condition
a
else
b
==> a or b
- python跟js 在字符串拼接的区别 python要求都是字符串;js如果字符串和数字拼接,会转为字符串
- 函数参数:参数arg、*args、**kwargs三个参数的位置必须是一定的。必须是(arg,*args,**kwargs)这个顺序,否则程序会报错。
def function(arg,*args,**kwargs):
print(arg,args,kwargs)
function(6,7,8,9,a=1, b=2, c=3) // 6 (7, 8, 9) {'a': 1, 'b': 2, 'c': 3}
- 变量命名:字幕、下划线、数字,开头不能为数字,系统关键字不能用在变量名中;
- 数据类型分为:
int str tuple
(不可变) 值类型和list set dict
(不可变)引用类型
==》python运算符:
------> 算数运算符:
+ - * / // % **
2**2 // 4 (2的2次方)
------> 赋值预算符:
== += -= /= %= **= //=
------> 比较(关系)运算符:
== != > < >= <=
------> 逻辑运算符:
and or not
------> 成员运算符:
in not in
------> 身份运算符:
is is not
is 与 == 区别: is 用于判断两个变量引用对象是否为同一个(同一块内存空间), == 用于判断引用变量的值是否相等。
------> 位运算符:
(把数字当作二进制进行运算)
& | ^ ~ << >>
------> 运算符优先级:
==》Python项目的组织结构:
包 模块 类 函数、变量
-
__all__ = []
如果用于__init.py
文件则限制导出模块,用于普通模块文件,则限制当前模块导出的变量、函数和类; python中模块的all详细使用 -
建议通过类来管理变量和函数;
-
__init__.py
文件用于区分普通文件和包,因此内容可以为空。它的名字就是它上层文件包的名字;
_init.py
的作用:__all__ = []
限制导出模块;批量导入包或模块; -
导入模块(
import module_name
):
使用import module_name
后面只能跟模块名(即文件名);
import 只能导入模块,不能直接导入模块下的变量;
import p.m as m
print(m.a) # a是模块下的变量
import的缺点是命名空间太长;
import 不能使用相对路径;
- 导入模块(
form ... import ...
):
form import 可以直接导入具体的变量和函数,也可以导入具体的模块;
from p.m import *
# 建议少星号
- 导入模块,会执行被导入模块的代码;
- 包和模块是不会重复导入;
- 注意避免循环导入;
- 模块内置变量:
print(dir())
import sys
print(dir(sys)) # 可以传入指定的模块或类
- 常用内置变量:
__file__
、__package__
、__name__
、__doc__
入口文件的__file__
、__package__
、__name__
内置变量打印出来的值跟普通模块打印出来是有区别的:入口文件的__name__
会被python强制更改为__mian__
;__package__
为空;__file__
为执行python命令的文件目录地址;而普通模块__file__
为本地绝对地址; -
python -m m.py
python规定模块必须归属于一个包下面; - 相对导入和绝对导入:使用
.
点表示的是相对导入; - 顶级包跟入口文件地址有关:
__package__
; - 绝对路径必须从顶级包开始,eg:
import package2.package4.m
-
import
不能使用相对导入,from
才可以; - 入口文件不能使用相对路径来导入模块(因为python会把入口文件名强制转为
__main__
,而python相对路径又是通过__name__
来识别路径的)
==》函数:
- 函数默认返回
None
- python解析,是自上而下执行的,所以函数调用必须放在函数声明之后(区别:js如果使用函数声明式语法,函数调用是可以放在函数申明之前的(变量提升))
- 设置python递归次数(默认为995次)
import sys
sys.setrecursionlimit(10000)
- 返回多个值(用逗号分隔,以元组类型返回)
return data1,data2
- 变量接受返回值的结果:(方便代码阅读)
skill1_damage,skill2_damage = damage(3, 6)
# 上面damage是函数,它返回两个值, 定义两个变量以解包的方式接收函数返回的两个值,通过这种方式,能方便代码的阅读
- 序列、解包:
序列:
a,b,c = 1,2,3
a = 1,2,3
#a 元组
a,b,c = 1,1,1
=>a = b = c = 1
解包:
u,v,w = a
- 区分:js函数传参和变量解构赋值不要求元素个数必须相等,而python要求元素个数必须相等
// js:
let arr = [1,2,3,4]
[a,b] = arr // a = 1, b = 2
[a, ...b] = arr // a = 1, b = [2,3,4]
#python
a,b = [1,2,3,4] # 报错
a,*b = [1,2,3,4] # a = 1,b = [2,3,4] 这里的解包,右边数据类型无论是元祖、集合、还是列表,解包回来的b都是列表(list)类型
- 形式参数和实际参数概念;
- 必须参数(必须传递参数,否则报错);
- 关键字参数(可以不用考虑参数顺序,提高代码可读性);
def add(x, y)
pass
c = add(y = 1, x = 2)
- 函数默认参数(非默认参数不能跟着默认参数)
SyntaxError: non-default argument follows default argument
def add(x = 1, y = 2)
pass
- 函数传参时,具体参数不能跟着关键字参数
SyntaxError: positional argument follows keyword
def add(x,y = 6, z = 8):
pass
add(10,y = 10, 2) # 报错 argument
- 可变参数(可以接受任意参数)
def demo(*param):
print(param)
print(type(param)) # tuple 无论实参是list,还是tuple、set,这里都是tuple类型
a = [1,2,3]
demo(*a)
- 必须参数(
param1
)必须前面(如果跟可变参数混合用):
def demo(param1, param2 = 3, *param):
print(param)
print(type(param))
- 任意数量的关键参数:
def city_temp(**param):
print(param)
print(type(param))
- 遍历字典:
for key,value in param.items():
print(key,value)
- 全局变量和局部变量:
-> 局部变量只是相对概念;
-> python没有块级作用域;
-> 作用域链;
-> 逐级寻找;
-> python for 循环(因为不存在块级作用域)不属于作用域链,即使它能访问到它的上级变量:
def demo():
c=10
for i in range(0,20):
a = 10
c += i
print(c) # 200
print(a) # 10
demo()
-> global 关键字:
(python中,所属函数可以访问全局变量,但是不建议所属函数修改全局变量,如下所示)
c = 10
def demo():
global c
c = 2
demo()
print(c) # 2
==》类(面向对象):
-
封装性
继承性
多态性
-
如何构建一个类:
-> 类跟对象的关系
-> 类建议第一字母大写,不建议用下划线链接
-> 类括号跟函数括号的参数用途不一样(类表示继承,函数表示传参)
-> 类的内部:
1、定义变量
2、定义函数
-> 实例化类:
student = Student()- 类下面编写函数跟普通函数有区别,必须有self,不能把类下的变量理解为全局变量;
# python强制要求必须显示指定self
- 类下面编写函数跟普通函数有区别,必须有self,不能把类下的变量理解为全局变量;
class Student():
age = 10
def print_age(self):
print(self.age)
-
必须通过self访问内部变量,函数括号必须有self
-
一个模块下面不建议又声明类,又调用类;建议一个模块只单独声明类,再通过另外一个模块导入类,再调用类;
-
方法和函数的区别:
-> 方法: 设计层面
-> 函数:程序运行,过程式的一种称谓 -
类是现实世界或思维世界中的实体在计算机中的实现,它将数据以及这些数据上的操作封装在一起;
-
行为要找对主体(主谓关系)
-
类就像一个模板,通过模板可以产生很多对象
-
构造函数:
def __init__(self) # 必须带self
pass
-> 构造函数不能强制返回其他类型,必须(默认None)None,否则报错;
def __init__(self)
return 666 # 会报错
-> Student.__init__()
- 构造函数作用:初始化对象的属性
- 类变量 实例变量区别:
-> 类变量在class下直接定义
-> 实例变量在__init__()
内定义
class Student():
name = ''
age = 0
def __init__(self,name,age):
self.name = name
self.age = age
-
局部变量不会更改全局变量(变量同名)
-
实例变量必须通过self(在init内)赋值
-
student1.__dict__
#打印实例对象的变量 -
寻找链条“
实例查找 -> 类查找 -> 父类查找(继承过来的父类) -
实例方法 类方法 静态方法
-
实例方法访问类变量和实例变量:
-> 访问实例变量用self
-> 访问类变量:
Student.sum
self.__class__.sum
-
类方法:
@classmethod
def do_work(cls):
pass
-
类方法一般用于处理与实例变量无关的值
-
实例也可以调用类方法,一般建议不要用对象调用类方法
student1.do_work()
# 不建议这么用 -
静态方法:
@staticmethod
def add(a,b):
pass
-> 静态方法不用像实例方法一样强制传递self和cls参数
-> 对象和类都可以调用静态方法
-> 静态方法可以访问类变量
-
类方法和静态方法不可以访问实例变量
-
静态方法不建议经常使用,因为它跟类处于弱关系;
-
方法和变量的内部调用和外部调用:
->限制外部调用和更改
-> 提倡:类下面的变量(包括类变量和实例变量)不要在外部直接修改,例如student1.score = 59
而是要通过方法内修改;原因在于可以控制判断保护数据;(只是提倡建议,不强制要求) -
公开 私有:
-> 公开可以在外部访问
-> 如何变成私有:加双下划线
(_类名__变量名
) -
拓展:加双下划线能让实例访问不到属性和方法,如果像
__init__
左右都加双下划线,就又可以访问到了; -
python动态语言可以通过点的方式给对象新增变量;
-
面向对象三大特性
继承行
封装性
多态性
:
-> 继承性: 避免定义重复的方法和变量;继承实例变量,类变量; -
拓展:python支持多继承(不建议使用多继承)
-
子类调用父类构造函数:
super(Student,self). __init__(name,age)
- 子类方法调用父类方法:
super(Student,self). do_homework()
- 拓展:编程开闭原则
==》枚举:
- 枚举的好处:
不可变
、防止重复
- 枚举类型 枚举的名字 枚举的值
print(VIP.YELLOW) # VIP.YELLOW
print(VIP.YELLOW.value)
print(VIP.YELLOW.name)
print(VIP["GREEN"])
- 不能有相同的标签(key),可以相同的值,但是后者只是前者的别名:
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLUE = 1
print(VIP.YELLOW) # VIP.YELLOW
print(VIP.BLUE) # VIP.YELLOW
print(VIP['BLUE']) # VIP.YELLOW
for v in VIP:
print(v)
#打印结果:
# VIP.YELLOW
# VIP.GREEN
for v in VIP.__members__.items():
print(v)
# 打印结果:
# ('YELLOW', <VIP.YELLOW: 1>)
# ('GREEN', <VIP.GREEN: 2>)
# ('BLUE', <VIP.YELLOW: 1>)
for v in VIP.__members__:
print(v)
# 打印结果:
# YELLOW
# GREEN
# BLUE
-
枚举的比较运算符:
支持:==
in
不支持:>
<
-
枚举的转换
a = 1
VIP(a) # VIP.YELLOW
from enum import IntEnum,unique
@unqiue
class VIP(IntEnum):
YELLOW = 1
GREEN = 1 # 报错
BLUE = 'str' # 报错
- 枚举类型不能实例化(单例模式)(23种设计模式)
==>函数式编程(闭包)
python一切皆对象
- 把一个函数当作另外一个函数的返回结果
- 另外一个函数作为参数,传递到另外函数里
- 闭包概念跟变量作用域有关
def curve_pre():
a = 10
def curve(x):
return a*x
return curve
f = curve_pre()
f(2)
f.__closure__
f.__closure__[0].cell_contents
- 闭包= 函数+环境变换量(把函数和函数变量封装在一个环境里面,让其不受外面影响)
- 局部变量不能影响外部变量
- 经典闭包题目:
def f1():
a = 10
def f2()
a = 8 #python没有认为是一个局部变量(没用引用外部啊= 10)
return f2
f = f1()
-
闭包的用处,保存上一次执行记录
-
global origin # 声明全局变量
-
闭包环境变量有保存现场的功能
origin = 0
def factory(pos):
def go(step):
nolocal pos #声明非本地pos局部变量
new_pos= pos+step
origin = new_pos # 否则python会认为等号左边的origin是一个局部变量声明
return new_pos
return go
tourist = factory(origin)
- 闭包不改变全局变量
- 闭包可以实现工厂模式
- 闭包是常驻内存变量,容易造成内存泄露
==>匿名函数(lambda):
- 只能用于简单表达式(不能代码块)
def add(x,y):
return x + y
# 等同于
lambda x,y: x+y
- 匿名函数使用场景:
不能做赋值运算(冒号后面不能是代码块);
==>三元表达式:
x > y ? x: y
#等同于
x if x > y else y # 格式:条件为真时返回的结果 if 条件判断 else 条件为假时的返回结果
==> map、reduce、filter
- 注:reduce需要导入
list1 = [1,2,3]
list2 = [1,2,3]
def square(x):
return x * x
r = map(square, list1)
print(list(r)) # 需要转换为list格式
# 等同于
map(lambda x,y: x + y, list1, list2)
#导入reduce
from functools import reduce
r = filter(lambda x: x>1, list1)
- 拓展:map/reduce 大数据 编程模型 映射 归约 并行计算 函数式编程
import time
def decorator(func):
def wrapper():
print(time.time())
func()
return wrapper
def f2():
print('this is a function')
f = decorator(f2)
f()
# 语法糖
# 装饰器最大的用处(相比上面)
@decorator
def f1():
print('this is a function')
f1()
- 语法糖只是一种魔术(简化写法,但是不能优化性能)
- 可以接受定义的复杂,但是不能接受调用的复杂
- 拓展:装饰器体现了AOP变成思想(从横切面解决问题)
--> 改造:支持多个参数(上述不能传参)
def decorator(func):
def wrapper(*args):
print(time.time())
func(*args)
return wrapper
@decorator
def f2(param1, param2):
print(f'this is {param1}')
print(f'this is {param2}')
f2('roy', 'roben')
--> 再次优化:
- 装饰器的用途:不改变具体实现,而通过装饰器改变行为
def decorator(func):
def wrapper(*args,**kw):
print(time.time())
func(*args,**kw)
return wrapper
@decorator
def f2(param1, param2, **kw):
print(f'this is {param1}')
print(f'this is {param2}')
print(kw) # {'a': 1, 'b': 2}
f2('roy', 'roben', a = 1, b =2)
==>字典映射代替switch case语句:
day = 0
def get_sunday():
return 'Sunday'
def get_monday():
return 'Monday'
def get_tuesday():
return 'Tuesday'
def get_default():
return 'Unknow'
switch = {
0: get_sunday,
1: get_monday,
2: get_tuesday,
}
r = switch.get(day, get_default)() # get方法具有容错性
print('日期:')
print(r)
==>列表推导式:
- 注:元组比较特殊,因为它是不可变的,所以其返回是一个遍历器
list = (1,2,3)
list_new = [i**2 for i in list]
print(list_new)
list_new = {i**2 for i in list if i > 1} # 加条件
print(list_new)
list_new = (i**2 for i in list if i > 1)
print(list_new) #返回迭代器
print(*list_new)
# 打印结果:
# [1, 4, 9]
# {9, 4}
# <generator object <genexpr> at 0x0000021EF894D148>
# 4 9
# list_new:generator object
for i in list_new:
print(i) # 4 9
students = {
'roy': 18,
'roben': 20,
}
b = { value: key for key,value in students.items()}
print(b)
# 打印结果:
# {18: 'roy', 20: 'roben'}
==>可迭代对象 迭代器(interator)(针对对象来说):
- for in interable
- 迭代器是一个可迭代对象,可迭代对象不一定是可迭代器
class bookCollection:
def __init__(self):
self.data = ['data1', 'data2', 'data3']
self.cur = 0
def __iter__(self):
return self
def __next__(self):
if self.cur >= len(self.data):
raise StopIteration()
r = self.data[self.cur]
self.cur += 1
return r
books = bookCollection()
import copy
books_copy = copy.copy(books) # 浅拷贝 deepcopy 深拷贝
# 迭代器只有一次性
for i in books_copy:
print(i)
# 迭代器可以调用next方法,但是迭代对象不可以调用next方法
books1 = bookCollection()
print(next(books1))
==> 生成器(针对函数来说)
- 列表存储需要消耗内存
- 利用生成器解决上述问题
def gen(max):
n = 0
while n<=max:
n+=1
yield n
# 解决了内存问题
g = gen(100)
print(next(g))
print(next(g))
print(next(g))
# 生成器
g1 = (i for i in range(0, 100))
==> 非空判断:
- None 不等于 [] '' 0 False
# 判空操作
a = None # False 0 '' []
if a:
pass
if not a:
pass
# 不建议用下面进行判空
if a is None:
pass
==>对象存在不一定是True:
- 受下述内置函数影响:
class Test():
def __len__(self):
return 0 # 只能返回整型数字 或者 True False
def __bool__(self):
return False # 只能True False
==>装饰器的副作用:
-
f1.__name__
help(f1)
打印出来的值不是f1的内容,而是wrapper的内容 - 解决方法:
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args):
print(time.time())
func(*args)
return wrapper
==>walrus operator 海象运算符 (必须python 3.8版本以上)
a = 'python'
if (b:=len(a)) > 5:
print('长度大于5:'+ '真实长度为' + str(b))
==> dataclass(语法糖)
- 帮助快速创建类的
__init__
方法
from dataclasses import dataclass
@dataclass
class A():
name: str
postion: float
a = A('roy', 1.2)
print(a__repr__()) # A(name='roy', postion=1.2)
print(a) # A(name='roy', postion=1.2)
-
与普通通过
__init__
创建类还是有区别的,dataclass
默认修改了__repr__
方法,因此print
打印出的实例对象能看到它具体的属性值 -
支持传参:
@dataclass(init=False, repr = False)
网友评论