Python-04-基础

一、装饰器(decorator)

  • 装饰器本质上也是函数,目的是为其他函数添加附加功能(装饰其他函数)
  • Python通过使用装饰器来达到代码的开放与封闭。

原则:

  1. 不能修改被装饰函数的源代码。
  2. 不能修改被装饰函数的调用方式。

我们现在有个需求:写一个计时器来统计每个函数执行的时间长度,满足上面的2个原则。

  • 实现一:
import time

def timer(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print("The function run time is %s" % (stop_time-start_time))
    return func

def f1():
    print("This is function F1")
    time.sleep(1)
    
timer(f1)

上述方法虽然可以实现需求,但是它却改变了原函数f1的调用方式,所以不满足第2个原则。

  • 我们下面使用装饰器来实现:
import time

def timer(func):
    def deco():
        start_time = time.time()
        func()
        stop_time = time.time()
        print("The func run time is %s" % (stop_time-start_time))
    return deco

@timer
def f1():
    print("This is function F1")
    time.sleep(1)

f1()

装饰器使用“@+函数名”的语法,当代码运行到@timer的时候,会把下面被装饰的函数f1做为自己的参数,相当于:func = f1,当f1()执行时,实际上执行的是deco()。

  • 当被装饰的函数有参数时我们怎么实现呢?
  1. 参数固定时:
def login(func):
    def deco(user):
        print("[装饰器]正在验证登录:")
        func(user)
    return deco

@login
def wel(user):
    print("Welcome %s to login the page!" % user)

wel("huyd")

2.参数不固定时:

def login(func):
    def deco(*args,**kwargs):
        print("[装饰器]正在验证登录:")
        func(*args,**kwargs)
    return deco

@login
def wel(*args,**kwargs):
    print("Welcome {} to login the page!".format(*args,**kwargs))

wel("huyd")
  • 当被装饰的函数有返回值时,又该怎么实现呢?
def login(func):
    def deco(*args,**kwargs):
        print("[装饰器]正在验证登录:")
        res = func(*args,**kwargs)
        return res          # 此处应该将被装饰函数的返回值return
    return deco

@login
def wel(*args,**kwargs):
    print("Welcome {} to login the page!".format(*args,**kwargs))
    return "sucessful"      # 被装饰的函数有返回值

wel = wel("huyd")
print(wel)
  • 装饰器也可以有自己的参数
def deco_fun1():
    print("装饰器功能1")

def deco_fun2():
    print("装饰器功能2")

def deco(deco_fun):        # 第1层传入装饰器参数(这里只传入了1个参数,也可传入多个)
    def outer(main_fun):    # 第2层传入被装饰的函数名
        def inner():         # 第3层传入被装饰函数的参数
            deco_fun()
            main_fun()
        return inner
    return outer

@deco(deco_fun1)         # 这样就使用了装饰器deco功能1
def index():
    print("我是主程序")

index()    

需求:使用装饰器写一个简单的用户认证功能,当登录index页面时使用本地验证用户名,登录home页面时使用LDAP验证。

user,passwd = 'huyd','123'

def auth(auth_type):     # 判断装饰器的参数
    def outer_wrapper(func):
        def wrapper(*args,**kwargs):
            if auth_type == "local":
                username = input("Username:").strip()
                password = input("Password:").strip()
                if username == user and password == passwd:
                    print("\033[32;1mLogin successful!\033[0m")
                    res = func(*args,**kwargs)
                    return res
                else:
                    print("\033[31;1mInvalid username or password!\033[0m")
            elif auth_type == "ldap":
                print("Home page must be LDAP type Login!")
        return wrapper
    return outer_wrapper



@auth(auth_type="local")
def index():
    print("Welcome to index page!")
    return "Index"

@auth(auth_type="ldap")
def home():
    print("Welcome to home page!")
    return "Home"

# index()    # 进入index页面时使用本地验证登录
home()       # 进入home页面时使用LDAP验证登录

二、生成器(generator)& 迭代器(iterator)

  • 迭代器是访问集合中元素的一种方式,迭代器 object从集合中的第一个元素开始访问,知道所有的元素被访问完成.
  • 所以迭代器的特点是:只能往前,不能后退
  • 迭代器的优点:不需要提前准备整个迭代器中的所有元素,仅仅迭代到某个元素时才计算该元素,而之前或者之后,元素可以不存在或者销毁.因为这个特点,迭代器特别适合遍历文件比较大或者无限的集合.
  • 总结下迭代器 iter()的特点吧:
  1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
  2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
  3. 访问到一半时不能往回退
  4. 便于循环比较大的数据集合,节省内存

**迭代器是用__next__()来取值的,来看个例子吧:**

gen = iter([1,2,3])

# 取值方法一:
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())    #再取值就会报错

# 取值方法二:
for i in gen:
    print(i)

能被for直接循环的都是可迭代对象,如列表,字典等。判断一个对象是不是可迭代对象,可以使用isinstance(*, Iterable)来判断。

生成器在被调用的时候返回一个迭代器。生成器有个标志性的语法yield。

当生成器被调用时,yield返回一个值,并记住当前位置,下一次调用时,从yield下一句语句运行返回下一个值。

def catch_mony(amount):
    while amount > 0:
        amount -= 100
        print("又来取钱了!")
        yield "给你100吧,剩余:{}".format(amount)

atm = catch_mony(500)
print(type(atm))
print(atm.__next__())
print(atm.__next__())
print("去看电影!。。。")
print(atm.__next__())

======================================
运行结果:

<class 'generator'>
又来取钱了!
给你100吧,剩余:400
又来取钱了!
给你100吧,剩余:300
去看电影!。。。
又来取钱了!
给你100吧,剩余:200

此外,yield还有实现在单线程模式下实现并发运算的效果。如下例:

import time


def consumer(name):
    print("{}准备吃包子啦!".format(name))
    while True:
        baozi = yield   # yield也可以用于接收值
        print("第{}次的包子来了,被{}吃掉了!".format(baozi, name))


def producer(name):
    c1 = consumer('A')
    c2 = consumer('B')
    c1.__next__()
    c2.__next__()
    print("{}准备开始做包子了!".format(name))
    for i in range(1, 11):
        time.sleep(1)
        print("{}第{}次做了两个包子。".format(name, i))
        c1.send(i)  # 将i的值传给yield
        c2.send(i)  # 将i的值传给yield

producer("老板")

三、Json & pickle 数据序列化

用于序列化的两个模块:

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换
  • Json模块提供了四个功能:dumps、dump、loads、load
  • pickle模块提供了四个功能:dumps、dump、loads、load
import json
data = {'k1':123,'k2':'Hello'}

# json.dumps 将数据通过特殊的形式转换为所有程序语言都认识的字符串
j_str = json.dumps(data)
print(type(j_str),j_str)

# json.loads 将字典形式的字符串转换为字典格式
j_dict = json.loads(j_str)
print(type(j_dict),j_dict)

# json.dump 将数据通过特殊的形式转换为所有程序都认识的字符串,并写入文件
with open('result.json','w') as f:
    json.dump(data,f)

#######################################################################

import pickle
# pickle.dumps 将数据通过特殊的形式转换为只有python语言认识的字符串
p_str = pickle.dumps(data)
print(type(p_str),p_str)

# pickle.dump 将数据通过特殊的形式转换为只有Python语言认识的字符串,并写入文件
with open('result.pk','w') as f:
    pickle.dump(data,f)

转载于:https://www.cnblogs.com/huyuedong/p/5785334.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值