关键词:
__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()()