关于python函数修饰的信息

python让一个循环不影响其他代码循环是一种常用的程序控制结构 。我们常说,机器相比人类的最大优点之一,就是机器可以不眠不休的重复做某件事情 , 但人却不行 。而“循环”,则是实现让机器不断重复工作的关键概念 。
在循环语法方面,Python 表现的即传统又不传统 。它虽然抛弃了常见的 for(init;condition;incrment) 三段式结构,但还是选择了 for 和 while 这两个经典的关键字来表达循环 。绝大多数情况下,我们的循环需求都可以用 forin来满足, while相比之下用的则更少些 。
虽然循环的语法很简单,但是要写好它确并不容易 。在这篇文章里,我们将探讨什么是“地道”的循环代码,以及如何编写它们 。
什么是“地道”的循环?
“地道”这个词,通常被用来形容某人做某件事情时,非常符合当地传统,做的非常好 。打个比方,你去参加一个朋友聚会,同桌的有一位广东人,对方一开口,句句都是标准京腔、完美儿化音 。那你可以对她说:“您的北京话说的真地道” 。
既然“地道”这个词形容的经常是口音、做菜的口味这类实实在在的东西,那“地道”的循环代码又是什么意思呢?让我拿一个经典的例子来解释一下 。
如果你去问一位刚学习 Python 一个月的人:“如何在遍历一个列表的同时获取当前下标?” 。他可能会交出这样的代码:
?
上面的循环虽然没错 , 但它确一点都不“地道” 。一个拥有三年 Python 开发经验的人会说 , 代码应该这么写:
enumerate() 是 Python 的一个内置函数,它接收一个“可迭代”对象作为参数,然后返回一个不断生成 (当前下标,当前元素) 的新可迭代对象 。这个场景使用它最适合不过 。
所以,在上面的例子里,我们会认为第二段循环代码比第一段更“地道” 。因为它用更直观的代码,更聪明的完成了工作 。
【关于python函数修饰的信息】enumerate() 所代表的编程思路
不过 , 判断某段循环代码是否地道,并不仅仅是以知道或不知道某个内置方法作为标准 。我们可以从上面的例子挖掘出更深层的东西 。
如你所见,Python 的 for 循环只有 forin这一种结构 , 而结构里的前半部分 - 赋值给 item- 没有太多花样可玩 。所以后半部分的 可迭代对象 是我们唯一能够大做文章的东西 。而以 enumerate() 函数为代表的“修饰函数”,刚好提供了一种思路:通过修饰可迭代对象来优化循环本身 。
这就引出了我的第一个建议 。
建议1:使用函数修饰被迭代对象来优化循环
使用修饰函数处理可迭代对象,可以在各种方面影响循环代码 。而要找到合适的例子来演示这个方法,并不用去太远,内置模块 itertools 就是一个绝佳的例子 。
简单来说,itertools 是一个包含很多面向可迭代对象的工具函数集 。我在之前的系列文章《容器的门道》里提到过它 。
如果要学习 itertools,那么 Python 官方文档 是你的首?。?里面有非常详细的模块相关资料 。但在这篇文章里,侧重点将和官方文档稍有不同 。我会通过一些常见的代码场景 , 来详细解释它是如何改善循环代码的 。
1. 使用 product 扁平化多层嵌套循环
虽然我们都知道“扁平的代码比嵌套的好” 。但有时针对某类需求,似乎一定得写多层嵌套循环才行 。比如下面这段:
?
对于这种需要嵌套遍历多个对象的多层循环代码,我们可以使用 product() 函数来优化它 。product() 可以接收多个可迭代对象,然后根据它们的笛卡尔积不断生成结果 。
?
相比之前的代码,使用 product() 的函数只用了一层 for 循环就完成了任务,代码变得更精炼了 。
2. 使用 islice 实现循环内隔行处理
有一份包含 Reddit 帖子标题的外部数据文件,里面的内容格式是这样的:
?
可能是为了美观,在这份文件里的每两个标题之间,都有一个 "---" 分隔符 。现在,我们需要获取文件里所有的标题列表,所以在遍历文件内容的过程中,必须跳过这些无意义的分隔符 。
参考之前对 enumerate() 函数的了解,我们可以通过在循环内加一段基于当前循环序号的 if 判断来做到这一点:
?
但对于这类在循环内进行隔行处理的需求来说 , 如果使用 itertools 里的 islice() 函数修饰被循环对象 , 可以让循环体代码变得更简单直接 。
islice(seq,start,end,step) 函数和数组切片操作( list[start:stop:step] )有着几乎一模一样的参数 。如果需要在循环内部进行隔行处理的话,只要设置第三个递进步长参数 step 值为 2 即可(默认为 1) 。
?
3. 使用 takewhile 替代 break 语句
有时,我们需要在每次循环开始时,判断循环是否需要提前结束 。比如下面这样:
?
对于这类需要提前中断的循环 , 我们可以使用 takewhile() 函数来简化它 。takewhile(predicate,iterable)会在迭代 iterable 的过程中不断使用当前对象作为参数调用 predicate 函数并测试返回结果,如果函数返回值为真,则生成当前对象,循环继续 。否则立即中断当前循环 。
使用 takewhile 的代码样例:
?
itertools 里面还有一些其他有意思的工具函数,他们都可以用来和循环搭配使用,比如使用 chain 函数扁平化双层嵌套循环、使用 zip_longest 函数一次同时循环多个对象等等 。
篇幅有限,我在这里不再一一介绍 。如果有兴趣 , 可以自行去官方文档详细了解 。
4. 使用生成器编写自己的修饰函数
除了 itertools 提供的那些函数外,我们还可以非常方便的使用生成器来定义自己的循环修饰函数 。
让我们拿一个简单的函数举例:
?
在上面的函数里,循环体内为了过滤掉所有奇数 , 引入了一条额外的 if 判断语句 。如果要简化循环体内容,我们可以定义一个生成器函数来专门进行偶数过滤:
?
将 numbers 变量使用 even_only 函数装饰后,sum_even_only_v2 函数内部便不用继续关注“偶数过滤”逻辑了,只需要简单完成求和即可 。
Hint:当然,上面的这个函数其实并不实用 。在现实世界里,这种简单需求最适合直接用生成器/列表表达式搞定:sum(numfornuminnumbersifnum%2==0)
建议2:按职责拆解循环体内复杂代码块
我一直觉得循环是一个比较神奇的东西,每当你写下一个新的循环代码块,就好像开辟了一片黑魔法阵,阵内的所有内容都会开始无休止的重复执行 。
但我同时发现,这片黑魔法阵除了能带来好处,它还会引诱你不断往阵内塞入越来越多的代码 , 包括过滤掉无效元素、预处理数据、打印日志等等 。甚至一些原本不属于同一抽象的内容,也会被塞入到同一片黑魔法阵内 。
Python 中的 classmethod 和 staticmethod 有什么具体用途classmethod:类方法staticmethod:静态方法
在python中,静态方法和类方法都是可以通过类对象和类对象实例访问 。但是区别是:
@classmethod 是一个函数修饰符 , 它表示接下来的是一个类方法 , 而对于平常我们见到的则叫做实例方法 。类方法的第一个参数cls,而实例方法的第一个参数是self,表示该类的一个实例 。
普通对象方法至少需要一个self参数,代表类对象实例
类方法有类变量cls传入,从而可以用cls做一些相关的处理 。并且有子类继承时 , 调用该类方法时 , 传入的类变量cls是子类,而非父类 。对于类方法,可以通过类来调用,就像C.f(),有点类似C++中的静态方法, 也可以通过类的一个实例来调用,就像C().f(),这里C() , 写成这样之后它就是类的一个实例了 。
静态方法则没有,它基本上跟一个全局函数相同,一般来说用的很少
Example 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class a():
@staticmethod
def staticm():
print 'static'
def normalm(self):
print 'nomarl',self
@classmethod
def classm(cls):
print 'class',cls
a1=a()
a1.normalm()
nomarl __main__.a instance at 0x84dddec
a1.staticm()
static
a1.classm()
class __main__.a
type(a)
type 'classobj'
type(a1)
type 'instance'
Example 2:
class A(object):
@classmethod
def cm(cls):
print '类方法cm(cls)调用者:', cls.__name__
@staticmethod
def sm():
print '静态方法sm()被调用'
class B(A):
pass
A.cm()
B.cm()
A.sm()
B.sm()
输出:
类方法cm(cls)调用者: A
类方法cm(cls)调用者: B
静态方法sm()被调用
静态方法sm()被调用
@classmethod与@staticmethod的应用实例
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class TClassStatic(object):
obj_num = 0
def __init__(self, data):
self.data = https://www.04ip.com/post/data
TClassStatic.obj_num= 1
def printself(self):
print("self.data: ", self.data)
@staticmethod
def smethod():
print("the number of obj is : ", TClassStatic.obj_num)
@classmethod
def cmethod(cls):
print("cmethod : ", cls.obj_num)
cls.smethod()
def main():
objA = TClassStatic(10)
objB = TClassStatic(12)
objB.printself()
objA.smethod()
objB.cmethod()
print("------------------------------")
TClassStatic.smethod()
TClassStatic.cmethod()
if __name__ == "__main__":
main()123456789101112131415161718192021222324252627282930313233
输出结果如下:
('self.data: ', 12)
('the number of obj is : ', 2)
('cmethod : ', 2)
('the number of obj is : ', 2)
------------------------------
('the number of obj is : ', 2)
('cmethod : ', 2)
('the number of obj is : ', 2)
Python中的“ @”(@)符号有什么作用?【@】符号在python中是装饰器python函数修饰的意思 。
装饰器对一个可调用对象(函数、方法、类等等)进行装饰python函数修饰,它返回的也是一个可调用对象 。
一般情况下python函数修饰,装饰器是对被装饰对象的修饰与增强 。用现实事物类比的话,可以类比为中间商python函数修饰:中间商不生产产品,它将工厂生产的产品进行包装、运输后再销售给顾客 。装饰器不实现核心功能 , 它提供对目标函数调用的封装与强 。
它装饰的方法返回值是一个对象(BillList、Bill、List[BillDetail]等),而装饰器【enabled_cache】的作用如它的名称一样:使用缓存 。可以看到,这个装饰器函数中定义python函数修饰了一个函数【wrapper】然后将这个wrapper作为返回值 。这样,原本调用ProductionBos.bill_with_last_week的代码就不需要做任何改变就能享受到ProductionBos.bill_with_last_week原有的功能(得到一个BillList对象)和enabled_cache提供的附加功能(如果该对象有缓存,就不再从数据库查询) 。
python 中 @ 是什么意思修饰符python函数修饰,比如说
class A:
@staticmethod
def m(self):
pass
就相当于
class A:
def m(self):
pass
m = staticmethod(m)
其实就是一调用一个函数参数为下行python函数修饰的变量 , 并且替换它
扩展资料:
函数修饰符
@用做函数的修饰符,可以在模块或者类的定义层内对函数进行修饰 , 出现在函数定义的前一行,不允许和函数定义在同一行 。
一个修饰符就是一个函数,它将被修饰的函数作为参数,并返回修饰后的同名函数或其python函数修饰他可调用的东西 。
在Python的函数中偶尔会看到函数定义的上一行有@functionName的修饰,当解释器读到@这样的修饰符的时候会优先解除@后的内容 , 直接就把@的下一行的函数或者类作为@后边函数的参数,然后将返回值赋给下一个修饰的函数对象 。
参考资料来源:百度百科-Python (计算机程序设计语言)
关于python函数修饰和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息 , 记得收藏关注本站 。

    推荐阅读