数据分析 NO.9python进阶深入

    xiaoxiao2022-07-02  108

    python进阶深入 1.生成器:创建生成器最简单的方法就是用圆括号()代替方括号 [] 把列表生成式的 [ ] 变成() 生成器只能调用一次,不占用资源。用完就释放出来。

    for i in g: print(i)

    也可以调用Next函数直到计算出最后一个元素位置,但是这种方法很明显不适用,并且最后会抛出StopIteration的错误。

    斐波那契数列:除第一个和第二个数外,任意一个数都可由前两个数相加得到: 1, 1, 2, 3, 5, 8, 13, 21, 34, … return返回的是具体的数值 yield返回的是一个生成器 递归的思路代码:

    def fib(n_position): if n_position == 1 or n_position ==2: return 1 return fib(n_position - 1 ) + fib(n_position -2)

    2.迭代器: 可用于for循环的对象统称为可迭代对象:Iterable。包括之前学的list,tuple等数据结构以及生成器。 但是生成器不仅可以被for循环调用, 还可以使用next函数获取元素,可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。 生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator

    isinstance(g,Iterator) 判断g 是不是后面类似返回True or False

    3.装饰器: 用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。 这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌“原“”函数的函数。

    import time def timer(f): def wrapper(): start = time.time() f(x) end = time.time() last_time = end -start print("持续了%s"%last_time) return wrapper @timer def yanchi(x): print("开始休息") time.sleep(x) print("休息完毕")

    这里的timer函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。 其中作为参数的这个函数f(x)就在返回函数wrapper()的内部执行。然后在函数f(x)前面加上@timer, yanchi()函数就相当于被注入了计时功能,现在只要调用yanchi(),它就已经变身为“新的功能更多”的函数了, (不需要重复执行原函数)。

    无固定参数的装饰器:

    import time def deco(f): def wrapper(*args, **kwargs): start_time = time.time() f(*args, **kwargs) end_time = time.time() execution_time_ = (end_time - start_time)*1000 print("time is %d ms" %execution_time) return wrapper @deco def f(a,b): print("be on") time.sleep(1) print("result is %d" %(a+b)) @deco def f2(a,b,c): print("be on") time.sleep(1) print("result is %d" %(a+b+c)) if __name__ == '__main__': f2(3,4,5) f(3,4)

    装饰器是可以叠加的,多个装饰器装饰一个函数,其装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。

    4.函数式编程 高阶函数: 函数名也是变量, 既然变量可以指向函数,函数可以接受变量,那么一个函数就可以接受另一个函数作为传入参数,拿来使用

    def add(x,y,z): return z(x) + z(y) add([1,2,3,4],[4,3,1,5,6],len)

    5.map/reduce map接受两个参数,一个是函数,一个是Iterable,函数作用在序列的每一个元素上,并把结果作为Iterable返回

    x=[1,2,3,4,5,6,7,8,9,10] map(lambda s:s*s,x) list(map(lambda s:s*s,x))

    reduce也是把函数作用与序列上,但是这个函数必须接受两个参数,reduce把计算结果继续与下一个元素做累积计算

    from functools import reduce reduce(lambda a,b:a*b,x)

    6.filter函数: filter也是把函数作用在序列元素上,但是该函数返回的结果必须是布尔型,filter根据true或者false进行元素的保留和删除

    x = [1,3,6,7,2,19,20,33,29,10,49] list(filter(lambda s : s%2 ==0,x))

    7.匿名函数 Lambda

    f=lambda s:s*2 x=[1,2,3,4] map(f,x) f=lambda a,b:(a+b)*2 x=[1,2,3] y=[2,3,4] list(map(f,x,y))

    8.面向对象 类里面一般包含属性和方法,你可以简单理解为属性为静态,方法是动态的。比如人(PERSON)这个类,嘴、手、腿就是类的属性,跑步、吃饭等就是累的方法。

    我们可以把在创建实例时我们认为必须绑定的属性强制填写进去,这里通过 init 方法完成。init 方法的第一个参数永远是self,代表了实例本身。有了该方法之后,在创建的实例的时候必须强制指定属性值,否则会报错。该方法也可以理解为初始化的一个动作,在创建实例的时候初始化该实例的一些属性! 前后都是两个下划线 下面的S是的大写,如果是多个单词组合,每个单词第一个字母大写(编写规范)

    class Student: def __init__(self,student_id,address,score): self.staudent_id = staudent_id self.address = address self.score = score self.name = student_name self.gender = "female" def getId(self): print(self.student_id) #创建实例 student = Student(1020202,"北京",98,"xiaoming") 必须把()里面参数填满 class Student: kind = "Chinese" # Shared by all instances def __init__(self,id,address,score): self.id = id self.address = address self.score = score def getId(self): print(self.id) print(self.kind) def judge_age(self,age): if age < 18: return "未成年" elif age < 30: print("Student: {0}".format(self.id)) return "年轻人" elif age < 60: return "中年人" else: return "老年人" S1 = Student(12324,"上海市",100) S2 = Student(3245,"上海市",90) # print(S1.kind) # S1.judge_age(22) 上述程序中,kind是被所有的实例共享,只要是实例拥有的都要用self一下。

    调用属性和方法都是通过 .

    继承和多态: 面向对象编程语言连都会有继承的概念,我们可以定义一个class类,然后再定义它的子类,这个子类继承了上面的类,被继承的类称作父类

    class HighSchool(Student): pass

    Highschool类集成了Student类,student类就是父类。 继承的好处就是子类可以享用父类的全部方法和属性。虽然HighSchool什么也没定义,但是可以直接使用Student的方法

    子类也可以由自己的初始化方法,一定要用 super().init(name, id) 去初始化父类 函数super()将返回当前类继承的父类,即 Student ,然后调用init()方法

    class Student(): def __init__(self,name,id): self.name = name self.id = id def student(self): print("Student score!") def get_name_id(self): print(self.name +":" +self.id) class HighSchool(Student): def __init__(self,name,id,score): super().__init__(name,id) self.score=score pass

    如果在父类和子类的方法重复了,会首先使用我子类自己的方法 大佬博客可参考:链接

    9.Collections类 9.1 deque: deque 和list的用法比较类似,它是队列与栈的实现,可以对序列数据进行两端的操作。deque支持在O(1)的时间复杂度上对序列进行两端的append或者pop。list也可以实现同样的操作,但是它的复杂度是O(N) O(N)复杂度

    # 类似于列表实现 from collections import deque a = deque(['a','b','c','d']) a.append("e") # a a.pop() # 两端操作 #a.popleft() a.appendleft("a") #反转 a.rotate() 对首端进行操作的话,用deque_a.appendleft("a")

    9.2 counter

    from collections import Counter a = list('absgctsgabfxtdrafabstxrsg') c = Counter(a) # 查看TOPN的元素 c.most_common(5)

    关于OrderedDict 本身不是对key或者value的大小进行排序,而是对存储的时候,人为定义好的插入的顺序进行保存。

    from collections import OrderedDict # regular unsorted dictionary d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2} # dictionary sorted by key OrderedDict(sorted(d.items(), key=lambda t: t[0])) # # dictionary sorted by value OrderedDict(sorted(d.items(), key=lambda t: t[1])) # # dictionary sorted by length of the key string OrderedDict(sorted(d.items(), key=lambda t: len(t[0]))) od = OrderedDict(sorted(d.items(), key=lambda t: t[0])) t[0]:key t[1]:value od.popitem(last = False) False 去掉左端第一个,是True的话就是末尾

    10.字符串处理 s.strip() 去掉首位两端的空格 延伸:.lstrip(),.rstrip() s.find() s.find(“e”)返回e的索引位置,如果没有就会返回-1 s.find(“H”,1) 后面的1是启始位置,其实只要找的到了,是不影响索引位置。 s.startwith(“H”,1) 判断后面的索引位置开始的首字母是否是"H",返回True or False s.endwith() s.lower() s.upper()

    s.split(",") 切割,返回的一个列表。

    map(lambda t : t.strip() , s.strip().upper().split(","))

    11.格式化

    for i in range(100): t = str(i) print("这是我打印的第 %s 个数字"%t) a = 'chengdu' b = '35℃' print("%s的温度是%s"%(a,b))

    下面这个看起来更简洁

    a = "shanghai" b = 39 print("今天 {0} 的气温是 {1}".format(a,b)) 根据索引的位置选

    python 3.6版本后可以用: f’名字是:{a},温度是:{b}’

    print(f"{a}的温度是{b}") city = input("选择你所在的城市") temp = input("输入平均的温度") print(f"{city}的平均温度是{temp}℃".format(city,temp))

    数字的精度输出:自我感觉就像C语言的float类型的输出

    >>> '{:.4f}'.format(1/3) '0.3333' >>> '{:4f}'.format(100) '100.000000'

    数字的进制输出

    '18的二进制:{:b}'.format(18) '18的二进制:10010' >>> '18的八进制:{:o}'.format(18) '18的八进制:22' >>> '18的十六进制:{:x}'.format(18) '18的十六进制:12' "{:02x}".format(20) #16进制选择2位,不足两位前面补0

    12.datetime

    from datetime import datetime print(datetime.now())

    strptime(,)

    # 字符串与时间的转换 s = '20170901' s1 = datetime.strptime(s,'%Y%m%d') s = "2019/05/03" s2 = datetime.strptime(s,'%Y/%m/%d')

    返回结果: strftime("%Y-%m-%d-%H") #将时间格式转化为字符串

    timedelta ** timedelta **

    class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

    from datetime import datetime.timedelta s2 - s1

    返回结果是609天,datetime用作减可以直接减

    加的话是

    s2+timedelta(3)

    减可以是

    s2-timedelta(3) 或 s2+timedelta(-3) s2 + timedelta(hours = 10) + timedelta(weeks = 1)

    s1.date() 只获取到日的节点

    from datetime import datetime s="2019-5-9" s_test=datetime.strptime(s,"%Y-%m-%d") s_test.day I/O 读文件需要使用 open()函数,其参数为文件名与标识符: f = open("file",'r') data = f.read() f.close()

    读了文件一定要关闭文件。 可以使用with关键词进行整合:

    with open("helloWorld.py",'r') as handle: data = handle.readlines()

    read()所有数据读取进来 readlines()一行一行读出来,

    list(map(lambda s : s.strip(),data))

    编码问题:添加encoding=

    f = open("file",'r',encoding = 'gbk') # utf-8

    数据写入: 写文件和读文件几乎一致,唯一的区别是标识符需要改为"w"。 第一个实参也是要打开的文件的名称; 第二个实参(‘w’)告诉Python,我们要以写入模式打开这个文件。打开文件时,可指定读取模 式(‘r’)、 写入模式(‘w’)、 **附加模式(‘a’)**或让你能够读取和写入文件的模式(‘r+’)。如果 你省略了模式实参, Python将以默认的只读模式打开文件

    with open("test2.txt",'w') as handle: handle.write("hello world")

    如果你要写入的文件不存在,函数open()将自动创建它。然而,以写入(‘w’)模式打开文 件时千万要小心,因为如果指定的文件已经存在, Python将在返回文件对象前清空该文件。

    with open("test.txt",'a') as handle: handle.write("Today is Nice!\n") handle.write("We are happy!!\n")

    如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式打开文件。你以附加模式 打开文件时, Python不会在返回文件对象前清空文件,而你写入到文件的行都将添加到文件末尾。 如果指定的文件不存在, Python将为你创建一个空文件。

    要写入多行的话。需要自己添加换号符 “\n”

    动态执行代码的方法:参考于添加链接描述 核心在于 exec() 方法,它是内置的,用途是执行储存在字符串或文件中的代码段

    >>> list1 = ['A', 'B', 'C', 'D'] >>> for i in list1: >>> exec(f"{i} = []") >>> A

    14.ZIP()函数 一.zip()函数的定义: 从参数中的多个迭代器取元素组合成一个新的迭代器 返回:一个zip对象,其内部元素为元组;可以转化成列表或元组 传入参数:元组、列表、字典等迭代器 二.zip()的用法 (1)当zip()函数中只有一个参数时,zip(iterable)从迭代器中依次取一个元组,组成一个元组。

    # python 3 # zip()函数单个参数 In [1]: list1 = [1, 2, 3, 4] In [2]: tuple1 = zip(list1) In [3]: type(tuple1) Out[3]: zip In [4]: list(tuple1) Out[4]: [(1,), (2,), (3,), (4,)]

    (2)0当zip()函数有两个参数时,zip(a,b)函数分别从a和b中取一个元素组成元组,再次将组成的元组组合成一个新的迭代器。a与b的维数相同时,正常组合对应位置的元素。当a与b行或列数不同时,取两者中的最小的行列数。

    # zip()函数有两个参数 In [5]: m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] In [6]: n = [[1, 1, 1], [2, 2, 3], [3, 3, 3]] In [7]: p = [[1, 1, 1], [2, 2, 2]] In [8]: list(zip(m,n)) Out[8]: [([1, 2, 3], [1, 1, 1]), ([4, 5, 6], [2, 2, 3]), ([7, 8, 9], [3, 3, 3])] In [9]: list(zip(m,p)) Out[9]: [([1, 2, 3], [1, 1, 1]), ([4, 5, 6], [2, 2, 2])]

    三.zip(iterables)函数 zip()函数是zip()函数的逆过程,将zip对象变成原先组合前的数据

    In [24]: m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] In [25]: n = [[1, 1, 1], [2, 2, 3], [3, 3, 3]] In [26]: print(*zip(m, n)) ([1, 2, 3], [1, 1, 1]) ([4, 5, 6], [2, 2, 3]) ([7, 8, 9], [3, 3, 3]) In [27]: m2, n2 = zip(*zip(m,n)) In [28]: m == list(m2) and n == list(n2) Out[28]: True >>> a = [1,2,3] >>> b = [4,5,6] >>> c = [4,5,6,7,8] >>> zipped = zip(a,b) # 打包为元组的列表 [(1, 4), (2, 5), (3, 6)] >>> zip(a,c) # 元素个数与最短的列表一致 [(1, 4), (2, 5), (3, 6)] >>> zip(*zipped) # 与 zip 相反,可理解为解压,返回二维矩阵式 [(1, 2, 3), (4, 5, 6)]
    最新回复(0)