day4
---恢复内容开始---
1.函数的基本语法和特性
函数一词来源于数学,但编程中的【函数】概念与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫subroutine(子过程或者子程序),在Pascal中叫procedure(过程)和function,在java里面叫做method
定义:
函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
- 减少重复代码
- 使程序变的可扩展
- 是程序变的可维护
定义语法
>>> def sayhi(): #函数名 ... print("hello ,i'm nobody ") ... >>> sayhi <function sayhi at 0x7fc587a64840> >>> sayhi() #调用函数 hello ,i'm nobody >>>
可以带参数
#下面这段代码
>>> a,b = 5,8 >>> c = a ** b >>> print (c) 390625 >>>
改成用函数写
>>> def calc (x,y): ... res = x ** y ... return res ... >>> c = calc(a,b) >>> print(c) 390625 >>>
函数参数与局部变量
形参变量
只有在被调用时才分配内存单元,在调用结束时,即刻释放所有分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能在使用该形参变量
实参变量
可以是常量,变量,表达式,函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,因此应预先用赋值,输入等办法使参数获得确定值
>>> def calc (x,y):-----------形参 ... res = x ** y ... return res ... >>> c = calc(a,b)--------------实参 >>> print(c) 390625 >>>
默认参数
>>> def stu_register(name,age,nationality,course): ... print("-------注册学生信息--------") ... print("姓名:",name) ... print("age:",age) ... print("国籍:",nationality) ... print("课程:",course) ... >>> stu_register("Ryusei Ryo",23,'JP','actor') -------注册学生信息-------- 姓名: Ryusei Ryo age: 23 国籍: JP 课程: actor >>> >>> stu_register("王源",18,'CN','singer') -------注册学生信息-------- 姓名: 王源 age: 18 国籍: CN 课程: singer >>> stu_register("Jamie Dornan",35,'england','actor') -------注册学生信息-------- 姓名: Jamie Dornan age: 35 国籍: england 课程: actor >>>
def stu_register(name,age,nationality,country='CN'): 这样 这个参数在调用时不指定,那就是CN 指定的话就用指定的值
发现nationality这个参数 在调用时不指定,那默认参数就是CN
关键参数
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可,但记住一个要求,关键参数必须放在位置参数之后
>>> stu_register(age=22,name='morgana',nationality='CN',course='python') -------注册学生信息-------- 姓名: morgana age: 22 国籍: CN 课程: python
非固定参数
若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数
>>> def stu_register(name,age,*args): #*args就会把传入的参数变成一个元祖的形式 ... print(name,age,args) ... >>> stu_register("morgana",31) morgana 31 () >>> #后面这个()就是args,只是因为没传值,所以空 >>> stu_register("morgana",31,'CN','python') morgana 31 ('CN', 'python') >>>
还可以有一个**kwargs
>>> def stu_register(name,age,*args,**kwargs): #*kwargs会把多个传入的参数变成一个dict形式 ... print(name,age,args,kwargs) ... >>> stu_register("morgana",31) morgana 31 () {} #后面这个{} 就是kwargs ,只是因为没有传值,所以为空 >>> stu_register('morgana',31,'CN','python',sex='female',province='beijing') morgana 31 ('CN', 'python') {'sex': 'female', 'province': 'beijing'} >>>
局部变量
>>> name = 'morgana' >>> def change_name(name): ... print("before change:",name) ... name = 'katherine' ... print("after change",name) ... >>> change_name(name) before change: morgana after change katherine >>> print("在外面看看name改了么?",name) 在外面看看name改了么? morgana >>>
全局与局部变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量为全局变量
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序
当全局变量与局部变量同名时
在定义局部变量的子程序内,局部变量起作用:在其他地方全局变量起作用
返回值
要想获取函数的执行结果,就可以用return语句把结果返回
注意:
- 函数在执行过程中只要遇到return语句,就会停止执行并返回结果。so也也可理解为return语句代表着函数的结束
- 如果未在函数中指定return,那这个函数的返回值为None
嵌套函数
>>> name = "morgana" >>> def change_name(): ... name = "morgana2" ... ... def change_name2(): ... name = "morgana3" ... print("第3层打印",name) ... ... change_name2() #调用内层函数 ... print("第2层打印",name) ... >>> change_name() 第3层打印 morgana3 第2层打印 morgana2 >>> print("最外层打印",name) 最外层打印 morgana >>>
递归
>>> def calc(n): ... print(n) ... if int(n/2) == 0: ... return n ... return calc(int(n/2)) ... >>> calc (10) 10 5 2 1 1 >>>
递归特性
- 必须有一个明确的结束条件
- 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
- 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以递归调用的次数过多,会导致栈溢出)
堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
递归函数实际应用案例,二分查找
>>> data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35] >>> def binary_search(dataset,find_num): ... print(dataset) ... ... if len(dataset) >1: ... mid = int(len(dataset)/2) ... if dataset[mid] == find_num: #find it ... print("找到数字",dataset[mid]) ... elif dataset[mid] > find_num :# 找的数在mid左面 ... print("\033[31;1m找的数在mid[%s]左面\033[0m" % dataset[mid]) ... return binary_search(dataset[0:mid], find_num) ... else:# 找的数在mid右面 ... print("\033[32;1m找的数在mid[%s]右面\033[0m" % dataset[mid]) ... return binary_search(dataset[mid+1:],find_num) ... else: ... if dataset[0] == find_num: #find it ... print("找到数字啦",dataset[0]) ... else: ... print("没的分了,要找的数字[%s]不在列表里" % find_num) ... >>> binary_search(data,66) [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35] 找的数在mid[18]右面 [20, 21, 22, 23, 30, 32, 33, 35] 找的数在mid[30]右面 [32, 33, 35] 找的数在mid[33]右面 [35] 没的分了,要找的数字[66]不在列表里 >>>
匿名函数
匿名函数就是不需要显示的指定函数
>>> def calc(n): ... return n**n ... ... >>> print(calc(10)) 10000000000 >>>
换成匿名函数
>>> calc = lambda n:n**n >>> print(calc(10)) 10000000000 >>>
>>> res = map(lambda x:x**2,[1,5,6,4,8]) >>> for i in res: ... print(i) ... 1 25 36 16 64 >>>
函数式编程介绍
函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
定义
简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。
主要思想是把运算过程尽量写成一系列嵌套的函数调用。
高阶函数
>>> def add(x,y,f): ... return f(x) + f(y) ... >>> res = add (3,-6,abs) >>> print(res) 9 >>>
内置函数
abs
(x)
返回一个数的绝对值。参数可以是一个整数或者一个浮点数。如果参数是一个复数,那么将返回它的模。
>>> a=-1
>>> abs(a)
1
>>>
all
(iterable)
all会循环括号内的每一个元素,如果括号内的所有元素都是真的,则返回True
,如果有一个为假的那么就返回False
>>> all(["a"]) True >>> all(["a",""]) False >>>
假的参数有:False
、0
、None
、""
、[]
、()
、{}
等
查看一个元素是否为假可以使用bool进行查看
>>> bool(1) True >>> bool(0) False >>> bool([]) False
any(interable)
循环元素,如果有一个元素为真,那么就返回真
>>> any([0,1]) True >>> any([0]) False >>>
ascii(object)
在对象的类中寻找__repr__
方法,获取返回值
>>> class Foo: ... def __repr_(self): ... return "hello" ... >>> obj = Foo() >>> r = ascii(obj) >>> print(r) <__main__.Foo object at 0x7f4a395d2278> >>>
bin(x)
将整数x转换为二进制字符串,如果x不为python中int类型,x必须包含方法index()并且返回值为integer
# 返回一个整数的二进制 >>> bin(999) '0b1111100111'
# 非整型的情况,必须包含__index__()方法切返回值为integer的类型 >>> class myType: ... def __index__(self): ... return 35 ... >>> myvar = myType() >>> bin(myvar) '0b100011'
bool([x])
查看一个元素的布尔值,非真即假
>>> bool(0) False >>> bool(1) True >>> bool([1]) True >>> bool([10]) True
bytearray([source [, encoding [, errors]]])
bytearray([source [, encoding [, errors]]])返回一个byte数组。Bytearray类型是一个可变的序列,并且序列中的元素的取值范围为 [0 ,255]。
source 参数:
- 如果source为整数,则返回一个长度为source的初始化数组
- 如果source为字符串,则按照指定的encoding将字符串转换为字节序列
- 如果source为可迭代类型,则元素必须为[0,255]中的整数
- 如果source为与buffer接口一致的对象,则此对象也可以被用于初始化bytearray
>>> bytearray(3) bytearray(b'\x00\x00\x00') >>>
bytes([source[, encoding[, errors]]])
>>> bytes("asdadf",encoding="utf-8") b'asdadf' >>>
callable(object)
返回一个对象是否可以被执行
>>> def func(): ... return 123 ... >>> callable(func) True >>> func = 123 >>> callable(func) False >>>
chr(i)
返回一个数字在ASCII编码中对应的字符,取值范围256个
>>> chr(97) 'a' >>> chr(66) 'B' >>> chr(55) '7' >>> chr(255) 'ÿ' >>> chr(25) '\x19' >>> chr(65) 'A' >>>
classmethod(function)
compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
把字符串编译成python可执行的代码
>>> str = 'for i in range(0,10):print(i)' >>> c = compile(str,'','exec') >>> exec(c) 0 1 2 3 4 5 6 7 8 9 >>>
complex([real[, imag]])
创建一个值为real + imag*j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,而不需要指定第二个参数
>>> complex(1,2) (1+2j) #数字 >>> complex(1,0) (1+0j) #当做字符串处理 >>> complex("1") (1+0j) 注意:这个地方在"+"号两边不能有空格,也就是不能写成"1 + 2j",应该是 >>> complex("1+2j") (1+2j) >>>
delattr(object,name)
dict(**kwarg)
创建一个数据类型为字典
>>> dic = dict({"k1":"123","k2":"456"}) >>> dic {'k2': '456', 'k1': '123'} >>>
dir([object])
返回一个类中的所有方法
>>> dir(str) ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
divmod(a,b)
divmod(a,b)方法返回的是a//b(除法取整) 以及a对b的余数,返回结果类型为tuple
>>> divmod(10,3) (3, 1) >>>
enumerate(iterable, start=0)
为元素生成下标
>>> for n,k in enumerate(li): ... print(n,k) ... 0 a 1 b 2 c >>>
eval(expression, globals=None, locals=None)
把一个字符串当作一个表达式去执行
>>> string = "1 + 3" >>> string '1 + 3' >>> eval(string) 4 >>>
exec(object[, globals[, locals]])
把字符串当作python代码执行
>>> exec ("for n in range(5):print(n)") 0 1 2 3 4 >>>
filter(function, iterable)
筛选过滤,循环可迭代的对象,把迭代的对象当作函数的参数,如果符合条件就返回true,否则就返回false
>>> ret = filter(func,[11,22,33,44]) >>> for n in ret: ... print(n) ... 11 22 >>>
float([x])
将整数和字符串转换成浮点数
>>> float("124") 124.0 >>> float("123.45") 123.45 >>> float("-123.45") -123.45 >>>
format(value[, format_spec])
字符串格式化
>>> print('We are the {} who say "{}!"'.format('knights', 'Ni')) We are the knights who say "Ni!" >>>
frozenset([interable])
frozenset 是冻结的集合,它是不可变的,存在的哈希值,好处是他可以作为字典的key,可可以作为其他集合的元素。缺点是一旦创建不能修改,没有add,remove的方法
getattr(object, name[, default])
globals()
获取当前scripts文件内的所有全局变量
hasattr(object, name)
hash(object)
>>> a = "asdadasdwqeq234sdfdf" >>> hash(a) -2339656596927301452
help([object])
>>> help(list) Help on class list in module builtins: class list(object) | list() -> new empty list | list(iterable) -> new list initialized from iterable's items | | Methods defined here: | | __add__(self, value, /) | Return self+value. | | __contains__(self, key, /) | Return key in self. | | __delitem__(self, key, /) | Delete self[key]. | | __eq__(self, value, /) | Return self==value. | | __ge__(self, value, /) | Return self>=value. | | __getattribute__(self, name, /) | Return getattr(self, name). | | __getitem__(...) :
hex(x)
获取一个数的十六进制
>>> hex(13) '0xd' >>>
id(object)
返回一个对象的内存地址
>>> a= 123
>>> id(a)
10923296
>>>
input([prompt])
>>> name = input("please your name:") please your name:haha >>> print(name) haha >>>
int(x,base=10)
获取一个数的十进制
>>> int("31") 31 >>>
isinstance(object, classinfo)
判断对象是否是这个类创建
>>> li = [11,22,33] >>> isinstance(li,list) True >>>
issubclass(class,classinfo)
查看一个对象是否为子类
iter(object[,sentinel])
创建一个可迭代的对象
>>> obj = iter([11,22,33,44]) >>> obj <list_iterator object at 0x7f4a37a64ba8> >>> for n in obj: ... print(n) ... 11 22 33 44 >>>
len(s)
查看一个对象的长度
>>> url="geshuang.me" >>> len(url) 11 >>>
list([interable])
创建一个数据类型为列表
>>> li = list([11,22,33,44]) >>> li [11, 22, 33, 44] >>>
locals()
返回当前scripts的局部变量
>>> func=() >>> def func(): ... name='geshuang' ... print(locals()) ... >>> func() {'name': 'geshuang'} >>>
map(function,iterable,...)
把可迭代的对象作为函数的值
>>> ret = map(lambda x:x + 100,[1,2,3,4,5]) >>> for n in ret: ... print(n) ... 101 102 103 104 105 >>>
max(iterable, *[, key, default])
max(arg1, arg2, *args[, key])
取一个对象中的最大值
>>> li = list([11,22,33,44]) >>> li = [11,22,33,44] >>> max(li) 44 >>
min(arg1, arg2, *args[, key])
取一个对象中的最小值
>>> li = list([11,22,33,44]) >>> li = [11,22,33,44] >>> min(li) 11 >>>
next(inerator[,default])
每次只拿取可迭代对象的一个元素
>>> obj = iter([11,22,33,44]) >>> next(obj) 11 >>> next(obj) 22 >>> next(obj) 33 >>> next(obj) 44
object
oct(x)
获取一个字符串的八进制
>>> oct(13) '0o15' >>>
open(file,mode='r',buffering=-1,encoding=None,errors=None,newline=None.closedfd=True,opener=None)
文件操作的函数,用来做文件操作的
>>> f = open('log','r') >>>
进制转换
>>> int(10) 10 >>> int('0b11',base=2) 3 >>> int('11',base=8) 9 >>> int('0xe',base=16) 14 >>>
ord(c)
>>> ord("a") 97 >>> ord("t") 116 >>>
pow(x,y[,z])
返回一个数的N次方
>>> pow(2,10) 1024 >>> pow(2,20) 1048576 >>>
print(*object,sep='',end='\n',file=sys.stdout,flush=False)
打印输出
>>> print('hello word') hello word >>>
range(start,stop[,step])
生成一个序列
>>> range(10) range(0, 10) >>> for n in range(5): ... print(n) ... 0 1 2 3 4 >>>
repr(object)
reversed(seq)
对一个对象的元素进行反转
>>> li = [1,2,3,4] >>> reversed(li) <list_reverseiterator object at 0x7ff64a9e1278> >>> for i in reversed(li): ... print(i) ... 4 3 2 1 >>>
round(number[,ndigits])
四舍五入
>>> round(3.3) 3 >>> round(3.7) 4 >>>
set([interable])
创建一个数据类型为集合
>>> varss = set ([11,222,333]) >>> type(varss) <class 'set'> >>>
setattr(object, name, value)
slice(start, stop[, step])
元素的切片操作都是调用的这个方法
sorted(interable[,key][,reverse])
为一个对象的元素进行排序
代码: