1. 函数

  函数是组织好的,可重复使用的,用来实现单一,或相关功能的代码块。

  函数分为 Python 程序内置函数,用户自定义的函数。将代码定义为函数,有如下好处:

  • 代码重用(某个特定功能复用)
  • 保持代码一致性,易维护
  • 可拓展

1.1 定义和调用函数

  使用 def 关键字定义一个函数,后面紧跟函数名,小括号也必不可少,语法如下:

def func():
函数体

  函数在执行时,首先将函数体加载到解释器中,但是不会运行,只有当调用函数后才会执行,函数名+小括号即可调用函数:

def func():
函数体
func() # 调用函数

1.2 返回值

  有时我们需要函数返回一些数据来报告执行的结果,所有就需要有返回值,只需要在函数中添加 return 关键字,后面跟着返回值即可。

def func():
return 1

  return 将返回值传递给函数本身,我们只要调用函数,再将函数赋值给变量即可获得返回值:

def func():
return 1
res = func() # 获得返回值,并赋值给变量 res
print(res) 1

  返回值可以是 0 个,也可以是 1 个 或多个:

  • 没有返回值,返回 None
  • 一个返回值,返回 返回值
  • 多个返回值,返回一个元组
def func():
# return
# return 1
return 1, 2
res = func()
print(res) None
1
(1, 2)

1.3 函数参数

  函数的参数可以用函数实现个性化,大致分为两类:

  • 形参:函数在定义时定义的参数
  • 实参:函数在调用时传入的参数

  形参只有在调用时才分配内存单元,调用结束,就释放。仅在函数内部有效,不能在函数外部使用。

  实参可以是常量、变量、表达式、函数,占用内存空间。

1.3.1 默认参数

  形参又分为:默认参数、位置参数、关键字参数以及可变长参数,而默认参数即在函数定义时默认赋予某个形参一个值。若函数调用时,不传入实参,函数使用默认值,否则使用实参。

def func(x=2):		# x 默认为 2
return x + 2
res = func() # 即使不传入实参函数也能正常运行
print(res)

1.3.2 位置参数和关键字参数

  普通的参数即为位置参数,在调用时实参必须与形参一一对应。而关键字参数,可以不用考虑位置的关系,只需要名字相同即可。

def func(name, words):
print(name: words)
func('Hello', words='world') # 第一个为位置参数,第二个为关键字参数
func(words='World', name='Hello') # 不用考虑位置

Tips:位置参数必须在关键字参数后面

1.3.3 可变长参数

  可变长参数是一种参数组,它可以是多个参数,只需要在参数前加上星号(*)即可。它可以增加函数可拓展性,当你不知道定义的函数需要定义几个参数时,使用它很方便。

  可变长参数分为:*args 和 **kwargs两类:

  • *agrs:将参数们收集起来,打包成一个元组,再一一传递给函数使用
  • **kwargs:将参数们收集并打包成一个字典

*args

  *args 、**kwargs 是 Python 官方定义的参数名,也可以是其他名字,但是最好使用它,以便于辨认。

def func(*args):
print(args)
print('有 %d 个参数' % len(args))
print('第三个参数是:', args[2])
func('P', 'y', 't', 'h', 'o', 'n')
func('Python', 123, '爬虫')
('P', 'y', 't', 'h', 'o', 'n')
有 6 个参数
第三个参数是: t
('Python', 123, '爬虫')
有 3 个参数
第三个参数是: 爬虫

Tips:如果可变长参数后面还有参数,要将其定义为关键字参数,否则会被收集成可变长参数里面。建议在使用可变长参数时,可将其他参数设置为默认参数,或关键字参数,这样不易混淆。

def func(*args, extra=16):
# def func(*args, extra):
print(args)
print(extra)
func(1,2,3)
#func(5,6, extra=18) (1, 2, 3)
16 (5, 6)
18

  星号(*)既可用来收集打包参数,也可以用来“解包”参数。当传入的参数时列表、元组、字典以及集合时,可变长参数将会将其整个打包成只有一个元组的参数,而在其前面添加一个星号( *),就可以将里面的元素一个个都解出来。

def func(*args):
print(args) l = [1, 2, 3]
t = (4, 5, 6)
d = {'name':'rose', 'age': 18}
func(l)
func(*l)
func(t)
func(*t)
func(d)
func(*d)
([1, 2, 3],)
(1, 2, 3)
((4, 5, 6),)
(4, 5, 6)
({'name': 'rose', 'age': 18},)
('name', 'age')

**kwargs

  另一种可变长参数就是 **kwargs,它将传入的实参打包成一个字典,同样地也支持 “解包”。

def func(x, **kwargs):
print(x)
print(kwargs)
print('总共有 %d 个参数' % len(kwargs))
print('这些参数分别为:', kwargs) func(20, name='rose', age=18)
20
{'name': 'rose', 'age': 18}
总共有 2 个参数
这些参数分别为: {'name': 'rose', 'age': 18}

  解包,当传入的参数是字典时:

def func(gender, **kwargs):
print(gender)
print(kwargs)
print('总共有 %d 个参数' % len(kwargs))
print('这些参数分别为:', kwargs) t = {'name': 'rose', 'age': 18}
func('female', **t)
female
{'name': 'rose', 'age': 18}
总共有 2 个参数
这些参数分别为: {'name': 'rose', 'age': 18}

  当既有 *args,又有 **kwargs,以及位置参数和位置参数时:

def func(gender, country='China', *args, **kwargs):
print(gender, country)
print(args)
print(kwargs)
func('male', 'America', 20, 30, name='rose', age=19)
male America
(20, 30)
{'name': 'rose', 'age': 19}

1.4 函数文档

  函数文档即用来描述函数功能的文档,可以让别人更好地理解你的函数,定义函数文档是个好的习惯。

def func(x):
"""
计算一个数加一
:param x:
:return:
"""
x += 1
return x
res = func()

1.5 函数变量

1.5.1 函数和过程

  在 Python 中函数和过程是分开的,函数(function)与过程(procedure)的区别:

  • 函数:有返回值
  • 过程:简单、特殊且无返回值

  严格来说 Python 没有过程,只有函数,因为即使没有返回值,也会默认返回一个 None。

def func():
print('Hi')
res = func()
print(res) Hi
None

1.5.2 函数变量的作用域

  变量的作用域即变量可见性,也就是可用范围,一般编程语言分为:全局变量(global variable)和局部变量(local variable)。

  • 全局变量:程序开始定义时定义的变量,在函数外部,无缩进,作用域为整个程序
  • 局部变量:在子程序中(一般为函数)定义的变量,函数内部,有缩进,作用域是整个子程序

当全局变量与局部变量同名是,在子程序中局部变量起作用,在外面全局变量起作用。

# 首先加载整个函数(不执行),调用函数执行函数内部,打印 tom,最后打印 rose
name = 'rose' # 全局
def test():
name = 'tom' # 局部
print(name)
test()
print(name) tom
rose

  1. global 关键字

  全局变量的作用域是整个程序,函数内部亦可访问。但是不要在函数内部试图修改全局变量,这是因为 Python 使用了屏蔽(shadowing)的方式去 保护全局变量。一旦在函数内部修改,则会在函数内部创建一个一模一样的局部变量。

name = 'rose'
def test():
name = 'tom'
print(name)
test()
print(name) tom
rose

  从上面例子可以看出,全局变量的值没有改变。但是 Python 是支持在函数内部修改全局变量的,只需要在变量前面加上一个 global 关键字即可:

name = 'rose'
def test():
global name
name = 'tom'
print(name)
test()
print(name) tom
tom

总结:当全局与局部变量名字相同时,函数内部优先读取局部变量。为了更好地区分全局与局部变量,一般地全局变量名尽量使用大小,局部变量名使用小写。

  2. 内嵌函数

  函数支持嵌套,即一个函数中嵌套另外一个函数,这种函数叫内嵌函数或内部函数。

name = 'rose'		# (1)
def fun1(): # (2)
name = 'tom' # (5)
def fun2(): # (6)
name = 'lila' # (8)
fun2() # (7)
print(name) # (9) print(name) # (3)
fun1() # (4)
print(name) # (10) rose
tom
rose

Tips:内部函数只能在内部调用,外部调用会报 NameError

1.5.3 闭包

  闭包(closure)是函数式编程中的一个重要数据结构,Python 中认为如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么这个内部函数就是闭包(closure)。

def fun1(x):
def fun2(y):
return x * y
return fun2
a = fun1(6) # a 接收的是 fun2() 的内存地址
print(a)
b = a(5) # a(5) 相当于调用 fun2()
print(b) # 上述可以简写
# res = fun1(6)(5)
# print(res) <function fun1.<locals>.fun2 at 0x00000000026F48C8>
30

  从上面的例子可以看出,内部函数 fun2()对外部函数 fun1()的变量 x (不是全局变量)进行了引用,那么 fun2()即是闭包。

  nonlocal 关键字

  但需要注意的是不能在外部函数外面调用内部函数,对外部函数的局部变量只能进行访问,不能修改。

def fun1():
name = 'rose'
def fun2():
name = 'tom'
return name
print(name)
return fun2
fun1()() rose # 外部函数局部变量 name = ‘rose' 并没有被修改

  如果在内部函数中想修改外部函数的局部变量可以用 nonlocal 关键字,但是需要注意的是它不能修改全局变量。

def fun1():
name = 'rose'
def fun2():
nonlocal name # 添加 nonlocal 关键字
name = 'tom'
return name
print(name)
return fun2
fun1()() tom # 外部函数局部变量 name = ‘rose' 已经被修改

1.6 函数即变量

  Python 程序按程序执行,遇到函数,先加载到到内存,只有当调用函数时,才会运行函数体。因此一个函数可以作为 变量在另一个函数内部调用执行,前提是第一个函数需要先加载。

  首先加载 f1()、f2(),再调用 f1(),执行 f1()里的函数体,最后调用 f2(),执行 f2()里的函数体:

def f1():			# (1)
print('from f1') # (4)
f2() # (5)
def f2(): # (2)
print('from f2') # (6)
f1() # (3) from f1
from f2

  另一种情况:

def f2():
print('from f2')
def f1():
print('from f1')
f2()
f1() from f1
from f2

  第三种情况,调用 f2()时,因为 函数 f2()还未加载,导致出错(NameError: name 'f2' is not defined):

def f1():
print('from f1')
f2()
def f2():
print('from f2')
f1()

1.7 递归函数

  在函数内部,可以调用其他函数,如果在调用过程中直接或间接调用自身,那么这个函数就是递归函数。

  递归函数特征:

  • 必须有明确的结束条件(否则死循环)
  • 每次进入更深一次递归时,问题规模比上一次都应有所减少
  • 递归效率不高,层次过多容易导致 栈溢出

函数调用是通过栈(stack)实现,每调用一次,栈就会增加一层栈帧,函数返回,则减少一层。由于栈的大小有限,所有递归过多,就会导致栈溢出。

def func(n):
print(n)
if int(n/2) == 0: # 结束条件
return n
res = func(int/2) # 调用自身
return res
func(10) 10,5,2,1

1.7.1 示例

  递归问路

  使用递归函数,实现一次递归问路操作。

import time
person_list = ['rose', 'tom', 'lila', 'json', 'john']
def ask_way(person_list):
"""
问路操作
:param person_list: 被问的人
:return:
"""
print('-'*60)
if len(person_list) == 0:
return '没人知道'
person = person_list.pop()
if person == 'json':
return '%s 我知道 xxx 怎么走,它在 xxx' % person
print('你好,%s,请问 xxx 在哪里?' % person)
print('%s 回答道:我也不知道,我帮你去问问 %s' % (person, person_list))
time.sleep(2)
res = ask_way(person_list)
return res
res = ask_way(person_list)
print(res)
------------------------------------------------------------
你好,john,请问 xxx 在哪里?
john 回答道:我也不知道,我帮你去问问 ['rose', 'tom', 'lila', 'json']
------------------------------------------------------------
json 我知道 xxx 怎么走,它在 xxx

  二分查找

data = [1,3,6,7,9,12,14,16,17,18,20,21,22,23,30,32,33,35]
def find_num(data, num):
"""
使用二分查找法,查找出一个数字的位置
"""
print(data)
if len(data) > 1:
mid = int(len(data)/2)
if data[mid] == num:
print('找到数字', data[mid])
elif data[mid] > num:
print('要找的数字在 %s 右边' % data[mid])
return find_num(data[0:mid], num)
else:
print('要找的数字在 %s 左边' % data[mid])
return find_num(data[mid+1:], num)
else:
if data[0] == num:
print('找到数字', data[0])
else:
print('要找的数字不在列表中')
find_num(data, 66)
[1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]
要找的数字在 18 左边
[20, 21, 22, 23, 30, 32, 33, 35]
要找的数字在 30 左边
[32, 33, 35]
要找的数字在 33 左边
[35]
要找的数字不在列表中

1.7.2 尾调用

  尾调用又称为为递归,指的是函数在最后一步调用另一个函数的过程(最后一行不一定是最后一步)。

# bar 在 foo 内为尾调用
def bar(n):
return n
def foo(m):
return bar(m)
# bar 在 foo 内不是尾调用,最后一步为 return y
def bar(n):
return n
def foo(m):
y = bar(m)
return y
# bar1、bar2 在 foo 内都是尾调用
def bar1(n):
return n
def bar2(n):
return n+1
def foo(x):
if type(x) is str:
return bar1(x)
elif type(x) is int:
return bar2(x)

  尾调用优化

  定义 a 函数,a 内调用 b,b 调用 c,在内存中形成一个调用记录,又称为调用帧(call frame)。用于存储调用位置和内部变量等信息,即(a——b——c),直至 c 返回结果给 b,c 的调用记录消失。b 返回给 a,b 的调用记录消失,a 返回结果,a 的调用记录消失,所有记录都是先进后出,形成一个调用栈(call stack)

1.8 匿名函数

  匿名函数即不需要显示地指定函数名的函数,Python 允许使用 lambda 关键字来创建一个匿名函数,匿名函数也被称为 lambda 表达式。

lambda x:x+2
lambda x,y,z:(x+1, y+1, z+1) # 多个参数

  冒号左边是原函数参数,可以有多个参数,逗号分隔即可,冒号右边为返回值。对于有些结构比较简单的函数,可以直接定义为匿名函数:

def func(x):
return x+2
s = func(3)
print(s)

  上述函数可直接定义一个匿名函数:

f = lambda x:x+2
f(3) # 调用

  匿名函数常与其他函数搭配使用:

# 将 匿名函数当做参数传入 calc 中
def calc(func, li):
ret = []
for i in li:
res = func(i)
ret.append(res)
return ret
li = [2, 3, 4, 6, 8]
calc(lambda x:x+1, li) [3, 4, 5, 7, 9]

  lambda 表达式的作用:

  • 执行一些脚本时,省略定义函数过程
  • 对于整个程序只需要执行一两次的函数,不用考虑命名问题
  • 简化代码步骤

2. 函数式编程

2.1 编程论

  当今编程的三种方法论:

  • 面向过程:
  • 函数式编程:特征(无变量、函数即变量)
  • 面向对象:

  函数式编程(函数+数学函数),更贴近数学,是一种抽象成都很高的编程范式,不允许函数有变量。但 Python 不是严格意义上的函数式编程,因为它允许有变量。

  函数式编程特点:

  • 函数即变量(一个函数作为参数传入另一个函数)
  • 返回值是函数(可以函数本身,也可以是别的函数)

  函数即变量

def foo(n):
print(n)
def bar(name):
print(name)
foo(bar('rose')) rose
None

  上面例子中,bar('rose') 打印 rose,没有返回值,因此 foo(bar('rose'))相当于 foo(None)

  返回值是函数

  返回函数本身:

def handle():
print('from handle')
return handle # 返回函数本身内存地址
h = handle() # 使用变量 h 接收
h() # 再调用函数本身 from handle
from handle

  返回别的函数:

def test():
print('from test')
def test1():
print('from test1')
return test # 返回 test 函数的内存地址
n = test1() # 接收
n() # 相当于调用 test()

2.2 高阶函数

  函数式编程的两个特征:函数即变量,返回值是函数,只需满足其中一个条件,即可成为高阶函数。

def add(x, y, f):
return f(x)+f(y)
print(add(-5, 6, abs)) 11

  上面例子中,内置函数 abs 作为参数传入函数 add。

2.2.1 map 函数

  map(function, sequence) 函数是高阶函数的一种,它有两个参数:第一个为函数,另一个接收一个序列。

  其作用是将序列中每个元素(for 循环),作为函数参数传入第一个参数中,直至序列中每个元素都被循环,返回一个迭代器对象,用 list 可获得结果。

# 对列表 l 中每个元素加 1
li = [2, 3, 4, 5, 6]
def add_one(x):
return x+1
res = map(add_one, li)
print(res)
print(list(res)) <map object at 0x0000000002C5C0B8>
[3, 4, 5, 6, 7]

  上面例子中 map 函数将列表 li 的每个中每个元素取出,再传入 add_one 中。

  同样地也可以使用 lambda 表达式与 map 函数简写:

res = map(lambda x:x+1, li)

  传入两个列表:

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

2.2.2 filter 函数

  filter(function or None, iterable)函数有两个参数:第一个可以是函数也可以是 None,第二个为可迭代对象。

  • 第一个参数为函数:将序列中每个元素取出作为参数,传入第一个参数中,判断,并把为 True 的值返回
  • 第一个参数为 None:将序列中为 True 的元素返回

  第一个参数为函数:

# 过滤掉以 123 结尾的名字
names = ['rose_123', 'lila_123', 'john']
def filter_123(x):
return not x.endswith('123') # 返回没有以 123 结尾的名字
res = filter(filter_123, names)
list(res) john

  使用 lambda 表达式简写:

res = filter(lambda x: not x.endswith('123'), names)
list(res)

  第一个参数为 None:

res = filter(None, [1, 2, 0, True, False])
list(res) [1, 2, True]

2.2.3 reduce 函数

  reduce(function, sequence[, initial])函数三个参数:第一个为函数,第二个为序列,第三个可选为初始值。

  Python3 把 reduce 函数集成到 functools 模块中,因此每次使用时,需要from functools import reduce。它可以把一个函数作用在一个序列上,这个函数必须接收两个参数。首先将序列中的前两个元素取出,传入函数中,返回值再与序列中接下来的元素做累积计算,直至序列中的每个元素都被循环。

  求列表中所有元素的乘积:

  常规:

nums = [1, 2, 3, 100]
def reduce_test(func, array):
res = array.pop(0)
for i in array:
res = func(res, i)
return res
s = reduce_test(lambda x,y: x*y, nums)
print(s) 600

  reduce:

from functools import reduce

nums = [1, 2, 3, 100]
res = reduce(lambda x,y : x*y, nums)
print(res) 600

  首先将 nums 前两个元素,即 1、2 传入lambda x,y: x*y中,返回 x*y。再将 3 传入,最后将 100 传入,相当于(((1*2)*3)*100)

指定初始值:

from functools import reduce

nums = [1, 2, 3, 100]
res = reduce(lambda x,y : x*y, nums, 6) # 相当于 (((6*1)*2)*3)*100
print(res) 3600

  累加计算:

from functools import reduce

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

15

2.2.4 sorted 函数

  排序算法在程序中是经常用到的算法,无论是冒泡还是快排,其核心都是比较两个元素的大小。

  • 数字:直接比较
  • 字符串/字典:需要用函数抽象出来比较

  sorted(iterable, key, reverse)函数也是一个高阶函数,在列表内置方法中我们就已经接触到了,它可以对一个列表进行排序,默认从小到大。

sorted([1, -3, 2])

[-3, 1, 2]

  此外,它还接收一个 key 函数来自定义排序,key 函数作用在列表中的每个元素上,再进行比较,如按绝对值排序:

sorted([1, -3, 2], key=abs)

[1, 2, -3]

  第三个参数 reverse,可以反向排序:

sorted([1, -3, 2], key=abs, reverse=True)

[-3, 2, 1]

  上面都是针对数字的排序,直接比较其大小即可。但是对于字符串来说,一般地都是比较其首字母在 ASCII 中的大小:

sorted(['b', 'a', 'Z'])		# 因为在 ASCII中 Z<a

['Z', 'a', 'b']

  现在我们不想按照 ASCII 来排序,而是按照字母表排序,那么我们可以通过指定 key 函数,将所有字符串转换为大写或小写即可实现:

sorted(['b', 'a', 'Z'], key=str.upper)

['a', 'b', 'Z']

2.2.5 偏函数

  functools 模块提供了很多功能,其中一个就是偏函数(partial )。

  当函数的参数个数太多,需要简化时,使用 functools.partial 创建一个偏函数,这个新的函数可以固定住原函数的部分参数,从而调用更简单。

语法结构:

from functools import partial

func2 = partial(func, *args, **kwargs)	# 第一个参数:要固定的函数,第二个:原函数的位置参数,第三个:关键字参数

  第一个参数可以是自定义的函数,也可以是内置函数。

  int() 函数可以把字符串转换为整型,默认按照十进制转换:

>>> int('123')
123

  int() 函数还额外提供一个 base 参数,如果传入 base,就可以做 N 进制转换:

>>> int('123', base=8)		# 按照八进制转换
83

内置函数

  假如要转换大量的二进制字符串,每次都要传入 base,就会很繁琐。我们可以利用偏函数(partial)将 base=2 固定住,定义一个新的函数,每次只需要传入要转换的字符串即可:

>>> from functools import partial

>>> int2 = partial(int, base=2)		# 将 base = 2 固定住
>>> int2('100') # 相当于 kw={'base': 2} int('100', **kw)
4

自定义函数

  当我们调用某个函数,已知某个参数的值时,可以将其固定住(相当于设定默认值):

from functools import partial

def add(x, y):
return x % y
add2 = partial(add, 5) # 自动将 5 作为 *args 的一部分放在最左边,也就是 5 % 100
print(add2(100)) # 101

2.2.6 练习

  将列表中年龄小于等于 18 岁的人过滤出来。

people = [
{'name': 'rose', 'age': 18},
{'name': 'lila', 'age': 30},
{'name': 'tom', 'age': 60}
] res = filter(lambda p: p.get('age') <= 18, people)
print(list(res)) [{'name': 'rose', 'age': 18}]

3. 内置函数

  函数分为 Python 内置函数和自定义函数,内置函数有很多,但是真正能用到的也比较少。

# abs():求一个数字的绝对值
>>> abs(-5)
5 # all(iterable):判断序列中所有元素是否为 True,如果序列为空,也返回 True,返回布尔值
>>> all([1, 2, 0])
False # any(iterable):序列中元素 bool(x),只要有一个为 True,则返回 True,如果序列为空,返回 False
>>> any([])
False
>>> any(['', 0, 1])
True # bin(number):十进制转二进制
>>> bin(10)
'0b1010' # hex(number):十进制转十六进制
>>> hex(10)
'0xa' # bool():转换为布尔类型
>>> bool(0)
False
>>> bool(None)
False
>>> bool('')
False # bytes(obj,encoding=None):将对象编码(二进制)
# bytes(obj,encoding=None).decode(None):解码,用什么编码就应用什么解码
>>> name = '你好'
>>> bytes(name, encoding='utf-8')
b'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> bytes(name, encoding='utf-8').decode('utf-8')
'你好' # chr(i):返回一个数字在 ASCII 中对应的值
>>> chr(90)
'Z' # ord(obj):查询一个字符咋 ASCII 中的对应的数字
>>> ord('Z')
90 # dict():创建一个字典
>>> d = dict()
>>> type(d)
<class 'dict'> # dir(obj):返回一个对象的所有方法名字
>>> dir(str) # help(obj):查看帮助文档
>>> help(list.append)
Help on method_descriptor: append(...)
L.append(object) -> None -- append object to end # dirmod(x,y):返回一个元组,结果为 x/有的商和余数,一般用作网页分页
>>> divmod(10, 3)
(3, 1) # id(obj):查看一个对象的内存地址
>>> id(10)
1750035808 # globals():查看全局变量
# locals():查看局部变量 # pow(x,y[,z]):幂运算,z 可选, pow(x,y,z)相当于 (x**y)%z
>>> pow(10, 3)
1000
>>> pow(10, 3, 4)
0 # reversed(iterable):反转一个序列
>>> list(reversed('abc'))
['c', 'b', 'a']
>>> list(reversed([1, 2, 3]))
[3, 2, 1] # round(number,ndigits):四舍五入,保留几位有效小数
>>> round(4.5)
4
>>> round(4.564, 2)
4.56 # set(iterable):转换成集合、创建一个集合
>>> set('123')
{'2', '3', '1'}
>>> s = set()
>>> type(s)
<class 'set'> # slice(statr,stop[,step]):序列切片/分片
>>> l = 'hello'
>>> s = slice(2, 3)
>>> l[s]
'l' # str():转换为字符串
>>> str(123)
'123' # sum(iterable, start=0):求序列中所有元素的和,还可指定
>>> l = [1, 2, 3, 4]
>>> sum(l)
10
>>> sum(l, 1)
11 # tuple():转换为元组
>>> tuple(['a', 1])
('a', 1) # vars(obj):返回对象的属性和属性值的字典对象。
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'name': '你好', 'd': "{'name:': '
rose'}", 's': slice(2, 3, None), 'p': {'name': 'rose', 'age': 18, 'gender': 'male'}, 't': <zip object at 0x0000000002D9FF08>, 'i': ('c', 3), 'age': {'rose': 18, 'tom': 19}, 'li': 'hello', 'l': [1, 2, 3, 4]}
>>> vars(str)
.... # __import__():当模块名是字符串是,可以使用。
>>> module_name = 'test'
>>> __import__(module_name)
<module 'test' from 'C:\\Users\\HJ\\Anaconda3\\lib\\test\\__init__.py'>
>>> import module_name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'module_name'

  1. eval()

  eval(expression,[globals[,locals]),用于执行一个字符串表达式,并返回表达式值,可以去掉字符串的引号

>>> d = "{'name:': 'rose'}"
>>> type(d)
<class 'str'>
>>> s = eval(d)
>>> type(s)
<class 'dict'>

  字符串中表达式的值,也可以计算:

>>> express = '1*2+3'
>>> eval(express)
5

  2. hash()

  hash(obj)做哈希运算,不管对象有多长,经过哈希运算后的值长度都相同,也不能根据 hash 值反推出原始对象。

  可用于校对软件/文件是否被别人篡改,还可用于判断软件或文件是否下载完整(检验官方给出的 hash 值与自己下载完毕 hash 的值是否相同)

  • 可哈希数据类型:即不可变数据类型,如:字符串、元组
  • 不可哈希数据类型:即可变数据类型,如:列表、字典、集合
>>> hash('abc')
5994226220732616244
>>> hash('123')
-3466646395452377901

  3. isinstance()、type()

  两个都是用于判断数据类型,官方建议使用 isinstance。

>>> type(123)
<class 'int'>
nums = '123'
if type(nums) is str:
res = int(nums) + 1

  isinstance(x,A_tuple)有两个参数:第一个是待确定类型的数据,第二个是指定一个数据类型,判断两者是否一致,返回一个布尔值。

>>> isinstance(123, int)
True

  4. zip()

  zip(ite1[,iter2[...]])函数接收两个序列,要求它们元素数据相等,返回两个序列元素一一对应的元组(返回的是 zip 对象的内存地址)。

>>> p = {'name': 'rose', 'age': 18, 'gender': 'male'}
>>> t = zip(p.keys(), p.values())
>>> list(t)
[('name', 'rose'), ('age', 18), ('gender', 'male')]
>>> list(zip(['a', 'b', 'c'], [1, 2, 3]))
[('a', 1), ('b', 2), ('c', 3)] >>> for i in zip(['a', 'b', 'c'], [1, 2, 3]):
... print(i)
...
('a', 1)
('b', 2)
('c', 3)

  5. max()、min()

  max(iterable, key, default)、min()返回一个序列中的最大、小元素。

  特性:

  • 原理是将序列中每个元素都循环遍历出来比较
  • 首先比较第一个字符,分出大小则停止比较,若分出,钻继续比较。不同数据类型不能比较
  • 字典比较,默认比较 key
>>> max([1, 2, 3])
3
>>> max(['a', 'b'])
'b'
>>> max(['a12', 'a2']) # a 相同,2>1
'a2' # b>a
>>> max(['a12', 'b10'])
'b10' >>> age = {'rose': 18, 'tom': 19} # 字典比较默认比较 key
>>> max(age)
'tom' >>> max(zip(age.values(), age.keys())) # 既比较大小,又把名字也打印出来
(19, 'tom')

  max()还可以指定比较方法:

# 取出 age 比较
>>> people = [
{'name': 'rose', 'age': 18},
{'name': 'lila', 'age': 30},
{'name': 'tom', 'age': 60}
] >>> max(people, key=lambda dic:dic.get('age'))
{'name': 'tom', 'age': 60}

Python开发【第五篇】:函数的更多相关文章

  1. Python开发第五篇

    面向对象程序设计 面向过程编程:就是分析问题的解决步骤,按部就班的编写代码解决问题 函数式编程:就是把代码封装到函数中,然后在使用时调用封装好的函数 面向对象编程:把一类事物所共有的属性和行为提取出来 ...

  2. Python开发【第一篇】:目录

    本系列博文包含 Python基础.前端开发.Web框架.缓存以及队列等,希望可以给正在学习编程的童鞋提供一点帮助!!! Python开发[第一篇]:目录 Python开发[第二篇]:初识Python ...

  3. Python开发【第二篇】:初识Python

    Python开发[第二篇]:初识Python   Python简介 Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏 ...

  4. Python开发【第一篇】:目录

    本系列博文包含Python基础.前端开发.Web框架.缓存以及队列等,希望可以给正在学习Python编程的朋友们提供一点帮助! .Python开发[第一篇]:目录 .Python开发[第二篇]:初始P ...

  5. 【python自动化第五篇:python入门进阶】

    今天内容: 模块的定义 导入方法 import的本质 导入优化 模块分类 模块介绍 一.模块定义: 用来在逻辑上组织python代码(变量,函数,逻辑,类):本质就是为了实现一个功能(就是以.py结尾 ...

  6. Python开发【第九篇】:进程、线程

    什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于,程序是指令的集合,它是进程运行的静态描述文本 ...

  7. Python开发【第一篇】基础题目二

    1 列表题 l1 = [11, 22, 33] l2 = [22, 33, 44] # a. 获取l1 中有,l2中没有的元素 for i in l1: if i not in l2: # b. 获取 ...

  8. Python开发【内置函数篇】re正则表达式

    一.简介 正则表达式本身是一种小型的.高度专业化的编程语言,而在python中,通过内嵌集成re模块,程序媛们可以直接调用来实现正则匹配.正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎 ...

  9. python开发第四篇:函数(1)

    函数 阅读目录 一 函数知识体系 二 函数基础 三 函数对象.函数嵌套.名称空间与作用域.装饰器 四 迭代器.生成器.面向过程编程 五 三元表达式.列表推导式.生成器表达式.递归.匿名函数.内置函数 ...

  10. Python开发【第一篇】Python基础之函数递归

    函数递归 递归的本质: 就是一个函数调用另外一个函数. def d(): return '123' def c(): r = d() return r def b(): r = c() return ...

随机推荐

  1. Oracle备份和恢复

    --什么是脱机备份 脱机备份也叫冷备份,首先管理员使用 shutdown immediate 命令关闭数据库的服务. 之后复制需要的文件,包括数据文件和控制文件等相关内容复制到磁盘的其他位置.当 数据 ...

  2. python_unittest详解

    一 整体结构概览 unittest原名为PyUnit,是由java的JUnit衍生而来.对于单元测试,需要设置预先条件,对比预期结果和实际结果. 整体结构:unittest库提供了test cases ...

  3. TYOI Day1 travel:Tree dp【处理重复走边】

    题意: 给你一棵树,n个节点,每条边有长度. 然后有q组询问(u,k),每次问你:从节点u出发,走到某个节点的距离mod k的最大值. 题解: 对于无根树上的dp,一般都是先转成以1为根的有根树,然后 ...

  4. scanf和cin的返回值

    需要连续从标准输入读取数据时,可以采用下面两种不同的方式判断文件结束: [cpp] view plaincopy   int i; while(scanf("%d",&i) ...

  5. Selenium-js弹窗浮层

    学习过js的小伙伴会发现,我们在一些实例中用到了alert()方法.prompt()方法.prompt()方法,他们都是在屏幕上弹出一个对话框,并且在上面显示括号内的内容,使用这种方法使得页面的交互性 ...

  6. FFmpeg基础知识之————H264编码profile & level控制

    H.264有四种画质级别,分别是baseline, extended, main, high: 1.Baseline Profile:基本画质.支持I/P 帧,只支持无交错(Progressive)和 ...

  7. Excel文本获取拼音

    [说明] 版本:Excel 2010 文件后缀:.xls 有在.xlsb文件下使用未成功.建议使用.xls后缀. 1.调出“开发工具” 步骤:文件-->选项-->自定义功能区-->勾 ...

  8. Access中创建子数据表/主子数据表

    摘 要:我们为什么要使用Access,而不用Excel,因为数据库可以大幅度地消除冗余数据,其方法就是将数据拆分到不同的表中,再通过“关系”建立表间的联系.那么如何确定表间的关系呢.表之间的关系是通过 ...

  9. BZOJ2548:[CTSC2002]灭鼠行动

    我对模拟的理解:https://www.cnblogs.com/AKMer/p/9064018.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

  10. BZOJ1727:[Usaco2006 Open]The Milk Queue挤奶队列

    我对\(Jhonson\)算法的理解:https://www.cnblogs.com/AKMer/p/9863620.html 题目传送门:https://www.lydsy.com/JudgeOnl ...