python一些高级应用的再学习

1.lambda表达式

lambda表达式本质上其实就是python的匿名函数。并且也可以作为返回值返回一个匿名函数。这个在下面会具体说到。格式为 lambda 参数列表:函数体。

a = lambda x,y:x+y
a(3, 4)

等价于

def add(x,y):
    return x+y

add(3,4)

2.三元运算符

三元运算符很简单,就是一个条件判断,尤其在一些列表中用三元运算符在写代码时会较为简便。直接看例子:

condition = True
ans = 1 if condition else 2

condition = False
ans = 1 if condition else 2

其中第一个ans返沪1,第二个返回2。

3.map函数

先来看这个函数的参数:

第一个参数是一个函数,如果用lambda匿名函数不就方便很多吗,正好我们上面也说了可以作为函数返回。第二个参数是一个可迭代的对象,python中list就是这样一个对象。这样可以对可迭代对象中的每一个值都用这个函数进行映射。如下:

list1 = [1, 2, 3, 4, 5]
r = map(lambda x:x+x, list1)
print(list(r))

返回值:[2, 4, 6, 8, 10]

当然这是最简单的一种映射,传过来的函数也可以有多个参数,但是有多个参数的话map的第二个参数也需要是多个可迭代对象,长度相同。举个例子:

m1 = map(lambda x,y:x*x+y, [1, 2, 3, 4], [1, 2, 3, 4])
list(m1)

返回值:[2, 6, 12, 20]

4.filter过滤器

如图所示,我们可以看到第一个参数可以是函数或者为空,第二个参数为一个可迭代对象。

也就是函数是过滤的条件,可迭代对象是过滤的目标。例如:

def is_not_none(s):
    return s and len(s.strip()) > 0
list1 = filter(is_not_none, ['hello', ' ', None, 'love'])
# 用lambda实现相同的效果
list2 = filter(lambda s:s and len(s.strip()) > 0, ['hello', ' ', None, 'love'])
print(list(list1))
print(list(list2))

返回值:['hello', 'love']
       ['hello', 'love']

5.reduce函数

如图的定义,它会对参数序列中元素进行累积。

函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

from functools import reduce
f = lambda x, y : x + y
reduce(f, [1, 2, 3, 4, 5])

返回值:15

f = lambda x, y : x + y
reduce(f, [1, 2, 3, 4, 5], 10)

返回值:25 

6.python中的三大推导式

列表推导式

这个很简单,直接看例子:

list1 = [1, 2, 3, 4, 5, 6]
f = map(lambda x: x + x, list1)
print(list(f))

list2 = [i+i for i in list1]
print(list2)
list3 = [i**3 for i in list1]
print(list3)

list4 = [i*i for i in list1 if i > 3]
print(list4)


返回值:
[2, 4, 6, 8, 10, 12]
[2, 4, 6, 8, 10, 12]
[1, 8, 27, 64, 125, 216]
[16, 25, 36]

集合推导式

集合推导式可能平时用的不是那么频繁,但是形式和列表推导式几乎一样。

list1 = [1, 2, 3, 4, 5, 6]

list2 = {i+i for i in list1}
print(list2)
list3 = {i**3 for i in list1}
print(list3)

list4 = {i*i for i in list1 if i > 3}
print(list4)

返回值:
{2, 4, 6, 8, 10, 12}
{64, 1, 8, 216, 27, 125}
{16, 25, 36}

字典推导式

s = {
    "Alice": 10,
    "Bob": 20,
    "Jack": 30
}
# 拿出所有的key
s_key = [key for key, value in s.items()]
print(s_key)
s_key = [key+"xxx" for key, value in s.items()]
print(s_key)

# key和value颠倒
s_key_value = {value:key for key,value in s.items()}
print(s_key_value)

s_select = {key:value for key,value in s.items() if key == 'Alice'}
print(s_select)

返回值:
['Alice', 'Bob', 'Jack']
['Alicexxx', 'Bobxxx', 'Jackxxx']
{10: 'Alice', 20: 'Bob', 30: 'Jack'}
{'Alice': 10}

7.闭包

js中也有闭包,这两个是否类似我也不太清楚。python中的闭包一般指返回值为函数的函数。说的严谨一点:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

import time

# 调用后打印当前时间
def run_time():
    def now_time():
        print(time.time())
    return now_time

f = run_time()
f()
# 等价于 run_time()()

返回值:
1582780675.5656545
# 找到文件中有关键字的行
def mak_filter(key_word):
    def the_filter(file_name):
        doc = [line.strip() for line in open(file_name) if key_word in line]
        return doc
    return the_filter

f = mak_filter('Internet')
ans = f('./data/xjbz.txt')
print(ans)
print(len(ans))

返回值:
['GhostSurf Platinum ensures your safety online by providing an anonymous, encrypted Internet connection, and GhostSurf stops spyware,', 'options enable you to block personal information, mask your IP address, route your data through anonymous hubs and even encrypt your Internet', "connection. GhostSurf's Privacy Control Center allows you to see and block every piece of data that your computer emits over the Internet,", 'preventing even your Internet Service Provider (ISP) from creating a profile on you.']
4

那么闭包究竟有什么用呢,为什么要用闭包?我感觉不太能说得清楚,推荐两篇文章:

Python中的闭包到底有什么用谈谈自己的理解:python中闭包,闭包的实质

8.装饰器

装饰器又叫语法糖,又叫注解,是闭包的一个典型应用。装饰器到底是什么呢,先看一个例子,

# 获取函数运行时间
import time 

def runtime(func):
    def get_time():
        # 注意这两行和上面的区别
        func()
        print(time.time())
    return get_time

@runtime
def student_run():
    print("学生跑")

student_run()


返回值:
学生跑
1582783099.6487942

@其实是装饰器的一个语法糖,说明我们的student_run方法被runtime方法装饰了,并在runtime里面的gettime方法实现studentrun自己的功能,但是却可以实现一些自己不具有的通用的功能,如验证、打印日志等等,非常方便。但是如果函数有参数呢?我们再看这一个例子:

# 获取函数运行时间
import time 

def runtime(func):
    def get_time(i):
        # 注意这两行和上面的区别
        func(i)
        print(time.time())
    return get_time

@runtime
def student_run(i):
    print("学生跑")

student_run(1)

返回值:
学生跑
1582793456.4579806

可以看到,这个student_run确实是传到了runtime中被runtime装饰,而在runtime中运行时需要在其方法内传参,否则会报错。但是这样写参数多了更难管理,每次需要改三个地方。尤其是装饰器里面不应该这样麻烦,只需要在原本的函数runtime函数中保持一直就可以了,并且装饰器里也只是调用,并不管参数怎么传的,因此用可变参数就可以把装饰器和被装饰的函数彻底分开。如下:

# 获取函数运行时间
import time 

def runtime(func):
    def get_time(*args):
        # 注意这两行和上面的区别
        func(*args)
        print(time.time())
    return get_time

@runtime
def student_run(i):
    print("学生跑")

student_run(1)

返回值:
学生跑
1582793786.913682

当然这样还有一点问题,就是对于关键字参数或者或者说键值对参数如f(x,y,a=1),python也有相应的方法,那就是:

# 获取函数运行时间
import time 

def runtime(func):
    def get_time(*args, **kwargs):
        # 注意这两行和上面的区别
        func(*args, **kwargs)
        print(time.time())
    return get_time

@runtime
def student_run(i):
    print("学生跑")

@runtime
def student1_run():
    print("学生1跑")

@runtime
def studeent2_run(*args, **kwargs):
    print("学生2跑")

student_run(1)
student1_run()
studeent2_run(a=1, b=2)

返回值:
学生跑
1582795276.119493
学生11582795276.119493
学生21582795276.119493

可以看到无论参数啥样,都不需要改装饰器里面的内容了。具体如何应用呢,推荐一篇文章,讲的特别好,甚至它的评论也说得很好。——>Python 函数装饰器 节选一段比喻:

每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,让它变得更厚更长,这样一来,它不仅有遮羞功能,还能提供保暖,不过有个问题,这个内裤被我们改造成了长裤后,虽然还有遮羞功能,但本质上它不再是一条真正的内裤了。于是聪明的人们发明长裤,在不影响内裤的前提下,直接把长裤套在了内裤外面,这样内裤还是内裤,有了长裤后宝宝再也不冷了。装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。

9.@staticmethod && @classmethod

最后简单总结一下@staticmethod 和@classmethod,经常会在代码里看到。他们都可以使用类名来调用,也可以用实例来调用,如下代码:

class A(object):
    def foo(self, x):
        print("executing foo(%s, %s)"%(self, x))

    @classmethod
    def class_foo(cls, x):
        print("executing class_foo(%s, %s)" % (cls, x))

    @staticmethod
    def static_foo(x):
        print("executing static_foo(%s)" % x)    

a = A()
a.foo(1)
a.class_foo(1)
A.class_foo(1)
a.static_foo(1)
A.static_foo(1)


返回值:
executing foo(<__main__.A object at 0x000001FBA605EF60>, 1)
executing class_foo(<class '__main__.A'>, 1)
executing class_foo(<class '__main__.A'>, 1)
executing static_foo(1)
executing static_foo(1)

但是也有区别:其中@staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。@classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。

如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。

也就是说,二者都可以通过实例或类来调用,但是classmethod传入了一个cls,所以在函数内部可以使用类的属性或方法,但是staticmethod不可以

给一些我觉得写的很好的参考文章~~~

Python:staticmethod 和 classmethod的比较

@staticmethod和@classmethod的用法

Python中的 staticmethod 和 classmethod


 上一篇
数据分析的王炸--numpy&&pandas(1) 数据分析的王炸--numpy&&pandas(1)
只要进行过数据分析,对于numpy和pandas这两个工具一定不会陌生,用好了他俩,基本啥问题都能解决,再搭配可视化工具,牛逼。 0.pandas和numpy的关系numpy和pandas在数据分析中非常重要,但其实pandas是基于num
2020-02-28
下一篇 
Noisy Channel Model && How to estimate Language Model Noisy Channel Model && How to estimate Language Model
这是接着上一篇博客的,听了一点时间贪心的课其实觉得更多时候我们解决问题应该更专注于其背后的思想。如何考虑问题才是最重要的。 1.Noisy Channel Model先来看一张经典的Noisy Channel Model的模型图: 这张图
2020-02-26
  目录