可变对象与不可变对象
在python中,可变对象有数值类型(int,float),字符串(str),元组(tuple),可变对象有列表(list),字典(dict),集合(set)。在赋值操做中 可变对象是复制的对象自己,至关于复制了对象的指针,对赋值后的修改会修改原来的对象 例如:python
In [1]: b = [1,2,3,4] In [2]: _b = b In [3]: id(_b) Out[3]: 4519417736 In [4]: id(b) Out[4]: 4519417736 In [5]: _b.append(6) # 修改_b,b也会跟着一块儿变化,由于_b和b指向的是同一个地址 In [6]: b Out[6]: [1, 2, 3, 4, 6]
能够看出修改了_b的值,也修改了b的值,若是想仅仅修改_b的值,须要使用 _b = copy.copy(b)
而不是简单的_b = b
。
对于不可变对象,对象自己的值是不能修改的,每次对其的操做都会生成一个新的对象,保存新的值。以下:sql
In [1]: a = "sss" In [2]: id(a) Out[2]: 4338243040 In [3]: a += "c" # 不可变对象的赋值并不会使用同一个地址,因此id会发生变化 In [4]: id(a) Out[4]: 4338242704
因此在函数中传入可变对象的时候,要当心,由于可能修改原有的对象。数据库
元编程(metaclass)
在正常业务开发时不多使用,但在一些库中常常遇到,例如Django的ORM,其主要功能是在类初始化(不是实例化)的时候,定义一些行为和操做,代码以下django
import os import numpy import random class MetaClass(type): def __init__(self, *args, **kwargs): print('Meta Init') def __new__(cls, name, base, attr): print('class_name is :' , name) print(base,' is the Base *****') print(cls.v, getattr(cls, 'b', 99 )) print('==========') del cls.v return super(MetaClass, cls).__new__(cls, name, base, attr) class Model(metaclass=MetaClass): # python3中指定metaclass指定方式 __metaclass__ = MetaClass # python2中指定方式 MetaClass.v = 100 MetaClass.b = '-------------' c = 9 def __new__(cls, name, base, attrs): print('Model New---') return super(Model, cls).__new__(cls, name, base, attrs) def __init__(self, *args, **kwargs): self.arg = args self.kwargs = kwargs def __str__(self): return "test Models ----->>>>>>" class Test(metaclass=MetaClass): __metaclass__ = MetaClass MetaClass.v = 888 class Serial(Model): MetaClass.v = 777 class test(Serial): MetaClass.v = 666
在import 或者直接运行的时候,咱们没有作任何类的实例化操做,但仍是会有下面的打印信息,会发现,继承的每一个类都运行了metaclass中的__new__
和__init__
方法编程
class_name is : Model () is the Base ***** 100 ------------- ========== Meta Init class_name is : Test () is the Base ***** 888 ------------- ========== Meta Init class_name is : Serial (<class '__main__.Model'>,) is the Base ***** 777 ------------- ========== Meta Init class_name is : test (<class '__main__.Serial'>,) is the Base ***** 666 ------------- ========== Meta Init
slots
在python中,通常咱们能够自由的给类,实例添加属性,然而有时候咱们并不但愿这样,咱们须要指定的类只能有咱们要求的这些属性,在这种状况下,咱们引入了__slots__
例如:缓存
class R(object): """在这个类中,咱们只能添加prev,next等的属性, 当尝试添加别的的时候,会报AttributeError""" __slots__ = 'prev', 'next', 'key', '__weakref__' class Link(R): “”“__slots__ 不会被继承,因此在这个类中可添加指定以外的属性”“” pass class Node(R): """添加了 __slots__ 以后,父类的 __slots__也会生效,此时, 限制的属性为 value, prev, next 等 """ __slots__ = "value",
Django Queryset 切片
咱们知道Django 的queryset是lazy的,只有当真正使用的时候才会去数据库取数据,而且缓存取出来的数据。
因此对于没有执行的queryset,切片操做以后仍然是queryset,执行sql以后的queryset,切片会变成list。app
In [2]: qs = Order.objects.all() In [3]: qs_1 = qs[10:20] In [4]: type(qs_1) Out[4]: django.db.models.query.QuerySet In [5]: _qs = list(qs) # 会查询数据 In [6]: qs_2 = qs[10:20] In [7]: type(qs_2) Out[7]: list