python入门(六):函数

时间:2022-07-02 13:59:02

1.系统自带的函数:

>>> dir(__builtins__)

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

2.定义一个函数

>>> def a2_333():             #def定义一个函数,a2_333函数名,字母开头

...     pass                  #()中的参数可有可无

...

>>> a2_333                  #未调用函数,只是打印了一下函数名

<function a2_333 at 0x0000019CF2431EA0>      #function代表该名字是函数

#at代表了该函数在内存中的地址

>>> a2_333()                 #函数名后加(),便可调用该函数

>>>

>>> def count_letter(s):        #函数名不要与系统自带的函数名、定义的变量名冲突,

...     result=0               #s为参数,在括号中可以写多个参数,无限制

...     for i in s:

...         if i >="a" and i <="z":

...             result=result+1

...     return result            #函数执行完毕后,一定要有个返回值

...

>>> count_letter("a1b2Z3")

2

>>> count_letter("skdjhf3ksdhf")   #函数定义好后,传不同的参数,均能正确输出

11                             #封装的概念,调用时不用关注内部的逻辑

>>>count_letter()                #调用的时候,传参一个都不能少,除非函数使用默认

Traceback (most recent call last):    #参数

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

TypeError: count_letter() missing 1 required positional argument: 's'

>>> def count_digit(s):

...     result=0

...     for i in s:

...         if i>="0" and i<="9":

...             result+=1

...                                    #该函数就没有返回值

...

>>> print(count_digit("sadhfasjdgsjf"))     #没有return的函数,默认返回None

None

>>> print(count_digit("ssjhd24"))         #没有return的函数,默认返回None

None

>>> def count_digit(s):

...     result=0

...     for i in s:

...         if i>="0" and i<="9":

...             result+=1

...     return                         #有return,但是后面没有写任何参数

...

>>> print(count_digit("sadhfasjdgsjf"))   #依然返回None

None

>>> print(count_digit("ssjhd24"))

None

>>> print(None)                       #单独打印None,还是会有结果输出

None

>>> print(none)                       #打印小写none,提示未定义

Traceback (most recent call last):

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

NameError: name 'none' is not defined

3.函数的建壮性

输入两个数,返回相加的结果:

def add(a,b):

return(a+b)

print(add(1,2))              #在文件中执行时,一定要加print,否则无输出结果

>>> add(1,2)               #终端模式时,不必加print便有正确输出

3

该代码存在安全隐患,如果a,b类型不一致,会报错

>>> def add(a,b):

...     return(a+b)

...

>>> add(1,"2")             #传入的a,b的类型不一致

Traceback (most recent call last):

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

File "<stdin>", line 2, in add

TypeError: unsupported operand type(s) for +: 'int' and 'str'

改进后的代码是:

def add(a,b):

if isinstance(a,(int,float,complex)) and isinstance(b,(int,float,complex)): #判断a,b是否都

return(a+b)                                             #是int类型

print("Adding different types of objects is not supported")       #return具有短路功能

return None

print(add(1,"2"))

执行结果:

E:\>python a.py

Adding different types of objects is not supported

None

4.函数的作用域

>>> n=1                    #全局变量

>>> def func():

...     n=2                  #在函数内部定义的变量叫做局部变量,函数体内部有效

...     return n

...

>>> print(func())             #返回函数内的n值

2

>>> print(n)                 #返回全局变量n的值

1

>>> def func():

...     n=2                   #只存在一个局部变量n,不存在全局变量n

...     return n

...

>>> print(func())

2

>>> print(n)                  #不存在全局变量n,提示n未定义

Traceback (most recent call last):

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

NameError: name 'n' is not defined

n=1                          #全局变量中有n

def func():

return n+1                #函数中使用了n,但是在函数中未定义,会现在函数体内

#部找n,如果找不到,就到函数外面找

print(func())

运行结果:

E:\>python a.py

2                             #依然能返回正确的结果

n=1                          #n是全局变量

def func():

n+=1                     #n在函数中还未赋值,就加1

return n

print(func())

print(n)

运行结果:

E:\>python a.py

Traceback (most recent call last):

File "a.py", line 6, in <module>

print(func())

File "a.py", line 3, in func

n+=1

UnboundLocalError: local variable 'n' referenced before assignment

局部变量n在赋值前被引用了,意思就是还未赋值

解决方法:在函数内部也先赋一下值

n=1

def func():

n=10

n+=1

return n

print(func())

print(n)

运行结果:

E:\>python a.py

11

1

解决方法:使用全局变量的n

n=1

def func():

global n              #函数内部,也使用全局变量的n

n+=1                #函数内部n+1,同时全局变量的n也加了1

return n

print(func())

print(n)

运行结果:

E:\>python a.py           #n为2

2                       #此方法不推荐

2

n=1

def func(a):

a+=1

return a

print(func(n))             #传的参数为n,n在程序中是全局变量1,所以a=2

print(n)                  #此方法比较推荐使用

运行结果:

E:\>python a.py

2

1

n=[]                     #n在全局变量的位置,但是是列表,列表是可变对象

def func(a):

a.append(1)

return a

print(func(n))

print(n)

运行结果:

E:\>python a.py

[1]

[1]

n={}

def func(a):

a[1]=1

return a

print(func(n))

print(n)

运行结果;

E:\>python a.py

{1: 1}

{1: 1}

n="abc"

def func(a):

a=a+"d"

return a

print(func(n))

print(n)

运行结果:

E:\>python a.py

abcd

abc

原则1:

如果你传入的参数是变量a,这个变量是可变类型(list,dict,set)

那么函数内部对于这个参数的所有操作结果都会影响外部的参数值

原则2:

如果你传入的参数是个变量a,这个变量是不可变类型(字符串,整数,小数,元祖)

那么函数内部对于这个参数的所有操作结果都不会影响外部的参数值

>>> def func():

...     n=2

...     return n

...

>>> func=1                 #func是一个函数的名字,赋值后,从函数变成了int

>>> func()                  #整数加(),打印时提示不可调用

Traceback (most recent call last):

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

TypeError: 'int' object is not callable

>>> del func                #非内置的函数,提示不可调用后,可删除后再次定义

>>> def func():

...     n=2

...     return n

...

>>> print(func())             #函数功能正常

2

>>> del func()               #当删除函数时,不要加(),否则会报错儿

File "<stdin>", line 1

SyntaxError: can't delete function call

>>> print(len("abc"))          #len函数是系统自带的函数

3

>>> len=10

>>> print(len)               #len变成了10

10

>>> print(len("abc"))         #此时在调用函数,提示int类型不可调用

Traceback (most recent call last):

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

TypeError: 'int' object is not callable

>>> del len                   #删除掉len

>>> print(len("abc"))           #len为系统自带函数,删除后未经再次定义依然可以调用

3

5.调用时参数

1)       必填参数

>>> def add(a,b):             #函数定义了两个参数a,b

...     return(a+b)

...

>>> print(add(1))             #调用时只传入了一个参数

Traceback (most recent call last):

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

TypeError: add() missing 1 required positional argument: 'b'       #报错,少参数

2)       可选参数

>>> def add(a,b=100):        #定义了两个参数a,b,b的默认值是100

...     return(a+b)

...

>>> print(add(1))             #虽然只传入了一个参数,但是能正确输出结果,原因在于

101                         #b使用的是默认参数值

默认值是在定义时就设定的。

>>> def add(a,b=100):        #参数b的默认值是100

...     return(a+b)

...

>>> print(add(1,10))         #传入的b值是10

11                         #最后打印使用的是传入的值,非默认值

>>> def add(a,b=100):

...     return(a+b)

...

>>> print(add(b=1,a=10))   #调用时,参数赋值,也可正确输出

11

>>> def add(a,b=100):       #a是必填参数,b是可选参数

...     return a+b

...

>>> print(add(b=1))         #传参时,必填参数无,会报错

Traceback (most recent call last):

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

TypeError: add() missing 1 required positional argument: 'a'

>>> def add(a=100,b):       #默认值参数后有非默认值参数

...     return a+b

...

File "<stdin>", line 1

SyntaxError: non-default argument follows default argument

默认值参数后面跟了非默认值参数

函数定义时,默认值参数的后面不能有非默认值参数,

3)       可变参数:

def add(a,b,*c):

print(type(c))

print(c)                        #可变参数不需要对应,便可正确输出

return a,b,c

print(add(1,2,3,4,5))

运行结果:

E:\>python a.py

<class 'tuple'>                     #c的类型是元祖

(3, 4, 5)                           #c的值是(3,4,5)

(1, 2, (3, 4, 5))                      #a的值是1,b的值是2

def add(a,b,**c):                #c前面有两个*

print(type(c))

print(c)

print(add(1,2,c=3,d=4,e=5))

运行结果:

E:\>python a.py

<class 'dict'>                  #c的类型是dict

{'c': 3, 'd': 4, 'e': 5}              #c的值是赋值的结果,c,d,e是key,3,4,5,是value

None

>>> def add(a,b,*c):

...     print(type(c))

...     print(c)

...     return a,b,c

...

>>> print(add(1,2,3,4,5))

<class 'tuple'>

(3, 4, 5)

(1, 2, (3, 4, 5))

>>> print(a)                            #a为非可变参数,未对应赋值,便提示未定义

Traceback (most recent call last):

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

NameError: name 'a' is not defined

def add(a,b,*c):

print(type(c))

print(c)

return a,b,c

a,b,*c=add(1,2,3,4,5)                    #a,b非可变参数赋值后,可正常打印

print(add(1,2,3,4,5))

print(a)

print(b)

运行结果:

E:\>python a.py

<class 'tuple'>

(3, 4, 5)

<class 'tuple'>

(3, 4, 5)

(1, 2, (3, 4, 5))

1

2

6.返回时多个参数

def time_ten_bigger(a,b):

return a*10,b*10

print(time_ten_bigger(1,10))

print(a)

print(b)

运行结果:

E:\>python a.py

(10, 100)                       #返回了函数调用的结果

Traceback (most recent call last):

File "a.py", line 5, in <module>

print(a)

NameError: name 'a' is not defined#print(a)提示a未定义

正确的代码是:

def time_ten_bigger(a,b):

return a*10,b*10           #返回两个值,实际自动的将两个值放在了元祖里

a,b=time_ten_bigger(1,10)       #将a,b分别与函数的参数对应

print(time_ten_bigger(1,10))

print(a)

print(b)

运行结果:

E:\>python a.py

(10, 100)                       #函数返回的值

10                             #a的值

100                            #b的值

def time_ten_bigger(a,b):

return a*10,b*10             #函数返回值参数都乘以10

a,b=time_ten_bigger(1,10)         #a是1的十倍,b是10的十倍

print(time_ten_bigger(b=1,a=10))   #这个函数定义的参数前后位置不一样

print(a)

print(b)

运行结果:

E:\>python a.py

(100, 10)

10

100

小练习:

1.统计一句话中有多少个数字

>>> def count_digit(s):

...     result=0

...     for i in s:

...         if i>="0" and i<="9":

...             result+=1

...     return result

...

>>> count_digit("sadhfasjdgsjf")

0

>>> count_digit("ssjhd24")

2

2.使用可变参数的方式求1-5的和

def add(a,b,*c):                  #c是个元祖,使用遍历的方法

result=0

for i in c:

result+=i

return result+a+b

print(add(1,2,3,4,5))

运行结果:

E:\>python a.py

15

3.使用可变参数,求add(1,2,c=3,d=4,e=5)所有数的和

def add(a,b,**c):                  #c是字典,遍历字典的values值

result=0                     #方法1:

for i in c.values():

result+=i

return a+b+result

print(add(1,2,c=3,d=4,e=5))

运行结果:

E:\>python a.py

15

def add(*a,**c):                #方法2:字典+元祖

result=0

for i in a:

result+=i

for i in c.values():

result+=i

return result

print(add(1,2,c=3,d=4,e=5))

运行结果:

E:\>python a.py

15

4.使用可变参数,求add(1,2,3,4,c=5,d=6,e=7)的和

def add(a,b,*c,**d):

result=a+b

for i in d.values():

result+=i

for i in c:

result+=i

return result

print(add(1,2,3,4,c=5,d=6,e=7))

运行结果:

E:\>python a.py

28