Pythonic语法笔记
__new__
在类实例化之前执行的,也就是在init之前执行,可以为这个类写操作。接受的参数不是self而是cls。只有在new方法里返回类才会执行init操作,需要返回父类的new。
class A(object):
def __new__(cls,name):
print("cls name:{}".format(name))
return super().__new__(cls)
def __init__(self,name):
print("self name:{}".format(name))
if __name__ == "__main__":
a = A("ok")
'''
cls name:ok
self name:ok
'''
getattr和getattribute
在查找不到属性的时候会调用__getattr__
class A():
def __init__(self,name):
self.info = {
"Name":name
}
def __getattr__(self,item):
return self.info[item]
if __name__ == '__main__':
a = A('aa')
print(a['Name'])
__getattribute__管理的是整个类的属性访问,一般不重写,getattr实际上会在getattribute中被调用,重写了之后可能会导致整个类的崩溃,所以一般不重写。getattribute是无条件调用的,无论是否存在属性,都会被调用。
type
type是用来创建类的类,是元类的一种,所以我们也可以通过type函数来动态创建一个类。
type函数有三个参数,第一个是类名,第二个是基类名,第三个是属性
def say():
print("something")
User = type('user',(),{'name':'xueaoru',"say":say})
user = User()
print(user.name)
user.say()
'''
xueaoru
something
'''
实际使用过程中一般不用type直接创建类,而是使用元类,定义metaclass去创建。
我们知道new方法是可以控制在类实例化的过程,而使用元类可以使这个过程分离,单独创建一个类去管理该类的实例化过程,这样代码分离性比较好,所以称之为metaclass。
class MetaClass(type):
def __new__(cls,*args,**kwargs):
return super().__new__(cls,*args,**kwargs)
class Base(metaclass=MetaClass):
def __init__(self, *args, **kwargs):
return super().__init__(*args, **kwargs)
class User(Base):
def __init__(self, name,*args, **kwargs):
self.name = name
return super().__init__(*args, **kwargs)
def __str__(self):
return "user"
if __name__ == "__main__":
user = User("aoru")
print(user)
先定义了一个MetaClass,继承了type,这里其实和直接是type区别不大,因为直接返回super,也就是让实例化的过程交给父类来做,也就是type,然后定义base类,base类的metaclass是MetaClass,所以用MetaClass来做实例化的过程,User由于继承自base类,所以查找metaclass的时候自己没有,就调用基类的metaclass。
属性描述符
实际上是一个用来描述属性的类,需要定义其get方法或者是set方法,可以用来做类型的检查。
# 属性描述符类
class IntField():
def __set__(self,instance,value):
if not isinstance(value,int):
raise ValueError("int value err")
class User():
age = IntField()
if __name__ == "__main__":
user = User()
user.age = '2'
'''
Traceback (most recent call last):
File "/media/xueaoru/其他/ML/推荐系统入门/my_attr_desc_demo.py", line 9, in <module>
user.age = '2'
File "/media/xueaoru/其他/ML/推荐系统入门/my_attr_desc_demo.py", line 4, in __set__
raise ValueError("int value err")
ValueError: int value err
'''
数据查找过程,先查找类中的数据描述符对象,然后查找对象中的属性,然后查找类中或者基类中的属性,而在类中或者基类中查找的时候属性描述符优先。最后如果查找不到,就会调用类的getattr函数,没有就抛出异常。
迭代器
基于两个语法,next返回下一个迭代对象,__iter__返回被迭代的对象本身。
class Myobject():
def __init__(self,step):
self.step = step
def next(self):
if self.step == 0:
raise StopIteration
self.step-=1
return self.step
def __iter__(self):
return self
则Myobject对象可被迭代。
与生成器的不同
生成器是使用了yield函数的,返回迭代器的函数,只能用于迭代操作。每次遇到yield时,函数会暂停病保存当前所有的运行信息,返回yield值,病在下一次执行next方法时从当前位置继续执行。调用一个生成器函数,返回的是一个迭代器对象。我们用的比较多的生成器是列表生成器,一个简单的生成器的例子:
def fib(n):
a,b,cnt = 1,1,0
while True:
if cnt > n:
return
yield a
a,b,cnt = b,a+b,cnt+1
f = fib(10)
for ff in f:
print(ff)
'''
1
1
2
3
5
8
13
21
34
55
89
'''