Python进阶教程(一)

概述

hi,朋友们大家好,今天将英文原著作者 @yasoob《Intermediate Python》进行翻译和在工作中使用的Python技巧进行了总结。Gitbook里面有翻译的版本,大家可以下载下来看看。我今天主要是将该英文原著翻译成适合自己的理解的语言,并附加一些自己在工作中使用Python的技巧。废话少说,下面我们依次来学习一下@yasoob的原著。

Intermediate Python 中译

如果在翻译过程中有问题或者code无法运行,还请各位大侠指正。

*args和**kwargs

我们在函数定义时,会经常使用*args和**kwargs这两个魔法变量,特别是函数参数数量不确定或参数较多时。当然*args和**kwargs这两个name并不是惟一的name,可以改成*as和**kwas,只要在命名前面加上修饰符*和**即可。我们先来看一下*args。

*args

def test_args_kwargs(name,*args):
    print("frist arg: ",name)
    for arg in args:
        print("another arg through *argv: ",arg)

test_args_kwargs("brian","eric","rose")
#输出为
frist arg:  brian
another arg through *argv:  eric
another arg through *argv:  rose

我们也可以通过参数列表进行传递,比如:

names=("brian","eric","rose")
test_args_kwargs(*names)
frist arg:  brian
another arg through *argv:  eric
another arg through *argv:  rose

**kwargs

将不定长度的键值对作为参数传递给函数,我们来看一下。

def greet_me(**args):
    for key,value in args.items():
        print("{0}=={1}".format(key,value))

greet_me(name="brian",age=20,sex="男")
#输出为
name==brian
age==20
sex==男

或者也可以这样

person = {"name":"brian","age":20,"sex":"男"}
greet_me(**person)
#输出为
name==brian
age==20
sex==男

如何使用

在很多场景里面都大量使用比如: 1.装饰器 2.函数定义 3.单元测试 4.猴子补丁(在运行时修改某些代码),在英文版本里面主要介绍了通过猴子补丁修改API来进行测试。 ……

import someclass

def get_info(self,*args):
	return "Test Data"
someclass.get_info=get_info

Debugging

我们在生产和测试环境很少安装IDE进行调试的,如有有紧急需要修改或者出现问题如何快速排查问题和定位问题是非常重要的意见事情,也是主要衡量一个工程师水平的一个标准。那么在Python是如何做呢? 1.日志,不仅在关键的业务处理进行相应的日志输出,也要在入口和出口进行详细的日志处理。 2.Debugging,我们可以通过pdb、ipdb和jupyter进行有效的调试。 3.python docstring一定规范写好,方便调试和定位问题,特别是研发人员的流失比较严重时。 ……

我们今天来看一下通过pdb通过命令行和嵌套debug代码这两种方式都可以调试代码。我们来看一下, 1.命令行运行

python -m pdb test.py

2.嵌套代码

import pdb
def method(*args,**kwargv):
	pdb.set_trace()
	...
method(name="sasa")

当函数调用时进入debug模式。 无论是命令行模式还是嵌套代码模式所有调试代码的命令都是一样的,主要有如下几个快捷键:

  • c:继续在当前程序上下文执行直到遇到断点或者trace位置为止,即继续执行。
  • w:显示当前执行程序上下文信息。
  • a:打印当前函数的参数列表。
  • s:执行当前代码行。
  • n:执行下一行的代码。

Generators

Generators(生成器)很多教程在讲解Generators都会先讲解Iter(迭代器),因为生成器大多数场景都是基于迭代器的。所以我们先来了解学习一些迭代器相关的内容。

  • Iterable(可迭代对象):Python即对象,呵呵。Python的任意对象定了返回__iter__方法或者支持下标的__getitem__方法,它就是一个可迭代的对象。可迭代对象就是提供迭代器的任何对象
  • Iterator(迭代器):一般是指定义了__next__方法的对象。
  • Iteration(迭代):字面意思,不言而喻。实在不理解的,可以简单的理解为循环。

Generators也是一种迭代器,只不过你只能对其只能迭代一次,它并不是列表这种集合类型的数据保存在内存中,而是保存的是运行时的某个值。主要是通过yield来终止并暂存运行时栈,相当于保护现场进而为下次迭代提供记录和便利。特别一次性不需要全部结果集时显得非常重要。 我们来看一个简单的例子:

def fibon(n):
    a=b=1
    for i in range(n):
        yield a
        a,b=b,a+b

for i in fibon(3):
    print(i)
#输出为
1
1
2
#通过next方法来进行获取生成器的下一个迭代
gen_fibon = fibon(3)
print(next(gen_fibon))
print(next(gen_fibon))
print(next(gen_fibon))
#输出结果为
1
1
2
#如果我们再进行下一个迭代时,会出现Exception,这说明我们的迭代已经完成,生成器已经没有再生成Python对象。
print(next(gen_fibon))
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-18-5f779bae9fed> in <module>()
----> 1 next(gen_fibon)

StopIteration:

我们来看一下python的string类型是不是可以直接通过迭代器来获取元素。比如:

name="brian"
next(name)
#输出结果为,告诉我们python的str了O型不是一个迭代器,那么就无法进行迭代。所以我们需要将str对象模型变成可迭代的python对象数据模型,只需要通过iter(object)方法即可。
TypeError: 'str' object is not an iterator
#代码修改
iter_name = iter(name)
next(iter_name)

iter(object)是将一个可迭代的对象变为一个迭代器对象,从而通过next来获取数据。

map,filter and reduce

map,filter,reduce这三个函数式python的buildin函数,是一个开箱即用的函数,更是Python提供面向函数编程的一个优势。我们先来看一下这三个函数的原型:

  • map(function_apply,array/list_inputs)
  • filter(function_apply,array/list_inputs)
  • reduce(function_apply,array/list_inputs)

map

map在处理并行计算提供了极大的便利,巧妙的使用map可以使自己的application变得快速和代码优化。我们先看一个简单的例子:

temp=[2,7,14,18]
list(map(lambda x: x**2,temp))
#输出结果为:
[4, 49, 196, 324]

lambda 函数式python的匿名函数,处理逻辑简单开箱即用的“一行函数”。,当然我们也可以将输入统一,具体行为或者业务不一致的code分装成函数,将具体执行各自的任务和逻辑单元。比如:

def add(x):
    return x+x

def multiply(x):
    return x*x
funcs=(add,multiply)

for i in range(5):
    print(list(map(lambda func:func(i),funcs)))
#输出为
[0, 0]
[2, 1]
[4, 4]
[6, 9]
[8, 16]

filter

filter这是一个过滤的build-in函数,它的作用主要在于过滤行为。

nums=range(-5,5)
less_than_zero=list(filter(lambda x:x<0,nums))
#输出为
[-5, -4, -3, -2, -1]

在后面的我们会介绍列表推导式也很方便,我可以改一下该例子。

list(i for i in nums if i<0)
#输出结果为同样的

reduce

reduce是将列表结果进行规约处理的,又叫“规约函数”.我们来看一下处理:

from functools import reduce
print(reduce(lambda x,y:x+y,(2,3,4,5)))
##输出为
14

set data struct

python中的set数据结构是等价于数学意义上的集合。数学意义上的集合最重要的性质有:唯一性,可重复性,无序性。那么在Python的set数据结构中数据元素也是表现如此。我们来看一个得到重复元素的例子。

str_nums=('a','a','b','c','c','c','d','e','f')
duplicates=set([x for x in str_nums if str_nums.count(x)>1])
print(duplicates)
{'a', 'c'}
当然你也可以使用collection的Counter去处理
from collections import Counter
print(Counter(str_nums))
##输出为
Counter({'a': 2, 'b': 1, 'c': 3, 'd': 1, 'e': 1, 'f': 1})

和set相关的操作自然想到交集、并集合差集。下面我们依次看一下Python提供的API。

colors=set({'red','yellow','green'})
input_colors=set({'red','blue'})
#交集API
print(input_colors.intersection(colors))
#输出
{'red'}
#差集API
print(input_colors.difference(colors))
#输出
{'blue'}
#并集API
print(input_colors.union(colors))
#输出
{'blue', 'green', 'red', 'yellow'}

值得注意的是set的定义是通过{}来定义的或者通过set()初始化来定义。

三元运算符

三元运算符和其它语言的三元运算符所表达的语义是相同的,只是形式不一样。我们来看下: condition_true if condition else condition_is_false

flag = True
print("Brian" if flag else "Not Brian")
#输出
Brian

总结

由于内容较多,所以分成三个博客篇幅来介绍。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏iKcamp

翻译连载 | 第 9 章:递归(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 第 9 章:递归(下) 栈、堆 ...

2215
来自专栏java工会

导致程序崩溃的一行代码,你有写过吗?

初学编程时,可能经常遇到一些程序崩溃的现象。一般来说,程序崩溃由于操作不当引起的。但是有时候,因为一个程序员的粗心,正式版本的程序出现崩溃状况这就很不因该了。之...

972
来自专栏TungHsu

这或许是对小白最友好的python入门了吧——2,变量和字符串

长期以来,编程界都认为刚接触一门新语言时,如果首先使用它来编写一个在屏幕上显示消息 “Hello world!” 的程序,将给你带来好运。 因为微信排版编辑问题...

2755
来自专栏JavaEdge

设计模式实战-迭代器模式

迭代器是为容器服务的,那什么是容器呢? 能容纳对象的所有类型都可以称之为容器,例如Collection集合类型、Set类型等,迭代器模式就是为解决遍历这些容器中...

2072
来自专栏Crossin的编程教室

【编程课堂】有序字典 OrderedDict

编程课堂将和每周一坑一样,成为本教室公众号的一个长期固定栏目。每期讲解一个编程知识点,包括但不限于 Python 语法、模块介绍、编程小技巧等。用简短的篇幅,让...

3658
来自专栏搞前端的李蚊子

获取Object对象的length

所有JS程序猿(甚至不止JS)都知道,数组(Array)是有length的,通过length属性,可以很方便的获取数组的长度。可以说,只要使用到了数组,就必会使...

38211
来自专栏大数据平台TBDS

Hive 时间转换函数使用心得

Hive sql 与传统的 oracle 或者mysql 的时间转换函数有一些不同,对于想将传统数据库迁移到hdfs 用 hive sql 进行处理的任务,如何...

3.2K11
来自专栏GopherCoder

Scala 学习:N-001

1605
来自专栏owent

“C++的90个坑”-阅读笔记

C++确实是一门复杂的语言。包括之前查看了一些C++11的文档和做了一些实践和总结,越来越觉得C++是门神奇的语言,也是个陷阱多多的语言。 我现在开发过程中最...

731
来自专栏灯塔大数据

干货 | 数据科学入门必读:如何使用正则表达式?

有时候,这些数据中会包含大量文本语料。比如,假如我们需要搞清楚「xxx文件 」中谁给谁发送过邮件,那么我们就要筛查 1150 万份文档!我们可以采用人工方式,亲...

1202

扫码关注云+社区