python3中的描述器 生成器 迭代器 序列器 装饰器

python中的五种语法机制

描述器,生成器,迭代器,序列器,装饰器

描述器

  • 描述符协议:python描述符是一个“绑定行为”的对象属性,在描述符协议中,它可以通过方法重写属性的访问。这些方法有 __get__(), __set__(), 和__delete__()。如果这些方法中的任何一个被定义在一个对象中,这个对象就是一个描述符。
  • __dict__属性:字典类型,存放本对象的属性。

    • vars()函数可以打印出某一个对象的属性,当然,类名也可以作为参数
    • 对象属性的访问顺序
    1.实例属性 obj.__dict__['attr_name']
    2.类属性 type(obj).__dict__['attr_name']
    3.如果2中返回了一个描述器,实例则用 type(obj).__dict__['x'].__get__(obj, type(obj))
    4.如果是用class.x,类则用 type(class).__dict__['x'].__get__(None, type(class)
  • get函数参数

    def __get__(self, instance, owner):
        return self.name
  • set函数参数

    def __set__(self, instance, value):
        self.name = value

生成器(网址

  • yield关键字用于构造一个生成器,生成器是一个函数
  • yield 的作用就是把一个函数变成一个 生成器,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 生成器,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield
  • yield的主要效果是使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。
  • 应用举例

    • scrapy中用于返回json字符串

      yield {
          'text': quote.css('span.text::text').extract_first(),
          'author': quote.css('small.author::text').extract_first(),
          'tags': quote.css('div.tags a.tag::text').extract(),
      }
    • scrapy中用于翻页

      if next_page is not None:
          yield scrapy.Request(next_page, callback=self.parse)

迭代器

  • 迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合
  • 特点
    • 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
    • 不能随机访问集合中的某个值 ,只能从头到尾依次访问
    • 访问到一半时不能往回退
    • 便于循环比较大的数据集合,节省内存
  • 生成 实现了__iter__函数和next函数的对象就是迭代器
  • 和序列器的区别是,for . in ..语句中可以直接用在in的后面,而不用像序列器的例子中用range来限定范围
  • 例子

    >>> a= iter([1,2,3,4,5])
    >>> a
    <list_iterator object at 0x0044ADF0>
    
    >>> a.__next__()
    1
    >>> a.__next__()
    2
    >>> a.__next__()
    3

序列器

  • 序列器的叫法是我自己这么称呼的,因为已经有了迭代器,生成器,装饰器,描述器这么多器,而__getitem__函数和__len__ ,__setitem__ ,__delitem__这四个函数的作用也是让类具有python中类似list,tuple,dict等已经“序列化”的某一些特征,所以称呼这种机制为序列器也未尝不可
  • 目标是为让binner可以有长度(len函数有效),可以按list方法取值(binner[i])

    for i in range(0, len(binner)):
        print(i, binner[i])
  • 要求
    • 重写__len__函数可以使len()有效果
    • 重写__getitem__函数可以用index寻值
    • 重写__setitem__函数可以用index设值
    • 重写__delitem__函数可以使del 命令有效

装饰器

装饰器是在已有的函数基础上再添加点东西,也就是说把已有的函数作为内置函数执行。

  • @classmethod 函数第一个参数不再是self,而是cls_obj

    @classmethod means: when this method is called, we pass the class as the first argument instead of the instance of that class (as we normally do with methods). This means you can use the class and its properties inside that method rather than a particular instance.

  • @staticmethod 函数第一个参数不再是self,而是空。意思和其他语言的静态是一致的。

    @staticmethod means: when this method is called, we don’t pass an instance of the class to it (as we normally do with methods). This means you can put a function inside a class but you can’t access the instance of that class (this is useful when your method does not use the instance).

自定义装饰器

基础知识

  • 函数也是对象->可以作为函数返回值
  • 函数也是对象->可以作为函数参数
  • 装饰器中的@符号的意思是func=wrapper(func)

定义普通装饰器

def myDecorator(func): # 函数作为参数
    def wrapper(*args, **kwargs): # 作用是给函数传递参数
        print("something before function run")
        func(*args, **kwargs)
        print("something after function run")
    return wrapper #函数作为返回值

@myDecorator
def myAge():
    print("my age is 25")

定义带参数的装饰器

def myParamDecoratorMaker(arg1,arg2):
    print('arg1='+arg1+ ' arg2='+arg2)
    def myDecorator(func):
        def wrapper(*args, **kwargs):
            print("something before function run")
            func(*args, **kwargs)
            print("something after function run")
        return wrapper
    return myDecorator

@myParamDecoratorMaker('a','b')
def myAge():
    print("my age is 25")

猜你喜欢

转载自blog.csdn.net/u013894427/article/details/79156722