[学习总结] python语言学习总结 (三)

函数闭包

定义

延伸了作用域的函数(能访问定义体之外定义的非全局变量

作用

  1. 共享变量的时候避免使用了不安全的全局变量
  2. 允许将函数与某些数据关联起来,类似于简化版面向对象编程
  3. 相同代码每次生成的闭包,其延伸的作用域都彼此独立(计数器,注册表)
  4. 函数的一部分行为在编写时无法预知,需要动态实现,同时又想保持接口一致性
  5. 较低的内存开销:类的生命周期远大于闭包
  6. 实现装饰器

代码

print("Class方式:")
class Averager:def __init__(self):self.series = []def __call__(self,new_val):self.series.append(new_val)return sum(self.series)/len(self.series)
avg1 = Averager()
print(avg1(3))
print(avg1(2))print("闭包方式:")
def Avg_1():count = 0total = 0def Avg_2(val):nonlocal total,counttotal+=valcount+=1return total/countreturn Avg_2
avg = Avg_1()
print(avg(9))
print(avg(10))
'''
输出
Class方式:
3.0
2.5
闭包方式:
9.0
9.5
'''

理解

功能说明

这段代码需要解决的是,定义一个average函数,我们每次传进去一个值,都可以得到这个值和之前传入值的平均值。比如第一次传入1,均值就是1,第二次传入2,均值就是1.5,以此类推。

类方式

第一种方式是通过构建一个类,这也是我们通常容易想到的方式,利用在类里面创建一个list,每次调用都将新值append进去,这是一种解决方法。

函数闭包方式

这里跟前面提到的作用域是有关的,函数闭包延伸了作用域,我们可以看到,我们的外层函数只是为了存储两个变量而已,没有其他作用了。其实这时候应该有个疑惑,在调用Avg_1()之后,由于count和total是在Loval层,函数调用结束了应该销毁了才是,但实际上并没有,我们在Avg_2中通过nolocal关键字延长了两个变量的生命周期,使得我们在每次调用的时候都能访问都两个变量,达到效果。

装饰器

为什么会出现装饰器这个东西

  • 名称管理
  • 显示调用
  • 就近原则
  • 充分复用

@语法糖

'@' 用做函数的修饰符,可以在模块或者类的定义层内对函数进行修饰,出现在函数定义的前一行,不允许和函数定义在同一行。

什么是装饰器

  • 装饰器是一个可调用的对象,以某种方式增强函数的功能
  • 装饰器是一个语法糖,在源码中标记函数(此源码指编译后的源码)
  • 解释器解析源码的时候将被装饰的函数作为第一个位置参数传给装饰器
  • 装饰器可能会直接处理被装饰函数,然后返回它(一般仅修改属性,不修改代码)
  • 装饰器也可能用一个新的函数或可调用对象替换被装饰函数(但核心功能一般不变)
  • 装饰器仅仅看着像闭包,其实功能的定位与闭包有重合也有很大区别
  • 装饰器模式的本质是元编程:在运行时改变程序行为
  • 装饰器的一个不可忽视的特性:在模块加载时立即执行
  • 装饰器是可以堆叠的,自底向上逐个装饰
  • 装饰器是可以带参数的,但此时至少要写两个装饰器
  • 装饰器的更加Pythonic的实现方式其实是在类中实现 call() 方法

代码

def check_param(**kw):flag = kw.get('flag')def check_p(func):def decorate(*args):if flag:if not all([isinstance(arg,int) for arg in args]):raise TypeError("{} only accepts integers as argument".format(func.__name__))return func(*args)return decoratereturn check_p@check_param(flag=True)
def my_sum(a,b):return a+bif __name__=='__main__':print(my_sum(1,2))print(my_sum(1,2.0))'''
输出
3
Traceback (most recent call last):File "/home/xueaoru/文档/pydemo/blog.py", line 18, in <module>print(my_sum(1,2.0))File "/home/xueaoru/文档/pydemo/blog.py", line 7, in decorateraise TypeError("{} only accepts integers as argument".format(func.__name__))
TypeError: my_sum only accepts integers as argument'''

解释

上面的代码是为了完成一个检查my_sum函数的参数是否是整数的功能的装饰器,同时增加了开关功能,我们将flag设置为true就是开启检查功能,如果不是整数,则直接报错。

理解

装饰器是对函数在不改变原有函数内部实现的情况下,对原有函数进行功能增强。而@语法糖是对原函数进行修饰的修饰符,当调用@语法糖进行修饰的时候,即使该函数并不调用,也会执行修饰语句,因为触发了运行装饰器。这时候该函数作为参数传给修饰函数的外部函数,然后该函数作为引用赋值给内部函数的函数名,也就是说我们真正的操作是在内部函数中进行的,因此可以在内部函数中对原函数进行功能增强。其中,有参数的时候呢,内部函数也需要通过*和**拆包得到参数,原函数有返回值的时候呢,我们在调用完原函数的时候也应该给出返回值。而装饰器本身带参数的时候呢,可以在装饰函数外再加一层接收参数的包装得到参数。

OOP In Python

概念

一切都是对象

从语言设计层面理解Python中的数据类型:一切都是对象,都是从Object继承过来的。Object由三部分组成:identity、type、value。

identity

理解

当Objects创建之后呢,identity也不会改变,直到被销毁。我觉得跟c++里的地址差不多吧,当然也不能完全这么理解,也有不同的方。

要点

  • 变量存储的是创建的Object的identity
  • 创建出来的不同Object有不同的identity
  • 变量的id变了不是因为Object的identity变了,而是对应的Object变了
  • 对于不可变对象而言,计算结果如果已经存在,可以直接返回相同的identity

type

要点

  • 当Object创建后,其type不会改变
  • type决定了一个Object可以支持那些运算,可能的值在哪些范围

value

要点

  • 有些Object的value可以改变:可变对象
  • 有些Object的value不可以改变:不可变对象

每一个class在定义的时候如果没有继承的话,那么他继承的就是Object这个超级class,而每一个自定义的class在python中都是一个type object。

@classmethod

理解

可以把类中的某个方法变成这个类的方法而不依赖于对象,也就是说,在对象没有创建的时候,我们也可以调用这个类的方法执行一定的操作。这就有点像C++中的静态成员函数。

代码

class Student:teacher_name = "Omg"def __init__(self,name):self._name = name@classmethoddef Teacher(cls):print(cls.teacher_name)def Me(self):print(self._name)
if __name__== '__main__':aa = Student("xue")aa.Teacher()aa.Me()Student.Teacher()
'''
Omg
xue
Omg
'''

解释

这段代码是通过调用Teacher方法得到老师的名字,可以看出,我们就算不通过对象直接调用,也可以输出老师的名字。classmethod就起这个作用。

@property

理解

本质上这是一个装饰器,可以省去写get、set函数的对外绑定。

property

函数原型为

property(fget=None, fset=None, fdel=None, doc=None)

代码

@property与下面的代码效果是一样的

class Teacher:def __init__(self,name,subject):self._name = nameself._subject = subjectdef setName(self,name):self._name = namedef getName(self):return self._namedef setSubject(self,subject):self._subject = subjectdef getSubject(self):return self._subjectdef show(self):print("name is:{} and subject is:{}".format(self._name,self._subject))name = property(getName,setName)subject = property(getSubject,setSubject)
if __name__ == '__main__':t = Teacher("A","math")t.show()t.name = "B"t.subject = "English"t.show()
'''
name is:A and subject is:math
name is:B and subject is:English
'''

使用@property之后的更加优美的版本

class Teacher:def __init__(self,name,subject):self._name = nameself._subject = subject@propertydef name(self):return self._name@name.setterdef name(self,name):self._name = name@propertydef subject(self):return self._subject@subject.setterdef subject(self,subject):self._subject = subjectdef show(self):print("name is:{} and subject is:{}".format(self._name,self._subject))
if __name__ == '__main__':t = Teacher("A","math")t.show()t.name = "B"t.subject = "English"t.show()

注意

这里@property必须在setter前面初始化,这个应该很容易理解,因为解释器读程序的时候是从上往下读的。

Special method

要点

  1. 之所有要实现special method,是为了让自定义的class与python中的内置函数无缝衔接
  2. python中有大量的内置函数,而这些函数中绝大部分是special method
  3. python中的special method :https://rszalski.github.io/magicmethods/

代码

class A:def __init__(self):passdef __str__(self):return "I am str"def __len__(self):return 15def __bool__(self):return Falseif __name__ == '__main__':a = A()print(a,len(a),a==True)

转载于:https://www.cnblogs.com/aoru45/p/9937751.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/570175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jQuery中$.each()方法的使用

$.each()是对数组&#xff0c;json和dom结构等的遍历&#xff0c;说一下他的使用方法吧。 1、遍历一维数组 var arr1[aa,bb,cc,dd];//两个参数&#xff0c;第一个参数表示遍历的数组的下标&#xff0c;第二个参数表示下标对应的值$.each(arr1,function(i,val){console.log(ival…

【学习笔记】慕课网—Java设计模式精讲 第3章 软件设计七大原则-3-6 迪米特原则(最少知道原则)...

/** * 软件设计七大原则-迪米特原则 学习笔记 * author cnRicky * date 2018.11.10 */迪米特原则&#xff08;最少知道原则&#xff09; 一个对象应该对其他对象保持最少的了解。又叫最少知道原则 迪米特原则主要强调&#xff1a;尽量降低类与类之间的耦合 优点&#xff1a;降…

ORA-01745: 无效的主机/绑定变量名

问题描述&#xff1a;oracle中执行插入语句时报错 解决方案&#xff1a;缺失逗号

to_date , to_char

select sum(t.paid_fee)from order_payment_log twhere to_char(to_date(t.edit_time, yyyy-MM-dd HH24:mi:ss),yyyy-MM-dd) to_char(sysdate, yyyy-MM-dd)and t.paid_state Y; to_char to_char:将日期转换为字符串, to_char(to_date(t.edit_time, yyyy-MM-dd HH24:mi:ss),yy…

Duplicate local variable variable

问题描述&#xff1a;重复定义了变量。

mac/linux 解决启动命令行出现declare问题

问题描述&#xff1a;启动命令行时出现以下现象&#xff0c;如图所示&#xff1a; 问题解决&#xff1a; 在配置环境变量时&#xff0c;在某一行直接单独写了一个export,要么在bashrc中&#xff0c;要么在bash_profile等配置文件中&#xff0c;系统加载环境变量时就出现了上述情…

java 取Blob转为String

InputStream ins null;StringBuffer sb new StringBuffer();try {//blob要转换的Blob字段。ins blob.getBinaryStream();byte[] dis new byte[1024];int len 0;//开始处理流,并且显示while ((len ins.read(dis)) ! -1) {String disp new String(dis,0,len);sb.append(di…

分式递推

对于一类问题&#xff0c;比如是数列&#xff08;递推&#xff09;&#xff0c;然后给你两头的a[1]和a[n],如果含有分式&#xff0c;可以考虑乘过去&#xff0c;和一种二分的题目比较像&#xff0c;可能就会发现递推的规律&#xff0c;而且递推也可以只搞系数&#xff0c;没必要…

Blob和Clob的区别和用法

BLOB和CLOB都是大字段类型&#xff0c; 1、BLOB是按二进制来存储的&#xff0c;通常像图片、文件、音乐等信息就用BLOB字段来存储&#xff0c;先将文件转为二进制再存储进去。 2、CLOB是可以直接存储文字的&#xff0c;像文章或者是较长的文字&#xff0c;就用CLOB存储&#xf…

MVC 模式和模型 2

MVC框架 一个实现 MVC 模式的应用包含模型、视图、控制器 3 个模块&#xff1a; 模型&#xff1a;封装了应用的数据和业务逻辑&#xff0c;负责管理系统业务数据 视图&#xff1a;负责应用的展示 控制器&#xff1a;负责与用户进行交互&#xff0c;接收用户输入、改变模型、调整…

splite和map的结合使用

split() 方法用于把一个字符串分割成字符串数组。 Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。 作用&#xff1a;分割出来的字符串储存在map对象(key,value)中&#xff0c;便于前后台使用。 Map<String, Object> paramMap new HashMap<S…

Delphi与各数据库数据类型比较

Delphi数据类型与各数据库数据类型对比如下表&#xff0c;如有具体说明见表中脚注&#xff1a; Delphi Type Oracle Types SQL Server Types MySQL Types [1] InterBase Types PostgreSQL Types SQLite Types ftSmallint NUMBER(p, 0)[2] (p < 5) SMALLINT …

mybatis foreach collection

foreach的主要用在构建in条件中&#xff0c;它可以在SQL语句中进行迭代一个集合。 foreach元素的属性主要有 item&#xff0c;index&#xff0c;collection&#xff0c;open&#xff0c;separator&#xff0c;close。 item表示集合中每一个元素进行迭代时的别名&#xff0c;in…

Java中线程池,你真的会用吗?

在《深入源码分析Java线程池的实现原理》这篇文章中&#xff0c;我们介绍过了Java中线程池的常见用法以及基本原理。 在文中有这样一段描述&#xff1a; 可以通过Executors静态工厂构建线程池&#xff0c;但一般不建议这样使用。 关于这个问题&#xff0c;在那篇文章中并没有深…

java (lodop) 打印实例

首先在lodop官网下载相关文件&#xff08;js、css等&#xff09;&#xff1a;http://www.lodop.net/download.html 在下载好的包里 除了html页面 其他的js、css等拷贝到项目的一个目录下、新建个lodop文件夹。 lodop主要接口函数如下&#xff1a; ● PRINT_INIT(strPrintTaskN…

深入了解java虚拟机(JVM) 第四章 对象的创建

一、对象的创建过程 对象的创建过程大致可以分为六步&#xff0c;其中对象的分配尤为重要&#xff1a; 二、对象分配内存 一般来说对象分配内存有两种方式&#xff1a; 第一种是指针碰撞&#xff0c;这是一种比较理想的方式&#xff1a;如果Java堆是绝对规整的&#xff1a;一边…

LODOP使用问题解决汇总

LODOP 打印控件出现问题及修改方法 问题1 、打印网页时页面出现电脑设置的底色如何解决&#xff1f; 解决方法 &#xff1a;按照如下方式添加HTML页面 var strHTML"<body stylemargin:0;background-color: white>"document.getElementById("table02&qu…

[UWP]使用Picker实现一个简单的ColorPicker弹窗

[UWP]使用Picker实现一个简单的ColorPicker弹窗 原文:[UWP]使用Picker实现一个简单的ColorPicker弹窗在上一篇博文《[UWP]使用Popup构建UWP Picker》中我们简单讲述了一下使用Popup构建适用于MVVM框架下的弹窗层组件Picker的过程。但是没有应用实例的话可能体现不出Picker相对于…

java sort排序

问题&#xff1a;对list中的对象中的属性值排序&#xff1a; User对象&#xff1a; public class User {private int id;private String Name; public int getid() {return id;}public void setid(int id) {this.id id;}public String getName() {return Name;}pub…

C# WebRequest.Create 锚点“#”字符问题

背景 在与后台API接口对接时&#xff0c;如将网页Url作为参数请求数据时&#xff0c;如果是锚点参数&#xff0c;则会丢失。 锚点参数 请求通过WebRequest.Create创建一个WebRequest&#xff1a; 1 var uri "https://id.test.xxx.com/api/v1/auth/sso/url?redirectUrlht…