目录
Hello,你好呀,我是灰小猿!一个超会写bug的程序猿!
最近和大家总结了几期有关Python基础入门和常见报错解决的相关文章,得到了很多小伙伴的支持,同时Python基础入门相关的内容也算是和大家总结得差不多了,有想学习或参考的小伙伴可以看以下几篇文章:
Python基础入门:
万字长文爆肝Python基础入门【第二弹、超详细数据类型总结】
常见报错及解决:
全网最值得收藏的Python常见报错及其解决方案,再也不用担心遇到BUG了!
今天就继续来和大家分享有关Python进阶中函数和类使用的相关内容,同时之后还会继续更新,感兴趣的小伙伴可以关注一起学习呀!
Python 中内置有很多常用的函数,这些函数无需从模块中导入,可直接使用。由于内置函数有六七十个之多,
故这里不一一介绍,只介绍一些最常用的,有关其他详细的内置函数大家可以参考这里“菜鸟教程—Python内置函数”。
内置函数 | 功能 | 示例 | 示例结果 |
---|---|---|---|
dict() | 将参数转换为字典类型 | dict(a=1, b=2, c=3) | {'a': 1, 'b': 2, 'c': 3} |
float() | 将字符串或数字转换为浮点型 | float('0.22') | 0.22 |
int() | 将字符串或数字转换为整数型 | int(1.23) | 1 |
list() | 将元组、字符串等可迭代对象转换为列表 | list('abc') | 'a', 'b', 'c' |
tuple() | 将列表、字符串等可迭代对象转换为元组 | tuple(1, 2, 3) | (1, 2, 3) |
set() | 1.创建空集合;2.将可迭代对象转换为列表集合 | set('abc') | {'b', 'a', 'c'} |
str() | 将参数转换为字符串 | str(3.14) | '3.14' |
bytes() | 将参数转换为字节序列 | bytes(4) | b'\x00\x00\x00\x00 |
扩展:上表中的函数严格来讲并不是函数,而是类,只是其命名风格和使用方式和函数类似。 可迭代对象:如列表、元组、字符串、集合、字典等。关于可迭代对象的使用计划在下一篇和大家分享。
内置函数 | 功能 | 示例 | 示例结果 |
---|---|---|---|
max() | 求最大值 | max(13, 2, 0.6, -51, 7) | 13 |
min() | 求最小值 | min(13, 2, 0.6, -51, 7) | -51 |
sum() | 求和 | sum(13, 2, 0.6, -51, 7) | -28.4 |
abs() | 求绝对值 | abs(-51) | 51 |
pow() | 求次方 | pow(2, 10) | 1024 |
bin() | 转换为二进制 | bin(77) | '0b1001101' (注意结果为字符串) |
hex() | 转换为十六进制 | hex(77) | '0x4d' (注意结果为字符串) |
round() | 浮点数四舍五入 | round(4.5678, 2) (第二个参数为小数精度) | 4.57 |
内置函数 | 功能 |
---|---|
bool() | 判断参数是否为真,为真则返回 True,否则返回 False。「为真」指的是,表达式的结果为布尔值 True,或非零数字,或非空字符串,或非空列表 |
all() | 如果可迭代对象中的所有值,在逐一应用 bool(值) 后结果都为 True,则返回 True,否则返回 False |
any() | 如果可迭代对象中的任意一个或多个值,在应用 bool(值) 后结果为 True,则返回 True,否则返回 False |
关于上述三个函数的使用可以看下面的实例:
bool(2) True bool(0) False bool(1, 2, 3) True bool([]) False bool(‘abc’) True bool(’’) Falseall([‘a’, 1, 1]) True all([‘a’, 0, 1]) Falseany([’’, 0, []]) False any([‘a’, 0, []]) True
IO 即输入输出。
内置函数 | 功能 |
---|---|
input() | 从标准输入中读取字符串 |
print() | 将内容写入标准输出中 |
open() | 打开一个文件。之后便可以对文件做读写操作。详见 IO 操作章节 |
内置函数 | 功能 |
---|---|
type() | 获取对象的类型 |
isinstance() | 判断对象是否是某个类(或其子类)的对象 |
dir() | 获取类或对象中的所有方法和属性;无参数时获取当前作用域下的所有名字 |
id() | 返回一个对象的唯一标识。在我们所使用的 CPython 中这个唯一标识实际为该对象在内存中的地址 |
type()
示例:
numbers = 1, 2, 3 type(numbers) <class ‘list’>
isinstance()
示例:
numbers = 1, 2, 3 isinstance(numbers, list) True isinstance(numbers, str) False
也可以把多个类型放在元组中,其中一个与对象的类型相符即为 True
,若无相符则为 False
。如:
numbers = 1, 2, 3 isinstance(numbers, (list, str)) True
dir()
示例:
dir(list) ’__add__’, ‘__class__’, ‘__contains__’, ‘__delattr__’, ‘__delitem__’, ‘__dir__’, ‘__doc__’, ‘__eq__’, ‘__format__’, ‘__ge__’, ‘__getattribute__’, ‘__getitem__’, ‘__gt__’, ‘__hash__’, ‘__iadd__’, '__imul__, ‘__init__’, ‘__init_subclass__’, ‘__iter__’, ‘__le__’, ‘__len__’, ‘__lt__’, ‘__mul__’, ‘__ne__’, ‘__new__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__reversed__’, ‘__rmul__’, ‘__setattr__’, ‘__setitem__’, ‘__sizeof__’, ‘__str__’, ‘__subclasshook__’, ‘append’, ‘clear’, ‘copy’, ‘count’, ‘extend’, ‘index’, ‘insert’, ‘pop’, ‘remove’, ‘reverse’, ‘sort’
id()
示例:
number = 1 id(number) 4411695232numbers = 1, 2, 3, 4 id(numbers) 4417622792
解释器交互模式下获取某个函数、类的帮助信息,非常实用。
比如查看内置函数 any()
的用法:
help(any) # 只需使用函数名字
将显示出 any()
的帮助信息:
Help on built-in function any in module builtins:
any(iterable, /)
Return True if bool(x) is True for any x in the iterable.
If the iterable is empty, return False.
(END)
按下
q
键退出上述界面。
对于这个章节中的内置函数,如果你有不清楚的地方,便可以用 help()
来查看使用说明。
对可迭代对象中的数据进行排序,返回一个新的列表。
numbers = (4, 5, 2, 8, 9, 1, 0) sorted(numbers) 0, 1, 2, 4, 5, 8, 9
通过参数 reverse=True
指定倒序:
numbers = (4, 5, 2, 8, 9, 1, 0) sorted(numbers, reverse=True) 9, 8, 5, 4, 2, 1, 0
通过参数 key
指定排序时所使用的字段:
codes = (‘上海’, ‘021’), (‘北京’, ‘010’), (‘成都’, ‘028’), (‘广州’, ‘020’) sorted(codes, key=lambda x: x1) (‘北京’, ‘010’), (‘广州’, ‘020’), (‘上海’, ‘021’), (‘成都’, ‘028’) 说明:指定 key 排序需要用到 lambda 表达式。有关 lambda 表达式的内容将在函数式编程章节中介绍。
获取一个整数序列。可指定起始数值,结束数值,增长步长。
在 for
循环中想要指定循环次数时非常有用。
位置参数这个名称其实我们并不陌生,之前所编写的函数使用的就是位置参数。位置参数,顾名思义,传入函数时每个参数都是通过位置来作区分的。函数调用时,传入的值需按照位置与参数一一对应。
比如下面这个程序:
def overspeed_rate(current, max, min):
if current > max:
return (current - max) / max # 超过最大时速,结果为正
elif current < min:
return (current - min) / min # 超过最小时速,结果为负
else:
return 0 # 不超速,结果为 0
这个函数用来判断车辆在高速上行驶时超速的比例。它接受三个参数,current
表示当前时速,max
参数表示当前路段的允许的最大时速,min
表示所允许的最小时速。
位置参数需要按位置顺序来传递,否则结果不可预期。
overspeed_rate(150, 120, 90) 0.25 # 超过最大时速 25% overspeed_rate(80, 100, 60) 0 # 不超速 overspeed_rate(60, 120, 90) -0.3333333333333333 # 超过最小时速 33.33%
前面的函数中,如果最大时速和最小时速比较固定,那么每次函数调用时都输入这个两个参数就显得有些繁琐,这时我们可以使用参数默认值。
参数默认值也就是给参数设置默认值,之后函数调用时便可以不传入这个参数,Python 自动以默认值来填充参数。如果一个有默认值的参数依然被传入了值,那么默认值将会被覆盖。
函数定义时,以 参数=值
来指定参数默认值。如下:
def 函数(参数1, 参数2=默认值):
pass
例如上面的 overspeed_rate
函数, max
和 min
通常比较固定,我们可以使用一个常用值来作为默认值。
def overspeed_rate(current, max=120, min=90):
if current > max:
return (current - max) / max
elif current < min:
return (current - min) / min
else:
return 0
overspeed_rate(192) 0.6 overspeed_rate(45) -0.5
对于 overspeed_rate
函数,我们还可以在函数调用时,以 参数名=值
的形式来向指定的参数传入值。
如:
overspeed_rate(100, min=80)
或者
overspeed_rate(current=100, min=80)
或者
overspeed_rate(current=100, max=100, min=80)
在调用函数时以 参数名=值
指明要传递的参数,这种以关键字的形式来使用的参数叫做关键字参数。
使用关键字时甚至可以打乱参数传递次序:
overspeed_rate(min=80, max=100, current=100)
overspeed_rate(min=80, max=100, current=100) 0
但要注意,关键字参数需要出现在位置参数之后,否则将抛出 SyntaxError
异常:
overspeed_rate(100, max=100, 80) File “”, line 1 SyntaxError: positional argument follows keyword argument
关键字参数的用法还不止如此。
当我们在定义函数时,如果参数列表中某个参数使用 **参数名
形式,那么这个参数可以接受一切关键字参数。如下:
def echo(string, **keywords):
print(string)
for kw in keywords:
print(kw, ":", keywords[kw])
echo(‘hello’, today=‘2019-09-04’, content=‘function’, section=3.6) hello today : 2019-09-04 content : function section : 3.6
显然,我们并没有在函数定义时定义 today
、content
、section
参数,但是我们却能接收到它们,这正是 **keywords
发挥了作用。函数会将所有接收到的关键字参数组装成一个字典,并绑定到 keywords
上。验证一下:
def foo(**keywords): … print(keywords) … foo(a=1, b=2, c=3) {‘a’: 1, ‘b’: 2, ‘c’: 3}
定义函数时,在参数列表中使用 **参数名
,可以接收一切关键字参数。类似的,参数列表中使用 *参数名
,就可以接受任意数量的非关键字参数,也就是可变参数。
如,计算任意个数的乘积:
def multiply(*nums):
result = 1
for n in nums:
result *= n
return result
multiply(1,3,5,7) 105
这个函数能接收任意个参数,这正是 *nums
所发挥的作用。函数所有接收到的非关键字参数组装成一个元组,并绑定到 nums
上。来试验一下:
def multiply(*nums): … print(nums) … multiply(1, 2, 3, 4, 5) (1, 2, 3, 4, 5)
典型情况下,函数只有一个返回值,但是 Python 也支持函数返回多个返回值。
要返回多个返回值,只需在 return
关键字后跟多个值(依次用逗号分隔)。
例如:
def date():
import datetime
d = datetime.date.today()
return d.year, d.month, d.day
date()
返回了今天的日期的年、月、日。
接收函数返回值时,用对应返回值数量的变量来分别接收它们。
year, month, day = date() year 2019 month 9 day 4
函数返回多个返回值是什么原理呢?其实多返回值时,Python 将这些返回值包装成了元组,然后将元组返回。来验证下:
date() (2019, 9, 4)
接收返回值时,year, month, day = date()
,这样赋值写法,会将元组解包,分别将元素赋予单独的变量中。即:
year, month, day = (2019, 9, 4) year 2019 month 9 day 4
之前介绍类的时候,我们学习了对象属性和对象方法。对象属性和对象方法是绑定在对象这个层次上的,也就是说需要先创建对象,然后才能使用对象的属性和方法。
即:
对象 = 类()
对象.属性
对象.方法()
除此之外,还有一种绑定在类这个层面的属性和方法,叫作类属性和类方法。使用类属性和类方法时,不用创建对象,直接通过类来使用。
类属性和类方法的使用方式:
类.属性
类.方法()
类属性如何定义呢?
只要将属性定义在类之中方法之外即可。如下面的 属性1
和 属性2
:
class 类:
属性1 = X
属性2 = Y
def 某方法():
pass
举个例子:
class Char:
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits = '0123456789'
这里定义了类 Char
,有两个类属性,这两个类属性分别包含所有大写字母和所有数字。可以通过类名来使用这两个类属性,此时无需创建对象:
Char.letters ’ABCDEFGHIJKLMNOPQRSTUVWXYZ’ Char.digits ’0123456789’
当然,类所创建出来的对象也能使用类属性:
char = Char() char.letters ’ABCDEFGHIJKLMNOPQRSTUVWXYZ’ char.digits ’0123456789’
再来看下类方法的定义方法。类方法的定义需要借助于装饰器,装饰器具体是什么后续文章中会介绍,目前只要知道用法即可。
定义类方法时,需要在方法的前面加上装饰器 @classmethod
。如下:
class 类:
@classmethod
def 类方法(cls):
pass
注意与对象方法不同,类方法的第一个参数通常命名为 cls
,表示当前这个类本身。我们可以通过该参数来引用类属性,或类中其它类方法。
类方法中可以使用该类的类属性,但不能使用该类的对象属性。因为类方法隶属于类,而对象属性隶属于对象,使用类方法时可能还没有对象被创建出来。
在之前 Char
类的基础上,我们加上随机获取任意字符的类方法。代码如下:
import random
class Char:
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits = '0123456789'
@classmethod
def random_letter(cls):
return random.choice(cls.letters)
@classmethod
def random_digits(cls):
return random.choice(cls.digits)
方法 random_letter()
可以从属性 letters
随机获取一个大写字母;方法 random_digits()
可以从属性 digits
随机获取一个数字。它们函数体中的 random.choice()
可从指定序列中随机获取一个元素。
Char.random_digits() ‘8’ Char.random_letter() ‘X’ 扩展:
import
语句不仅可用于模块的开头,也可用于模块的任意位置,如函数中。
与类方法有点相似的是静态方法,静态方法也可直接通过类名来调用,不必先创建对象。不同在于类方法的第一个参数是类自身(cls
),而静态方法没有这样的参数。如果方法需要和其它类属性或类方法交互,那么可以将其定义成类方法;如果方法无需和其它类属性或类方法交互,那么可以将其定义成静态方法。
定义静态方法时,需要在方法的前面加上装饰器 @staticmethod
。如下:
class 类:
@staticmethod
def 静态方法():
pass
之前的例子中,我们可以从类属性 letters
和 digits
中随机获取字符,如果想要自己来指定字符的范围,并从中获取一个随机字符,可以再来定义一个静态方法 random_char()
。如:
import random
class Char:
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits = '0123456789'
@classmethod
def random_letter(cls):
return random.choice(cls.letters)
@classmethod
def random_digits(cls):
return random.choice(cls.digits)
@staticmethod
def random_char(string):
if not isinstance(string, str):
raise TypeError('需要字符串参数')
return random.choice(string)
静态方法 random_char
从传入的字符串中随机挑选出一个字符。之所以定义成静态方法,是因为它无需与类属性交互。
Char.random_char(‘imooc2019’) ‘0’ Char.random_char(‘imooc2019’) ‘m’
类属性 letters
和 digits
是为了提供给同一个类中的类方法使用,但我们可以通过类或对象从类的外部直接访问它们。比如:
Char.letters
Char.digits
Char.letters ’ABCDEFGHIJKLMNOPQRSTUVWXYZ’ Char.digits ’0123456789’
有时我们不想把过多的信息暴露出去,有没有什么方法来限制属性不被类外部所访问,而是只能在类中使用?
答案是有的,我们只需要在命名上动动手脚,将属性或方法的名称用 __
(两个下划线)开头即可。如:
import random
class Char:
__letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
__digits = '0123456789'
@classmethod
def random_letter(cls):
return random.choice(cls.__letters)
@classmethod
def random_digits(cls):
return random.choice(cls.__digits)
从类外部访问这两个属性看看:
Char.__letters Traceback (most recent call last): File “”, line 1, in AttributeError: type object ‘Char’ has no attribute ‘__letters’Char.__digits Traceback (most recent call last): File “”, line 1, in AttributeError: type object ‘Char’ has no attribute ‘__digits’
可以看到,修改过后的属性不能直接被访问了,解释器抛出 AttributeError
异常,提示类中没有这个属性。
但位于同一个类中的方法还是可以正常使用这些属性:
Char.random_letter() ‘N’ Char.random_digits() ‘4’
像这样以 __
(两个下划线)开头的属性我们称为私有属性。顾名思义,它是类所私有的,不能在类外部使用。
上述是以类属性作为示例,该规则对类方法、对象属性、对象方法同样适用。只需在名称前加上 __
(两个下划线)即可。
我们也可以使用 _
(一个下划线)前缀来声明某属性或方法是私有的,但是这种形式只是一种使用者间的约定,并不在解释器层面作限制。如:
class Char:
_letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
_digits = '0123456789'
上面的 _letters
和 _digits
也可看作私有属性,只不过是约定上的私有,通过名称前缀 _
(一个下滑线)向使用者告知这是私有的。但你如果非要使用,依然可以用。
Char._letters ’ABCDEFGHIJKLMNOPQRSTUVWXYZ’ Char._digits ’0123456789’
类中以 __
开头并以 __
结尾的方法是特殊方法,特殊方法有特殊的用途。它们可以直接调用,也可以通过一些内置函数或操作符来间接调用,如之前学习过的 __init__()
、__next__()
。
特殊方法很多,在这里我们简单例举几个:
如果想基于一个现有的类,获取其全部能力,并以此扩展出一个更强大的类,此时可以使用类的继承。被继承的类叫作父类(或基类),继承者叫作子类(或派生类)。关于类的简单继承可以看下图就是一个典型的例子:
在类的继承的定义时,子类名称的后面加上括号并写入父类。如下:
class 父类:
父类的实现
class 子类(父类):
子类的实现
例如:
class A:
def __init__(self):
self.apple = 'apple'
def have(self):
print('I hava an', self.apple)
class B(A):
def who(self):
print('I am an object of B')
b = B() b.who() I am an object of B b.apple ’apple’ b.have() I hava an apple
可以看到,虽然类 B
中什么都没定义,但由于 B
继承自 A
,所以它拥有 A
的属性和方法。
子类 B
中当然也可以定义自己的属性。
class B(A):
def __init__(self):
super().__init__()
self.banana = 'banana'
b = B() b.banana ’banana’
我们在 B
中定义 __init__()
方法,并在其中定义了 B
自己的属性 banana
。
super().__init__()
这一句代码是什么作用?由于我们在子类中定义了 __init__()
方法,这会导致子类无法再获取父类的属性,加上这行代码就能在子类初始化的同时初始化父类。super()
用在类的方法中时,返回父类对象。
子类中出现和父类同名的方法会怎么样?答案是子类会覆盖父类的同名方法。
class A:
def __init__(self):
self.apple = 'apple'
def have(self):
print('I hava an', self.apple)
class B(A):
def __init__(self):
super().__init__()
self.banana = 'banana'
def have(self):
print('I hava an', self.banana)
b = B() b.have() I hava an banana
子类可以继承父类,同样的,父类也可以继承它自己的父类,如此一层一层继承下去。
class A:
def have(self):
print('I hava an apple')
class B(A):
pass
class C(B):
pass
c = C() c.have() I hava an apple
在这里 A
是继承链的顶端,B
和 C
都是它的子类(孙子类)。
其实 A
也有继承,它继承自 object
。任何类的根源都是 object
类。如果一个类没有指定所继承的类,那么它默认继承 object
。
A
中也可以显式指明其继承于 object
:
class A(object):
def have(self):
print('I hava an apple')
如果想要判断一个类是否是另一个类的子类,可以使用内置函数 issubclass()
。用法如下:
issubclass(C, A) True issubclass(B, A) True issubclass(C, B) True
子类可以同时继承多个父类,这样它便拥有了多份能力。如下图,步兵类就同时拥有士兵类和人类的属性,就步兵类属于多继承。
定义时,子类名称后面加上括号并写入多个父类。如下:
class A:
def get_apple(self):
return 'apple'
class B:
def get_banana(self):
return 'banana'
class C(A, B):
pass
c = C() c.get_apple() ‘apple’ c.get_banana() ‘banana’
此时 C
便同时拥有了 A
和 B
的能力。
在 Python 中,所有的对象都可以赋值给变量,包括函数。这可能有点出乎意料,我们不妨来试一试:
def say_hello(name):
return name + ', hello!'
f = say_hello
f(‘开发者’) ‘开发者, hello!’ f <function say_hello at 0x10befec80>
注意,这里被赋值的是函数本身,而不是函数的结果。赋值后,变量 f
与函数 say_hello
绑定,f
也就相当于是 say_hello
的别名,完全可以用调用 say_hello
的方式来调用 f
。
扩展:类也可以赋值给变量。如: class Apple: who_am_i = 'apple' banana = Applebanana.who_am_i ’apple’ 注意,被赋值的是类本身,而不是类实例化后的对象。赋值后,变量
banana
与类Apple
绑定,banana
也就相当于是Apple
的别名,使用banana
就相当于使用Apple
。
一切对象都可以作为函数的参数,包括另一个函数。接受函数作为参数的函数,称为高阶函数。这和数学中的高阶函数有些相似。
来看一个函数作为参数的例子。
这个例子中,我们实现了一个函数,它从给定的数字列表中筛选数字,而具体的筛选策略由另一个函数决定并以参数的形式存在:
def filter_nums(nums, want_it):
return [n for n in nums if want_it(n)]
函数 filter_nums
用来筛选数字,它接受两个参数,nums
是包含所有待筛选数字的列表,want_it
是一个函数,用来决定某个数字是否保留。
我们选定一个简单的策略来实现下 want_it
参数所对应的函数(其函数名不必为 want_it
):
def want_it(num):
return num % 2 == 0
这里 want_it
接受一个数字作为参数,如果这个数字是 2 的倍数,则返回 True
,否则返回 False
。
调用一下 filter_nums
试试:
def filter_nums(nums, want_it): … return n for n in nums if want_it(n) … def want_it(num): … return num % 2 == 0 … filter_nums(11, 12, 13, 14, 15, 16, 17, 18, want_it) 12, 14, 16, 18
这里每个数字都经过 want_it()
函数的判断,而 want_it()
是以 filter_num()
第二个参数的形式传递进去,供 filter_num()
调用。
在 Python 中,可以通过 lambda 表达式来便捷地定义一个功能简单的函数,这个函数只有实现没有名字,所以叫作匿名函数。
lambda 表达式的写法如下:
lambda 参数1, 参数2, 参数N: 函数实现
使用上述表达式将定义一个匿名函数,这个匿名函数可接受若干参数,参数写在冒号前(:
),多个参数时用逗号分隔,其实现写在冒号后(:
)。
举个例子:
f = lambda x: x ** 2
这个 lambda 表达式定义了一个匿名函数,这个匿名函数接受一个参数 x
,返回 x ** 2
的计算结果。同时赋值语句将这个匿名函数赋值给了变量 f
。注意 f
保存的是函数,而不是函数结果。
f <function at 0x10bcba0d0> f(4) 16 f(9) 81
通过观察上述示例可以发现,lambda 表达式中并没有 return
关键字,但结果被返回出来。是的,匿名函数的 函数实现
的执行结果就会作为它的返回值,无需使用 return
关键字。
从功能上来看,lambda x: x ** 2
等同于:
def no_name(x):
return x ** 2
no_name(4) 16
一般情况下,我们不会像 f = lambda x: x ** 2
这样直接将匿名函数赋值给变量,然后去用这个变量。而是在需要将函数作为参数时,才去使用 lambda 表达式,这样就无需在函数调用前去定义另外一个函数了。
如我们刚才写的函数 filter_nums
:
def filter_nums(nums, want_it):
return [n for n in nums if want_it(n)]
它的 want_it
参数需要是一个函数 ,这时用 lambda 表达式便能方便的解决问题。可以像这样来使用:
filter_nums(11, 12, 13, 14, 15, 16, 17, 18, lambda x: x % 2 == 0) 12, 14, 16, 18
以前讲内置函数的时候,我们介绍过排序函数 sorted()
。它有一个参数 key
,用来在排序复杂元素时,指定排序所使用的字段,这个参数需要是个函数,同样可以用 lambda 表达式来解决:
codes = (‘上海’, ‘021’), (‘北京’, ‘010’), (‘成都’, ‘028’), (‘广州’, ‘020’) sorted(codes, key=lambda x: x1) # 以区号字典来排序 (‘北京’, ‘010’), (‘广州’, ‘020’), (‘上海’, ‘021’), (‘成都’, ‘028’)