在日常使用python时,我们经常会碰到一些特殊的函数,下面就此进行一定的总结:
1.匿名函数
匿名函数:函数名字被隐藏
匿名函数的定义语法:
lambda 参数1,参数2,...,参数n:函数体
注意:匿名函数函数体只有一行代码,并且该行代码必须具有运行结果,运行结果会被作为函数的返回值自动返回(也可以实现只输出功能,但违背了Python简化代码的初衷,一般不建议使用)
匿名函数因为没有函数名,因此通常是通过变量接受该函数,之后通过变量名(参数列表)来调用。同时匿名函数因为代码只有一句,因此匿名函数一般只用来解决比较简单的数据计算问题
##2.递归函数
如果一个函数直接或间接的调用本身,这个函数即为递归函数
注意:正确的递归函数都是有限定值的,即有递归次数的限制,不会无限递归下去。因此正确的递归函数需要设置结束位置
##3.闭包函数
闭包函数:在A函数内部定义另外一个函数B,之后B作为A函数的返回值直接被返回,此时函数B称为函数A的闭包函数。
在闭包函数中如果使用了A函数中定义的变量,此时A函数中被定义的变量会被临时存储,直到B函数调用结束时,变量才会被系统回收,从而延长A中变量释放的时间
global:声明的变量属于全局变量,此时在使用该变量时,计算机直接到函数的最外层寻找是否存在该变量
nonlocal:声明的变量属于非本地变量,此时计算机不会在当前变量使用的函数中寻找该变量,而是到该函数的最外层寻找该距离函数比较近的对应变量进行应用
# 延续num的寿命
def put(num):
print(num)
def wrapper():
nonlocal num # 非本地变量
num = num + 20
print(num)
return wrapper
fun = put(20)
# 此时put()函数已结束,但num仍存在
fun()
# 20
# 40
##4.装饰器
装饰器:装饰器的作用是,通过@语法直接用定义好的函数修饰之前已经存在的函数,从而实现对原函数功能的扩充
装饰器的优点
1.不需要修改原函数代码,即可实现对原函数功能的扩充
2.利于后期代码的维护
# 定义一个带参数的装饰器
import time
import functools
def log(txt):
def decorator(fun):
@functools.wraps(fun)
# 使用functools中函数将fun函数参数的名字赋值给warpper 等价于wrapper.__name__ = fun.__name__
def wrapper(*args, **kwargs):
print(txt, end=" ")
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
return fun(*args, **kwargs)
return wrapper
return decorator
# 功能1:求最大值
@log("您当前正在运行的函数运行的时间是")
def max_num(num1, num2):
print(max(num1, num2))
# 功能2:求最小值
@log("您当前正在运行的函数运行的时间是")
def min_num(num1, num2):
print(min(num1, num2))
max_num(10, 20)
min_num(10, 20)
# 您当前正在运行的函数运行的时间是2018-07-28 16:03:41
# 20
# 您当前正在运行的函数运行的时间是 2018-07-28 16:10:42
# 10
#5.偏函数
偏函数:将指定的函数和函数中默认的参数进行绑定,生成一个新的函数,比如把int函数和int的默认参数base
绑定生成一个新的函数int2,int2此时进行数据转化时按照二进制数据进行转化
import functools
int2 = functools.partial(int, base=2)
print(int2("1000"))
# 8
6、类的小函数
(1)isinstance:检查是不是这个对象产生的实例,返回布尔值 isinstance(a,b)
(2)issubclass:检查一个类是否是另一个类的子类,返回布尔值 如上
魔法函数:形如__xx__的函数即为魔法函数
(3)__init__ 初始化函数(构造函数)
Python的类中可以有很多个构造函数,但是最后一个构造函数会覆盖掉上面的构造函数,所以,只有最后一个init函数有效。
__new__是一个静态函数,并且至少需要传递一个参数cls。cls表示需要实例化的类。此参数在实例化时由Python解释器自动提供。另外,实例化对象时,__new__在__init__方法之前调用。有个比较形象化的比喻:__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工、初始化商品环节。
class Demo(object):
def __init__(self):
print('__init__() called...')
def __new__(cls, *args, **kwargs):
print('__new__() - {cls}'.format(cls=cls) )
return object.__new__(cls, *args, **kwargs)
if __name__ == '__main__':
de = Demo()
输出结果为:
__new__() - <class '__main__.Demo'>
__init__() called...
利用__new__函数可以实现一个简单的单例模式
补:
我们在查看一些项目时,常会发现一个__init__.py文件,
- __init__.py的在文件夹中,可以使文件夹变为一个python模块,python的每个模块对应的包中都有一个__init__.py文件的存在
- 通常__init__.py文件为空,但是我们还可以为它增加其他的功能,我们在导入一个模块时候(也叫包),实际上导入的是这个模块的__init__.py文件。我们可以在__init__.py导入我们需要的模块,不需要一个个导入
- _init__.py 中还有一个重要的变量,叫做 __all__。我们有时会使出一招“全部导入”,也就是这样:from PackageName import *,这时 import 就会把注册在包 __init__.py 文件中 __all__ 列表中的子模块和子包导入到当前作用域中来。比如:#文件 __init__.py中__all__ = ["Module1", "Module2", "subPackage1", "subPackage2"]
(4)__doc__ 文档,也就是获取类的注释文档
注意它只返回第一个三对单引号或三对双引号的类的注释文档。
(5)__dict__:
以字典的形式返回类的属性及其值,属性和值构成键值对。
如果是 对象.__dict__ 的话返回的是属性和值的字典
如果是 类.__dict__ 的话返回的是类中所有的内容,包括属性、方法
甚至注释文档等。
(6)__call__
实例化对象()自动调用类中的__call__方法,如果类中没有__call__函数的话,实例化对象()这样使用会报错
(7)__str__ 和 __repr__
其实简单来说
__str__是给人看的
__repr__是给机器看的,但是总的来说repr的优先级比str要高,因为str只能给人看,而repr既能给机器看也能给人看。
所以平时尽可能的使用repr。
》示例1
###case 1
class person:
def __init__(self,fname,lname):
self.fname=fname
self.lname=lname
p=person("san","zhang")
print(p) ###得到一个实例对象及地址
p ###得到是一个实例对象及地址
###case 2
class person:
def __init__(self,fname,lname):
self.fname=fname
self.lname=lname
def __str__(self):
return "fnmae:%s,lname:%s"%(self.fname,self.lname)
def __repr__(self):
return "fnmae:%s,lname:%s"%(self.fname,self.lname)
p=person("san","zhang")
print(p) ###由于__str__函数,正常显示
p ###由于__repr__函数,正常显示
》示例2
》示例3:常用魔法函数:
class DictDemo:
def __init__(self,key,value):
self.dict = {}
self.dict[key] = value
def __getitem__(self,key):
print("2222")
return self.dict[key]
def __setitem__(self,key,value):
print("3333")
self.dict[key] = value
def __len__(self):
print("4444")
return len(self.dict)
dictDemo = DictDemo('key0','value0')
print(dictDemo['key0']) #value0
dictDemo['key1'] = 'value1'
print(dictDemo['key1']) #value1
print(len(dictDemo)) #2
######与c不同,python在声明一个类的对象的同时,可以对对象直接进行一些操作,然后自动调用类内的魔法函数。
参考链接:
https://blog.csdn.net/w18211679321/article/details/81262221(Python基础之特殊函数类型)
https://blog.csdn.net/ziteng_du/article/details/78825913(Python基础13——python和类相关的几个函数及几个特殊函数)
https://www.cnblogs.com/jiameng991010/p/11257918.html(Python学习8——魔法方法、特性和迭代器)