天天看点

Python-函数基础总结与内置函数 更多python相关内容:【python总结】python学习框架梳理

目录

上篇文章思考题

简介

函数长什么样子?

调用函数

位置传参与关键字传参

传参是值传递还是引用传递

定义函数

参数

默认参数

关键字参数

参数组

返回值

指定参数、返回值类型

内置函数

标准类型函数

dir

help

id

len

str

type

数字类型函数

转换工厂函数

功能函数

用于可迭代对象的函数

思考题

上篇文章思考题

Python-字典总结(操作符、方法、内置函数)

>>> d = {(1,):2}

>>> d = {(1,[1,2]):2}

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: unhashable type: 'list'

元组中不能含有列表,列表是不可哈希的,包含列表的元组也就无法哈希。这个元组的"不可变"还是有很大的讨论空间,有时间再详细看看内部原理。

简介

函数是对程序逻辑进行结构化或过程化的一种编程方法。能将整块代码巧妙地隔离成易于管理的小块,把重复代码放到函数中而不是进行大量的拷贝一这样既能节省空间,也有助于保持一致性,因为你只需改变单个的拷贝而无须去寻找再修改大量复制代码的拷贝。

函数长什么样子?

这是一个很简单的求和函数:

def plus(a, b):
    """
    :param a: a number
    :param b: a number
    :return: a+b
    """
    return a + b           

可以看到使用关键字def引入一个函数,然后是函数名,括号里面a,b是两个参数,使用关键字return进行返回,a+b是返回值。

三引号之间的是注释,写注释是一个很好的习惯,通过参数和返回值可以让和你合作的人不用看函数内的代码就知道函数的作用以及该怎么调用。

我们来看一下平常用的很多的输出函数,在builtins.py中,是一个内置函数,使用pycharm时,你可以写出print()后选中print,按Ctrl+B跳转到以下代码:

def print(self, *args, sep=' ', end='\n', file=None): # known special case of print
    """
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.
    """
    pass           

 作用是将值打印到流或系统标准输出(默认情况下)。

值使用逗号隔开,后面有几个默认参数(后面讲),我们常用的是sep和end,一个用来分隔值,一个用于末尾。

不填默认值时:

>>> print('lady','killer')

lady killer

 使用关键字参数填写默认值(后面讲)

>>> print('lady','killer',sep=';')

lady;killer

>>> print('lady','killer',end=';')

lady killer;>>>

参数数量不对,关键字错误,类型错误等会显示TypeError

>>> print('lady','killer',edn=';')

TypeError: 'edn' is an invalid keyword argument for print()

 ()操作符是函数调用,函数的名字你可以认为是指针/引用,函数名字后面有()时,函数体内的代码才会运行。

>>> display=print

>>> display('lady','killer')

上面代码我使用display变量让其指向print所指的函数,再使用()调用函数也可进行输出。()操作符在面向对象时也可用作类的实例化。

代码:

def function(x, lst):
    print('函数内x修改前:', id(x), x)
    print('函数内lst修改前:', id(lst), lst)
    x += 1
    lst.append(x)
    print('函数内x修改后:', id(x), x)
    print('函数内lst修改后:', id(lst), lst)
    return x, lst


x = 3
lst = [3]
print('函数外x调用前:', id(x), x)
print('函数lst外调用前:', id(lst), lst)
x_return, lst_return = function(x, lst)
print('函数外x调用后:', id(x), x)
print('函数外lst调用后:', id(lst), lst)
print('返回的x:', id(x_return), x_return)
print('返回的lst:', id(lst_return), lst_return)           

结果:

函数外x调用前: 140730711241024 3

函数lst外调用前: 1739892740680 [3]

函数内x修改前: 140730711241024 3

函数内lst修改前: 1739892740680 [3]

函数内x修改后: 140730711241056 4

函数内lst修改后: 1739892740680 [3, 4]

函数外x调用后: 140730711241024 3

函数外lst调用后: 1739892740680 [3, 4]

返回的x: 140730711241056 4

返回的lst: 1739892740680 [3, 4]

传参引用传递:修改前与调用前的id一样

返回引用传递:修改后与返回的id一样

不可变类型变量x,传参引用传递,返回引用传递,由于不可变,故指向3和4的变量都叫x(实参和形参),我们输出的修改后的x是指向4的x,指向3的x未变。

可变类型变量lst,传参引用传递,返回引用传递,由于可变,故id一直不变。

总结:函数传参是引用传递,函数外一直不变,对于不可变类型,可以通过返回修改后的引用来改变它(指向其他地方)。

我们定义一个简单的求x的n次幂的函数:

def power(x, n):
    return x ** n
print(power(2, 2))
print(power(3, 2))
print(power(4, 2))
print(power(2, 3))           

得到结果:

4

9

16

8

 我们定义了一个返回x的n次幂的函数,调用函数的人说,我大部分情况下都是想要x的平方,我懒得写2,这个时候你让他滚可以使用默认参数。

def power(x, n=2):
    return x ** n


print(power(2))
print(power(3))
print(power(4))
print(power(2, 3))           

这样,得到一样的结果,当参数特别多而有些参数大部分情况下不会改变时可以使用默认参数,也可以增强函数的健壮性。

注意: 默认值只会执行一次。这条规则在默认值为可变对象(列表、字典以及大多数类实例)时很重要。比如,下面的函数会存储在后续调用中传递给它的参数:

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))           

结果为:

[1]
[1, 2]
[1, 2, 3]           

如果你不想要在后续调用之间共享默认值,你可以这样写这个函数:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L
           

关键字参数在调用函数时使用过了,使用形如

kwarg=value

的关键字参数来调用函数。像print('lady','killer')是位置参数,python会根据参数前后位置进行匹配,关键字参数必须跟随在位置参数的后面,否则会出现语法错误,例如:

>>> display(sep=';','killer')

  File "<stdin>", line 1

SyntaxError: positional argument follows keyword argument

>>> display('lady','killer',end=';',sep='&')

lady&killer;>>> 

关键字参数之间是不需要按定义函数时的顺序填写的(此时,我的display和print在交互式命令窗口是一样的)。

这个时候调用函数的人说,我需要你完成一个复杂的函数,有很多的参数,你可以说老子辞职不干了使用参数组对参数进行打包。python 提供了两种,一种是元组,就是你经常看到的*args,另一个是字典,就是你经常看到的**kwargs。

在前面我们提到的print函数就把需要输出的很多value打包成了一个元组。

我们定义一个学生函数,打印学生的id、科目分数,总分和其他信息。

def student(id, *subjects, **more_info):
    print('id:', id)
    print('math:', subjects[0])
    print('english:', subjects[1])
    print('allscore:', sum(subjects))
    print('name:', more_info['name'])
    print('school:', more_info['school'])
    print('classroom:', more_info['classroom'])           
student(2, 80, 99, name='frank', school='computer', classroom='1114')           

id: 2

math: 80

english: 99

allscore: 179

name: frank

school: computer

classroom: 1114

可以看到,python会自动的按照顺序填写好。

当然,大部分情况下是因为调用函数的人拥有的数据也是这个数据结构(得到的json数据等),此时可以这样调用:

subjects = (80, 99)
more_info = {'name': 'frank', 'school': 'computer', 'classroom': '1114'}
student(2, *subjects, **more_info)           
print(*subjects)得到的是 80 99 而不是 (80,99),因为print没把subject作为一个value,而是拆成了多个(这是列表、元组两篇文章埋下的坑)。           

不像C++中函数前需要指定函数的返回值类型

int plus(int a, int b)

{

    return a+b;

}

python中函数可以不指定返回值的类型,也可以返回多个值,使用逗号分隔。

def sum_multiplication(a, b):
    return a + b, a * b


res = sum_multiplication(2, 3)
print(res)           
(5, 6)

可以看到返回值是一个元组,你也可以使用对应的个数直接解析到每个返回值

sums, multiplication = sum_multiplication(2, 3)
print(sums, multiplication)           
5 6

使用冒号:和箭头->

def plus(a: int, b: int) -> int:
    """
    :param a: a number
    :param b: a number
    :return: a+b
    """
    return a + b


print(type(plus(3, 4)))
print(plus(3, 4))           

<class 'int'>

7

传入字符串:

print(type(plus('3', '4')))
print(plus('3', '4'))           

<class 'str'>

34

Python-函数基础总结与内置函数 更多python相关内容:【python总结】python学习框架梳理

pycharm给出警告,仅此而已,毕竟python是动态语言,看python源代码中的函数也没看见过指定,如果非要进行类型检查,你可以自己写,使用isinstance等函数判断。这个指定一般是在leetcode这样的oj网站经常出现。

常用标准类型函数

函数 作用
dir() 如果没有实参,则返回当前本地作用域中的名称列表。如果有实参,它会尝试返回该对象的有效属性列表。
help() 如果没有实参,解释器控制台里会启动交互式帮助系统。如果实参是一个字符串,则在模块、函数、类、方法、关键字或文档主题中搜索该字符串,并在控制台上打印帮助信息。如果实参是其他任意对象,则会生成该对象的帮助页。
id() 返回对象的“标识值”。该值是一个整数,在此对象的生命周期中保证是唯一且恒定的。两个生命期不重叠的对象可能具有相同的l值。
len() 返回对象的长度(元素个数)。
str() 返回一个str 版本的 object 。
type() 传入一个参数时,返回 object 的类型。 返回值是一个 type 对象,通常与object.__class__所返回的对象相同。

>>> 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']

>>> help(list.insert)

Help on method_descriptor:

insert(self, index, object, /)

    Insert object before index.

>>> a = 3

>>> b = 3

>>> id(a)

140707324522816

>>> id(b)

>>> b = 4

140707324522848

>>> l = [1,2]

>>> t = [1,2]

>>> id(l)

2141070401288

>>> id(t)

2141071612360

>>> t=l

不可变类型的id可能相同(我尝试的一直相同),可变类型一般赋值后才会相同。

>>> len(l)

2

>>> str(l)

'[1, 2]'

>>> type(l)

<class 'list'>

bool(x) 返回一个布尔值,

True

或者

False

。 x 使用标准的真值测试过程来转换。如果 x 是假的或者被省略,返回

False

;其他情况返回

True

chr(i) 返回 Unicode 码位为整数 i 的字符的字符串格式。
float(x)

返回从数字或字符串 x 生成的浮点数。

如果实参是字符串,则它必须是包含十进制数字的字符串,字符串前面可以有符号,之前也可以有空格。可选的符号有

'+'

'-'

;实参也可以是 NaN(非数字)、正负无穷大的字符串。
hex(x) 将整数转换为以“0x”为前缀的小写十六进制字符串。
int(x,base=10) 返回一个使用数字或字符串 x 生成的整数对象,或者没有实参的时候返回
abs() 返回一个数的绝对值。实参可以是整数或浮点数。如果实参是一个复数,返回它的模。

divmod

(a, b)
它将两个(非复数)数字作为实参,并在执行整数除法时返回一对商和余数。对于混合操作数类型,适用双目算术运算符的规则。对于整数,结果和

(a // b, a % b)

一致。对于浮点数,结果是

(q, a % b)

,q 通常是

math.floor(a / b)

但可能会比 1 小。

pow

(x, y[, z])
返回 x 的 y 次幂;如果 z 存在,则对 z 取余(比直接

pow(x, y) % z

计算更高效)。两个参数形式的

pow(x, y)

等价于幂运算符:

x**y

round

(number[, ndigits])
返回 number 舍入到小数点后 ndigits 位精度的值。 如果 ndigits 被省略或为

None

,则返回最接近输入值的整数。

bool

返回False的有以下三类:

  • 被定义为假值的常量:

    None

    False

  • 任何数值类型的零: ,

    0.0

    0j

    Decimal(0)

    Fraction(0, 1)

  • 空的序列和多项集:

    ''

    ()

    []

    {}

    set()

    range(0)

>>> bool(None)

False

>>> bool(0)

>>> bool(())

>>> bool(l)

True

chr

>>> chr(97)

'a

chr的逆函数是ord

ord

>>> ord('a')

97

float

>>> float(1.23)

1.23

>>> float('-1.23')

-1.23

>>> float('2e-3')

0.002

>>> float('inf')

inf

hex

>>> hex(10)

'0xa'

>>> hex(-255)

'-0xff'

int

>>> int(23.5)

23

>>> int('010',8)

>>> int('010',16)

abs

>>> abs(-5)

5

>>> abs(-2.5)

2.5

divmod

>>> divmod(10,3)

(3, 1)

>>> divmod(10,2.5)

(4.0, 0.0)

pow

>>> pow(2,5)

32

>>> pow(2,5,10)

round

>>> round(2.45)

>>> round(2.45,1)

用于可迭代对象的内置函数

dict() 创建一个新的字典。
list() 虽然被称为函数,list实际上是一种可变序列类型,
set() 返回一个新的

set

对象,可以选择带有从 iterable 获取的元素。
tuple() 虽然被称为函数,但tuple实际上是一个不可变的序列类型,
max() 返回可迭代对象中最大的元素,或者返回两个及以上实参中最大的。
min() 回可迭代对象中最小的元素,或者返回两个及以上实参中最小的。
sorted() 根据 iterable 中的项返回一个新的已排序列表。

sum

(iterable[, start])
从 start 开始自左向右对 iterable 中的项求l 和并返回总计值。 start 默认为

dict

>>> dict()

{}

>>> dict({'one':1,'two':2})

{'one': 1, 'two': 2}

>>> dict(one=1,two=2)

更多字典相关内容:Python-字典总结(操作符、方法、内置函数)

list

>>> list((3,6,'7',[5,4]))

[3, 6, '7', [5, 4]]

更多列表相关内容:Python-列表总结(操作符、方法、内置函数、相关模块)

set

>>> set([1,2,3])

{1, 2, 3}

更多集合相关内容:Python-集合类型set与frozenset(操作符、方法、内置函数)

turple

>>> tuple([1,2,'3',{'one':1,'two':2}])

(1, 2, '3', {'one': 1, 'two': 2})

更多元组相关内容:Python-元组总结(操作符、方法、内置函数、相关模块)

max、min、sorted、sum

>>> l = [1,2,3,4,5,9,8,7,6,10]

>>> max(l)

10

>>> min(l)

1

>>> sorted(l)

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> sum(l)

55

参考:python 3.7.8-内置函数

map等函数将在下一篇文章中提到,其余的请读者自行阅读上方官方文档。

思考题

1.将函数长什么样子?一节中的plus函数改为一个可以接受多个参数并返回参数和的函数。

2.在默认参数一节中,我将power(x,n)改为了n有默认值,即power(x,n=2),请将x设置为有默认值2。

答案见:Python-命名空间和变量作用域详解(global、nonlocal)