闭包

  概念:外函数outer定义一个变量a,又定义一个内函数inner,而这个内函数inner访问了外函数outer的变量a,如果需要改变外函数outer的变量a的值,则需要声明 nonlocal a,之后才可以修改。由于外函数outer执行完,返回的值是内函数inner的函数变量名,在一般情况下,外函数里面的变量a就会被释放掉,而这种情况,内函数inner还是可以直接使用,即延长了变量名a的作用域(或者叫声明周期),我们成这个函数叫闭包函数,简称闭包

# 求任意直线的x对应y的值
def lines(a, b):
def get_y(x):
# 使用了外函数的变量b
nonlocal b
b = b+1
return a*x+b
return get_y # 先确定一条直线
y = lines(2,3)
print(y(1))

装饰器

  概念:就是给原有的代码增加一点新的功能,在了解完装饰器之后,你会发现装饰器是引用了闭包函数的知识,装饰器的三大要求(原则):

    1、不能修改被装饰的函数的源代码

    2、不能修改被装饰的函数的调用方式

    3、满足1、2的情况下给程序增添新的功能

  装饰器一步一步过程:

    1、假设源代码有两个函数:

# 函数1:求和
def func_test01(a, b):
print("func_test01 is running")
return a + b # 函数2:简单运算
def func_test02(a, b, c, d):
print("func_test02 is running")
return (a+b)*c//d print(func_test01(2, 4)) #func_test01 is running 6
print(func_test02(2, 3, 7, 4)) # func_test02 is running 8

    2、现在需要给这两个函数增加一样的新功能:先睡眠2秒,在执行函数,并打印耗时。但是这两个函数的形参变量不一样,我们可以借助可变参数来实现

import time
# 函数1:求和
def func_test01(a, b):
print("func_test01 is running")
return a + b # 函数2:简单运算
def func_test02(a, b, c, d):
print("func_test02 is running")
return (a+b)*c//d # 定义一个新函数,传参为需要新增功能的函数名称,在闭包函数实现主要添加的新功能
def wrapper_inner(func):
def wrapper(*args, **kwargs):
start_time = time.time()
time.sleep(2)
res = func(*args, **kwargs)
end_time = time.time()
print("耗时:", end_time-start_time)
return res
return wrapper
func_test01 = wrapper_inner(func_test01)
func_test02 = wrapper_inner(func_test02) # 原函数未改变,两者的调用方式也没有改变
print(func_test01(2, 4))
print(func_test02(2, 3, 7, 4))

    3、上面已经差不多实现了装饰器了,但是上述代码是添加了新的调用方式,以至于原有的调用方式没有改变,为此我们可以简化上述代码,将新的调用方式删除,在原有的函数上方添加@wrapper_inner即可,这样下来装饰器函数基本上已经完整了。

      @wrapper_inner 等价于 func_test01 = wrapper_inner(func_test01)

      @wrapper_inner 等价于 func_test01 = wrapper_inner(func_test01)

      @wrapper_inner默认是将被装饰的函数名称传递给装饰函数的形参func变量

import time
# 函数1:求和
@wrapper_inner
def func_test01(a, b):
print("func_test01 is running")
return a+b # 函数2: 简单运算
@wrapper_inner
def func_test02(a, b, c, d):
print("func_test02 is running")
return (a+b)*c//d # 定义一个新函数,传参为需要新增功能的函数名称,在闭包函数实现主要添加的新功能
def wrapper_inner(func):
def wrapper(*args, **kwargs):
start_time = time.time()
time.sleep(2)
res = func(*args, **kwargs)
end_time = time.time()
print("耗时:", end_time-start_time)
return res
return wrapper # 原函数未改变,两者的调用方式也没有改变
print(func_test01(2, 4))
print(func_test02(2, 3, 7, 4))

    4、补添一个新的功能,给装饰器函数传递一个参数,在这里博主只是给函数做一个标记,验证是哪个被装饰函数执行

import time

# 函数1:求和
@wrapper_outer(parameter="func_test01")
def func_test01(a, b):
print("这是个求和函数,返回值是两者之和")
return a + b # 函数2:简单运算
@wrapper_outer(parameter="func_test02")
def func_test02(a, b, c, d):
print("这是个简单运算函数,返回值是运算之后的整数值")
return (a+b)*c//d # 装饰器函数传递被装饰函数的名称,作为标记,并打印
def wrapper_outer(parameter):
# 定义一个新函数,传参为需要新增功能的函数名称,在闭包函数实现主要添加的新功能
def wrapper_inner(func):
def wrapper(*args, **kwargs):
# 分开执行,可以任意增添被装饰函数的的功能
# 这样做是可以让被装饰函数新增不一样的功能
if parameter == "func_test01":
start_time = time.time()
time.sleep(2)
res = func(*args, **kwargs)
end_time = time.time()
print("被装饰的函数", parameter,"\t耗时:", end_time-start_time)
return res
elif parameter == "func_test02":
start_time = time.time()
time.sleep(1)
res = func(*args, **kwargs)
time.sleep(1)
end_time = time.time()
print("被装饰的函数", parameter,"\t耗时:", end_time-start_time)
return res
return wrapper
return wrapper_inner # 原函数未改变,两者的调用方式也没有改变
print(func_test01(2, 4))
print(func_test02(2, 3, 7, 4))

私有化

  在python中也有类似于Java中私有变量和保护变量,虽然python中没有这种概念,但是作用还是和Java一样(可能说错了,没学过多少Java)。

    在python中"私有变量"的声明双下划线__xxx,这个变量在类作用域外,什么对象都不能访问,在类作用域内可以访问和修改。如果在类外访问或者修改,则需要在类内另外定义方法

    "保护变量"的声明是单下滑线_xxx,这个变量只能在当前模块访问和修改,但是可以导入到另外一个模块使用,导入的方式:import xxx(模块名)

    "魔法方法"的声明是以双下划线开头和结尾的__xxx__,这是python提供的特殊方法,有些时候我们可以自定义原有的"魔法方法"

class People(object):
def __init__(self, name, gender, age):
self.name = name
self._gender = gender
self.__age = age
def get_age(self):
return self.__age
def set_age(self, age):
self.__age = age
def show(self):
print("名字:", self.name, "\t性别:", self._gender, "\t年龄", self.__age) if __name__ == "__main__":
people = People("aaa", "female", 22)
people._gender = "male"
print(people._gender) # male
people.set_age(25) # 年龄转换25
print(people.get_age()) #
# 查看结果
people.show()
# 类外不能访问私有变量
# print(people.__age) # error
# print(People.__age) # error

property

  上述代码中的”私有变量“只能靠调用方法进行访问和修改,为了让私有变量的访问和修改的方式和普通的对象的属性一样,property就起到了重要的作用。property有两种方式处理私有变量

  1、先在类内定义两个方法,然后用property(访问变量的方法,设置变量的方法),顺序不能颠倒,将其赋值给一个变量名,这个变量是在类外进行访问和修改的

class People(object):
def __init__(self, name, gender, age):
self.name = name
self._gender = gender
self.__age = age
# 先定义好私有变量的访问和设置方法
def get_age(self):
return self.__age
def set_age(self, age):
self.__age = age
# 变量名就是类外访问的变量名,通过下面方式进行设置即可
age = property(get_age, set_age)
def show(self):
print("名字:", self.name, "\t性别:", self._gender, "\t年龄", self.__age) if __name__ == "__main__":
people = People("aaa", "female", 22)
people._gender = "male"
print(people._gender) # male
people.age = 25 # 年龄转换25
print(people.age) #
# 查看结果
people.show()

  2、使用装饰器简化: @property、@x.setter、@x.deleter(这个一般用不到,这里不做介绍),这里很关键,x(变量名)和被装饰的方法名一定要相同,这个变量名是可以在类外进行访问和修改的

class People(object):
def __init__(self, name, gender, age):
self.name = name
self._gender = gender
self.__age = age
# @property 装饰的是返回私有变量的值
@property
def age(self):
return self.__age
# 变量名.setter,这个变量名是类外进行访问和修改的
@age.setter
def age(self, age):
self.__age = age def show(self):
print("名字:", self.name, "\t性别:", self._gender, "\t年龄", self.__age) if __name__ == "__main__":
people = People("aaa", "female", 22)
people._gender = "male"
print(people._gender) # male
people.age = 25 # 年龄转换25
print(people.age) #
# 查看结果
people.show()

reload

  概念:重新加载模块:即原先导入的模块没有改变,但是在之后,导入的模块改变了,那么就要重新载入

# 假设自己写的模块mymodel
import mymodel # 之后mymodel代码程序或者功能改变了,在运行的过程中需要重新导入
mymodel.reload

python高级编程——入门语法(二)的更多相关文章

  1. python高级编程——入门语法(一)

    元类 在python中一切皆对象,类也是对象,只不过类是一个创建对象的对象,我们可以在类中动态的创建一个类,比如 def func(name): if name == "Plane" ...

  2. Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍

    原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Gen ...

  3. python高级编程之列表推导式

    1. 一个简单的例子 在Python中,如果我们想修改列表中所有元素的值,可以使用 for 循环语句来实现. 例如,将一个列表中的每个元素都替换为它的平方: >>> L = [1, ...

  4. VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)

    VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)-软件开发-鸡啄米 http://www.jizhuomi.com/software/141.html   上一讲中讲了VS20 ...

  5. python高级编程:有用的设计模式1

    # -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#设计械是可复用的,某种程序上它对软件设计中觉问题提供的语言 ...

  6. python高级编程技巧

    由python高级编程处学习 http://blog.sina.com.cn/s/blog_a89e19440101fb28.html Python列表解析语法[]和生成 器()语法类似 [expr  ...

  7. 第十一章:Python高级编程-协程和异步IO

    第十一章:Python高级编程-协程和异步IO Python3高级核心技术97讲 笔记 目录 第十一章:Python高级编程-协程和异步IO 11.1 并发.并行.同步.异步.阻塞.非阻塞 11.2 ...

  8. python高级编程:有用的设计模式3

    # -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#访问者:有助于将算法从数据结构中分离出来"&qu ...

  9. python高级编程:有用的设计模式2

    # -*- coding: utf-8 -*- __author__ = 'Administrator' #python高级编程:有用的设计模式 #代理 """ 代理对一 ...

随机推荐

  1. JAVA的toString方法的一个小例子

    Object是一个抽象类,他有很有方法,其中的toString方法是我们常见的一个方法,我们可以看这段代码 package com.com.day1; public class ToStringTes ...

  2. mysql性能优化随笔

    mysql性能优化是一个很大的命题,这里只记录一下近期的一些小经验. 曾经以为看了点create table时加index的语法就觉得自己知道怎么做mysql优化了,后来又看了点介绍mysql索引底层 ...

  3. Github实战测试情况

    测试情况 很久没有熬夜测试程序了,经过测试,没有复现功能的有echo.葫芦娃.火鸡堂.那周余嘉熊掌将得队.为了交项目而干杯.修!咻咻!.云打印和追光的人.据汪老师反应在现场实践课程中大都能实现的,公平 ...

  4. mybatis-config.xml 知识点

    typeAliases 标签:配置别名,主要用于 XML 文件中的 resultType 参数. mappers 标签:配置所有的 mapper. MyBatis 和 Spring Boot 配合使用 ...

  5. Excel引用和数学函数

    1.indirect函数--引用函数 indirect 英 [ˌɪndəˈrekt] 美 [ˌɪndəˈrekt] adj. 间接的;附带的;闪烁其词的;拐弯抹角的;迂回的;弯曲的 indirect函 ...

  6. 简析平衡树(四)——FHQ Treap

    前言 好久没码过平衡树了! 这次在闪指导的指导下学会了\(FHQ\ Treap\),一方面是因为听说它可以可持久化,另一方面则是因为听说它是真的好写. 简介 \(FHQ\ Treap\),又称作非旋\ ...

  7. ES5.1下的作用域链

    作用域链(ES5.1规格视角) javascript作用域类型 javascript采用的是词法作用域(静态作用域) 与之相对的是动态作用域,以下的例子可以很好地说明 let a = 3 functi ...

  8. 配置Hive 支持 JSON 存储

    1.说明 hive默认使用分隔符如空格,分号,"|",制表符\t来格式化数据记录,对于复杂数据类型如json,nginx日志等,就没有办法拆分了,这时候需要更加强大的SerDe来处 ...

  9. [LeetCode] 130. Surrounded Regions 包围区域

    Given a 2D board containing 'X' and 'O'(the letter O), capture all regions surrounded by 'X'. A regi ...

  10. 《30天自制操作系统》笔记3 --- (Day2 上节)完全解析文件系统

    Day2 汇编语言学习与Makefile入门 本文仅带着思路,研究源码里关于文件系统的参数 关于day2主程序部分及更多内容,请看<30天自制操作系统>笔记 导航 发现学习中的变化 源码差 ...