zoukankan      html  css  js  c++  java
  • 九.类的进化(魔法方法、特性和迭代器)

    关键词:

    __init__, __del__, 类的序列化操作,@property,迭代器,生成器,静态方法与类方法,__new__,__call__

    0.Python中单下划线_,双下划线__有特殊意义。

    1.构造函数和析构函数:

    class Test:
        def __init__(self): #构造函数,创造实例默认执行
            pass
        def __del__(self):  #析构函数,程序全部运行完执行
            pass

    2.类的序列和映射协议,让类的实例可以实现类似序列的操作。

    class Test:
        # 构造函数,创造实例默认执行
        def __init__(self):
            self.date={} #这个方法通常要设置字典为数据类型
            print("Default start")
        # 析构函数,程序全部运行完执行
        def __del__(self):
            print("Default end")
        # 让实例可直接设置:A[key]=...
        def __setitem__(self, key, value):
            self.date[key]=value
        # 让实例可直接访问:A[item]
        def __getitem__(self, item):
            return self.date[item]
        # 让实例可直接运行del A[key]
        def __delitem__(self, key):
            del self.date[key]
        # 让实例可直接运行len(A)
        def __len__(self):
            return len(self.date)
    A=Test()
    #默认运行实例中的__setitem__
    A["k1"]="abc"
    A["k2"]="ABC"
    #默认运行实例中的__getitem__
    print(A["k1"],A["k2"]) #abc ABC
    print(A.date) #{'k1': 'abc', 'k2': 'ABC'}
    #默认运行实例中的__len__
    print(len(A)) #2
    #默认运行__delitem__
    del A["k1"]
    print(A.date) #{'k2': 'ABC'}

    3.类中函数property,通过设置property能够实现类中某些函数.

    class C:
        def __init__(self):
            self._x = 123
        def getx(self):
            return self._x
        def setx(self, value):
            self._x = value
        def delx(self):
            del self._x
        x = property(getx, setx, delx, "I'm the 'x' property.")
    c=C()
    print(c.x) #c.x will invoke the getter
    c.x=456 #c.x = value will invoke the setter
    del c.x #del c.x the deleter

    3.5属性方法@property:

    #装饰器写法@property
    class C:
        def __init__(self):
            self._x = 456
        @property #属性化当前函数,getx相当于变成了属性,所以访问不能加括号
        def getx(self):
            return self._x
        @getx.setter #getx属性进行设置
        def getx(self, value):
            self._x = value
        @getx.deleter #getx属性进行设置
        def getx(self):
            del self._x
    c=C()
    print(c.getx) #操作不能加(),因为变成了属性
    c.getx=123456789
    print(c.getx)
    del c.getx
    #print(c.getx)

    4.迭代器,一层层访问数据,不同于列表要把全部数据加载到内存

    it=iter(range(10))    #iter()函数获得一个迭代器
    print("first",it.__next__())
    print("second",it.__next__())
    print("third",it.__next__())
    print(next(it))
    print(next(it))
    class TestIterator:
        def __init__(self):
            self.value=0
        def __next__(self):   #必须要有__iter__方法才可以实现迭代
            self.value+=1
            if self.value>10: raise StopIteration
            return self.value
        def __iter__(self):   #__iter__方法让类成为迭代器,包含__next__方法
            return self          #可以不用设置其他参数
    TI=TestIterator()
    print(list(TI))

    5.生成器,包含yield语句的函数都被称为生成器

    • 生成器不是使用return返回一个值,而是可以生产多个值,每次一个。每次使用yield生成一个值后,函数都将冻结,等待下次调用。
    • 应用如下:
      datelist=[[1,2,3],[4,5],[6]]
      def generator(date):
          for i in date:
              for j in i:
                  yield j 
      #generator(datelist)生成器是以迭代的形式推进数据,而不是数据全部处理好一个一个调用。大数据时能省内存
      for ii in generator(datelist):
          print(ii, generator(datelist))

     6.静态方法、类方法:@staticmethod和@classmethod的作用于区别

    • method或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。这有利于组织代码。
    • @staticmethod和@classmethod都可以直接类名.方法名()来调用,区别:
      • @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
      • @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
      • 如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
      • 而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码
    class A(object):
        bar = 1
        def foo(self):
            print('foo')
        @staticmethod
        # 这里的self不是实例中的self,仅仅是个参数,如果没有@staticmethod,self表示实例
        def static_foo(self):
            print('static_foo')
            print(A.bar)
        @classmethod
        # 这里必须要有cls,表示当前的类
        def class_foo(cls):
            print('class_foo')
            print(cls.bar)
            A().foo()
    A.static_foo(123)  #static_foo , 1
    A.class_foo()  #class_foo, 1, foo
    class Dog(object):
        def __init__(self,name):
            self.name = name
        @staticmethod #实际上跟类没什么关系了
        def eat(self):
            print("%s is eating %s" %(self.name,'dd'))
    d = Dog("ChenRonghua")
    d.eat(d) #实例下调用,要把实例本身d传进去,但是这样影响直接调用
    
    class Dog(object):
        name = "huazai"
        def __init__(self,name):
            self.name = name
        @classmethod
        def eat(cls,self):
            print("%s is eating %s" %(cls.name,'dd'),self.name)
        def talk(self):
            print("%s is talking"% self.name)
    #Dog.eat()
    d=Dog("ChenRongHua")
    d.eat(d) #类方法也可以传递实例变量,但是这样影响直接调用

     7.__new__,__init__,__call__方法

    # __new__() 表示类实例化过程中,是否要使用该类下 __init__() 方法,__new__() 在 __init__() 之前执行
    # __new__()是针对当前类的,与__init__()相同,不是针对继承类和父类的
    # __call__()是实例化后,实例加()执行
    # 执行顺序__new__() --> __init__() --> __call__()
    class Stranger(object):
        pass
    class Foo(object):
        def __init__(self, *args, **kwargs):
            print("Foo:__init__")
        #new在init之前,所以并没有实例化的参数self
        def __new__(cls, *args, **kwargs):
            print("Foo:__new__")
            # return object.__new__(Stranger) #如果是这句,指向不是本类,而是其他类,则不执行__init__
            return object.__new__(cls) #这句不写也是不执行__init__
    foo=Foo() #Foo:__new__ , Foo:__init__
    
    class Goo(Foo):
        def __init__(self, *args, **kwargs):
            super().__init__()
            print("Goo:__init__")
        #子类不写new,会自动调用父类的new
        def __new__(cls, *args, **kwargs):
            print("Goo:__new__")
            return object.__new__(cls) #通常写法,写此句显然不会执行父类的new
            #return Foo.__new__(cls) #通过父类的new传递了当前cls,写此句显然会执行父类的new
        #实例后加()执行
        def __call__(self, *args, **kwargs):
            print("Goo:__call__")
    goo=Goo() #Goo:__new__, Foo:__init__, Goo:__init__
    goo() #Goo:__call__,相当于goo.__call__(),Goo()()
  • 相关阅读:
    sqlserver编程基本语法
    每日一记--技术小细节
    每日一记--jsp
    每日一记--session/servletContext
    每日一记--cookie
    每日一记--HashTable/HashMap/ConcurrentHashMap
    每日一记--Ajax(下)
    每日一记--Axjx
    每日一记--索引/过滤器
    每日一记--酱油日
  • 原文地址:https://www.cnblogs.com/i201102053/p/10626354.html
Copyright © 2011-2022 走看看