python学习笔记--进阶

Python进阶学习
主要围绕以下几个问题加强了对python的理解。

(1)python中常用的四种数据结构(set, dict, list, tuple)
python中常用的数据结构统称为容器(container),主要有:

  • 序列(列表,元组,字符串) 每个元素都有自己的编号
  • 映射(字典)唯一内建的映射类型
  • 集合(set)

列表可变,是区分于元组、字符串最重要特点。
一些基本用法:
列表(list):[ ]。有序,可更改(增加,删除等)。
获取方法:下标或者切片操作。
更改方法:直接赋值。
删除:末尾删除,L.pop(元素)。删除指定位置,L.pop(位置)。
增加:末尾增加,L.append(元素)。指定位置插入,L.insert(位置,元素)。
元组(tuple):( )。有序,不可变。赋值时候决定所有元素。
词典(dict):{ }。无序,可更改。空间换时间,提升效率。
集合(set):{ }。元素不能重复。无序,可更改。

使用场景:
列表:不定长连续空间 查找复杂度o(n)
消耗内存 yield方法(考虑性能和资源的使用)
元组:不能修改,正是其有用的地方;保存不可变对象的引用时,不用担心被其它程序修改
列表和元组之前的主要不同:
不可变vs可变
同构vs异构 :元组异构,当作没有字段名的记录;列表同构,具有相同意义的数据
字典:底层为hashmap 根据key找value的复杂度为o(1),适用于对成员的频繁查找与更新
集合:非连续的内存空间,相比列表内存效率高,一般做数据的交差并补操作

(2)python的关键字参数和位置参数

在python的函数定义/调用时,常涉及到以下几种参数:位置参数,关键字参数,默认参数等。
位置参数:调用函数时根据函数定义的参数位置来传递函数。
必须一一对应,缺失一个都不行。
关键字参数:调用函数时通过“键-值”形式加以指定。可以使函数更加清晰、容易使用,同时清除了参数的顺序需求。
当存在位置参数时,位置参数必须在关键字参数前面,但关键字之间不存在先后顺序。
默认参数:定义函数时,为参数提供默认值,调用函数时可传可不传该默认参数的值。
可变参数:定义函数时,有时并不确定调用的时候需要传递多少个参数(不传参也可以)。(而我们一般在定义函数时,是要预先定义要接受多少个参数的)。在代码中经常看到这种语句:func(args, **kwargs),其中带的参数用来接受可变数量参数,称为packing。

*arg 非关键字参数列表,是tuple类型

def func(*args):
     ...

func()
func(a)
func(a,b,c)

**keywords 关键字参数列表,是dict类型

def func(**kargs):
     ...

func(a=1)
func(a=1,b=2,c=3)

另外,* 和 **也可以在函数调用的时候使用,称为unpacking。
在传递元组时,让元组的每一个元素对应一个位置参数。

def func(name, sex):
    print name, sex

args=('noora', 'female')
func(*args)
# noora female

在传递词典字典时,让词典的每个键值对作为一个关键字参数传递给函数。

def func(kargs):
    print kargs

krags = {'name': 'noora', 'sex', 'female'}
func(**kargs)

# {'name': 'noora', 'sex', 'female'}

(3)作用域 变量解析规则 生存周期

扫描二维码关注公众号,回复: 2662992 查看本文章
  • 命名空间(namespace):名字到对象的一个映射
  • 作用域(scope):python程序的一块文本区域。
    在该文本区域中,对namespace可以直接访问(会在所有namespace中查找该变量),而不需要通过属性访问(名字+.)。
    命名空间是纯粹意义上名字和对象的映射关系;作用域还指出从用户代码的哪些物理位置可以访问到这些名字。 namespace:它存在吗?
    scope:我能看见它吗?
    python中,scope是由namespace按特定层级结构组合起来。scope一定是namespace,但namespace不一定是scope。
  • 为何要弄清? 涉及变量声明在程序里的可应用范围(变量可见性),即你可在程序的哪些部分去访问一个指定的标识符。
    python变量的作用域遵循LEGB原则:在一个python程序运行中,至少有4个scopes存在,直接访问一个变量可能在其中依次搜寻。
    L(local)局部作用域,比如函数/方法内部。 E(Enclosing)非局部也非全局变量,闭包函数外的函数中。
    G(Global)全局作用域,当前脚本的最外层,比如当前模块的全局变量。
    B(Built-in)内建作用域,builtin模块,包括内建的变量/关键字。
    变量依次在LEGB中搜索,若都没有搜索到则抛出NameError异常。

(4)装饰器(decorator)

  • 装饰器是一种设计模式,面向切面编程(AOP)。
    使用场景:抽离出大量函数中与函数功能本身无关的雷同代码并继续重用(插入日志、性能测试、事务处理等)。
    装饰器,是一个带有一个函数座位参数并返回一个替换函数的闭包。即是原函数的装饰版本,替换原版。原来的函数func还存在,只不过同名变量func指向了新的函数,调用func()将执行新函数。
    语法糖:函数定义前添加@实现对函数的包装。
    python内置装饰器有三个:@staticmethod,@classmethod和@property,分别是把类中定义的实例方法变为静态方法,类方法和类属性。
  • 重点看一下@classmethod和@staticmethod。 一般情况下,需要使用某个类的方法,需要先实例化一个对象再调用方法。
    而使用@classmethod和@staticmethod,可以不需要实例化,直接类名.方法名()来调用。
    这有利于组织代码,把某些应该属于某个类的函数放到那个类里去,同时有利于命名空间的整洁。 有时,仅需要和类交互而不是与实例交互。
    而这两种方法的区别是什么呢? @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
    @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
    @classmethod是一个函数修饰符,它表示接下来是一个类方法,而对于我们平常见到的则叫做实例方法。类方法的第一个参数cls,而实例方法第一个参数是self,表示该类的一个实例。
    普通对象方法至少需要一个self参数,代表类对象实例。
    类方法有类变量cls传入,从而可以用cls做一些相关的处理。并且有子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类。

(5)迭代器和生成器
属于python高级特性:减少代码量。
迭代器

  • 迭代器协议? 对象需要提供next方法,它要么返回迭代中的下一项,要么引起StopIteration异常,以终止迭代。
  • 迭代器对象? 实现了迭代器协议的对象(iterator)。
  • 协议是一种约定,可迭代对象实现迭代器协议,python内置工具(for循环,sum,min,max)使用迭代器访问对象。
  • 迭代器的两个基本方法: iter() 创建迭代器对象
    next() 输出下一元素

    生成器
    延迟操作,在需要时才产生结果,而不是立即产生结果。
    生成器自动实现迭代器协议。适用于大数据处理。

两种方法提供生成器:

  • 生成器函数
    常规函数定义,但使用yield而不是return返回结果。yield一次返回一个结果,在每个结果之间挂起函数的状态,以便下次从它离开的地方继续执行。
  • 生成器表达式 类似于列表推导,但生成器返回按需产生结果的一个对象,而非一次构建一个结果列表。

(6)函数式编程思想
之前经常采用的编程思想是命令式编程,包括面向过程编程和面向对象编程。
命令式编程关注解决问题的步骤。主要用到以下几类常用操作:
函数定义:def;
条件控制:if,else,elif;
循环控制:for,break,continue,while。
函数式编程关注数据的映射。主要涉及3个基本函数和1个算子:
基本函数:map(),reduce(),filter()
算子(operator):lambda
Python函数式编程的基本单元:

  • lambda 实现创建函数的功能

    func1 = lambda: <expression()> func2 = lambda x: <expression(x)>
    func3 = lambda x,y: <expression(x,y)>

    分别和下面采用def创建函数的效果相同:

    def func1():
    <expression()> def func2(x):
    <expression(x)> def func3(x,y):
    <expression(x,y)>

  • map(func, iterable) 需要两个必填参数,第一个参数是一个函数名,第二个参数是一个可迭代对象,如列表、元组等。

  • reduce(func, iterable, [initializer])
    功能:对可迭代对象(iterable)中的元素从左到右进行累计运算,最终得到一个数值。第三个参数initializer是初始数值,可以空置,空置为None时就从可迭代对象(iterable)的第二个元素开始,并将第一个元素作为之前的结果。

  • filter(func, iterable) 有且仅有两个参数,第一个参数是一个函数名,第二个参数是一个可迭代对象,如列表、元组等。
    与map()的差异是,filter()会判断每次执行结果的bool值,并只将bool值为true的筛选出来,组成一个新的列表并进行返回。

猜你喜欢

转载自blog.csdn.net/laotianv5/article/details/81535743