四大器

一、迭代器

迭代器:迭代取值的工具 ——(用__iter__生成迭代器对象)

优点:1.不依赖与索引取值

   2.内存中只占一份空间,不会内存溢出,节约空间,运行效率更高(执行一次__next__取值一次,而不是一次全部取值)

缺点:1.不能获取指定的元素

   2.只能依次往后取值

1.迭代协议

class MyIter:
    """num传入 用来指定迭代次数 """

    def __init__(self, num):
        self.num = num
        self.c = 0
        
    # 迭代
    def __iter__(self):
        return self
    
    # 取值
    def __next__(self):
        self.c += 1
        if self.c <= self.num:
            return "jeff"
        else:
            raise StopIteration

# 循环取值
for i in MyIter(10):
    print(i)

#结果:打印10遍jeff

2.一个简单的迭代器:

k = [1, 2, 3]
# 生成迭代器对象
k1 = k.__iter__()
#迭代器取值,调用__next__()
print(k1.__next__())
print(k1.__next__())
print(k1.__next__())

img

3.迭代异常处理(迭代完了,没有了,try)

k = [1,2,3]
k1 = k.__iter__()while True:
    try:
        print(k1.__next__())
    except StopIteration:
        print("没有了")
        break

img

二、生成器

优点:节约内存,不会内存溢出

生成器:使用yield自定义的迭代器叫生成器

yield:

​ 1.后面不跟值,默认返回None,可以返回多个值

​ 2.帮你将函数的运行状态暂停住

​ 3.可以返回值,多个也可以

yield与return的区别:

​ 1.yield配合迭代器使用__next__一个一个取值,return一次性全取

​ 2.yield可以返回多次值,return返回一次立即结束函数

​ 3.yield可以接受外部传入的值

def func():
    print("first")
    yield 1, 2, 3  # 函数内如果有yield,执行函数时不会执行函数代码

k = func()  # 将函数转化为迭代器
k2 = k.__next__()  # 取值
print(k2)

img

要一次,取一次值

def func():
    print('第一次')
    yield 1, 2, 3
    print('第二次')
    yield 2
    print('第三次')
    yield 3
    print('第四次')
    yield
    yield
k = func()  # 转化为迭代器
# k1 = k.__iter__()  # 这里不用生成迭代对象,函数自身可被迭代
print(k.__next__())
print(k.__next__())
print(k.__next__())
print(k.__next__())

img

三、装饰器

定义:不改变函数的源代码、调用方式,添加新的功能

1.无参模板(二层)

from functools import wraps   #  语法糖


def outter(func):   # 固定搭配
    @wraps(func)  # 固定搭配   语法糖
    def inner(*args, **kwargs):   # 固定搭配
        
        # 装饰前做的事
        return func(*args, **kwargs)  # 固定搭配
        # 装饰后做的事
    
    return inner  # 固定搭配

例子:给lookup添加登录认证的功能



user_info = {
    'user':None
}

def login():

    user = input('请输入用户名>>>:')
    passwd = input('请输入密码>>>:')
    passwd_d = input('请再次输入密码>>>:')
    if passwd == passwd_d:
        user_info['user'] = user
        print('登录成功')
    else:
        print('登录失败')


def register():

    user = input('请输入用户名>>>:')
    passwd = input('请输入密码>>>:')
    passwd_d = input('请再次输入密码>>>:')
    if passwd == passwd_d:
        with open(r'user', 'w')as f:
            f.write(user)
            f.write(passwd)
    else:
        print('重新输入')

# 装饰器
def outter(func):

    def inner(*args, **kwargs):
        if user_info['user']:
            print('hello')
            return func(*args, **kwargs)
        else:
            print('请先登录')
            login()  # 添加login的功能
    return inner


@outter
def lookup():
    with open(r'user','r')as f:
        print(f.read())



def run():
    while True:
        print('''
请选择你的功能>>>:
1.注册
2.登录
3.查看信息''')
        choice = input('>>>:')
        if not choice.isdigit():
            print('请输入数字')
            continue

        msg = {'1': register,
               '2': login,
               '3': lookup}
        msg[choice]()

run()

2.有参模板(三层)

# 有参模板
from functools import wraps

def wrappers(params1,params2,params3):
    def outter(func):
        @wraps(func)
        def inner(*args, **kwargs):
            
            # 装饰前做的事
                return func(*args, **kwargs)
            # 装饰后做的事
            
        return inner
    return outter

四、内置装饰器(绑定方法)

1.@property内置装饰器

夺命三问:
    1.什么是property?
        是一个python内置的装饰器,可以装饰在"类内部的方法"上。
        可以将该方法调用方式由 ----> 对象.方法() ---> 对象.方法

    2.为什么用property?
        PS: 在某些场景下,调用的方法只是用来获取计算后的某个值。
        PS: 必须通过 对象.方法() 方式调用,让该方法看起来像执行函数。

        让名词的方法,调用时更为合理。
        目的是为了,迷惑调用者,调用的方法误以为是 属性。

装饰器:为了调用方式一致,方便使用者
@property首先创建一个age对象,所以@setter、@deleter要加函数名
:这里的age是装饰方法的名称

@property(获取私有) :把一个方法伪装成普通属性,通常函数名和属性名保持一致(方便使用者调用)
@函数名.setter(修改私有):函数名和属性名保持一致
@函数名.deleter(控制删除):

class A:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    @property   # 获取属性时,触发下面
    # 获取伪装成普通属性,通常函数名伪装成属性名
    def age(self):
        return self.__age

    @age.setter  # 修改属性时,触发下面
    def age(self, new_age):
        self.__age = new_age
        print('修改成功')

    @age.deleter  # 删除属性时,触发下面
    def age(self):
        del self.__age
        print('删除成功,已经没有了')
# 查看
jeff = A('jeff', 50)
print(jeff.age)  #  50

# 修改
jeff.age = '100'
print(jeff.age)  # 修改成功   100

# 删除
del jeff.age
print(jeff.age)  # 报错,删除成功,已经没有了

绑定方法

classmethod:
    是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。

staticmethod:
    翻译: 静态方法
    是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “非绑定方法”。

- 对象的绑定方法:
    - 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。

- 类的绑定方法:
    - 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。

- 非绑定方法:
    - 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。

1.对象绑定方法

没有被任何装饰器装饰的方法,为对象量身定制

对象.方法(),自动将对象单座第一个参数传入self

class OldboyStudent:
    school = 'oldboy'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.sex = gender

    def choose_course(self):
        print(f'{self.name} choosing course')

    def func(self):
        print('from func')
      
stu1 = OldboyStudent('nick', 18, 'male')
stu2 = OldboyStudent('sean', 17, 'male')
stu3 = OldboyStudent('tank', 19, 'female')

print(stu1.name)   # nick
print(stu1.school)   # oldboy

2.类的绑定方法@classmethod

classmethod:
    是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。

例子:

class Dog():
    def eat(self):
        print('狗狗吃饭饭。。。')

class Pig():
    @classmethod  # 将此方法对象绑定
    def eat(self):
        print('猪猪看电视。。。')

# 对象绑定方法,需要实例化出一个对象
keji = Dog()
keji.eat()

# 类绑定方法,不需要对象,直接通过类
zhu = Pig.eat()

例子2:进阶高级

class DB:
    __data = 'jeff is very handsome!!!'
    def __init__(self, user, pwd, role):
        self.user = user
        self.pwd = pwd
        self.role = role
        
    # 查看数据方法
    @classmethod  # 类绑定
    def check_db(cls, user, pwd, role):  # cls --》指的是类
        # 在类方法内部调用类产生一个实例 ---》 对象
        obj = cls(user, pwd, role)    # 再类的内部实例化出一个对象,供内部使用

        # 1.查看数据前,必须要通过校验
        if obj.user == 'tank' and obj.pwd == '123' and obj.role == 'admin':
            print('检验通过..')
            print(cls.__data)
            return cls.__data
        
# 类绑定方法了
DB.check_db('tank', '123', 'admin')
#  结果:
检验通过..
jeff is very handsome!!!

3.非绑定方法@staticmethod

非绑定方法:
    - 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。
1.不用非绑定方法,打印的是func函数的地址
class Foo:
    def func(res):
        print(res)
obj = Foo()
obj.func()
#  <__main__.Foo object at 0x000001FF9F5D82E8>

2.对象调用非绑定方法
class Foo:
    @staticmethod
    def func(res):
        print(res)
# 产生了obj对象
obj = Foo()
obj.func(123)  # 123

3.类直接调用非绑定方法
class Foo:
    @staticmethod
    def func(res):
        print(res)
Foo.func(1234)
#  1234
posted @ 2019-08-13 14:39  Jeff的技术栈  阅读(514)  评论(0编辑  收藏  举报
回顶部