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

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

hue
返回结果是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
  1. 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)]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值