python tips(持續更新中)

python tips

  • 可變對象與不可變對象
    在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
相關文章
相關標籤/搜索