python(入门、进阶)

python(入门、进阶)

记: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 用于判断两个变量引用对象是否为同一个(同一块内存空间), == 用于判断引用变量的值是否相等。

------> 位运算符:
(把数字当作二进制进行运算)

& | ^ ~ << >>

------> 运算符优先级:

image.png


==》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
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()
  • 拓展:编程开闭原则

==》枚举:

Python中枚举的用法

  • 枚举的好处:
    不可变防止重复
  • 枚举类型 枚举的名字 枚举的值
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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,306评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,657评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,928评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,688评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,105评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,024评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,159评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,937评论 0 212
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,689评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,851评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,325评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,651评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,364评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,192评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,985评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,154评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,955评论 2 279