1. is 和 ==區別html
is 判斷是不是一個ID(內存中的數據是不是同一個), == 判斷內容是否一致。python
2.python 常量池包括閉包
1.短整型的-5~256app
2.字符串的數字、大小寫字母隨意組合(待研究)函數
3.字符串的單個符號測試
4.布爾類型的True、Falsespa
5.None命令行
6.空元組tuple線程
7.空不可變集合frozensetcode
3.在同一個做用域內的兩個變量,若是賦值超出常量池的整形、字符串、浮點型,則使用同一個內存。
# 在命令行中 a = 1 b = 1 print(a is b) # True a = 257 b = 257 print(a is b) # False a = 'helloWorld' b = 'helloWorld' print(a is b) # True a = 'hello world' b = 'hello world' print(a is b) # False a = 'hello world';b = 'hello world';print(a is b) # True # 在同一個做用域中,如同一個函數內。 # 以上都是 True # a和b不在同一個函數、類、py文件中
# 結果與在命令行中的結果相同
4.可變對象與不可變對象
不可變對象:該對象所指向的內存中的值不能被改變。也就是說內存中一旦一個值佔據以後,這塊內存中存的數據就不會發生變化了,直到被銷燬後才能夠存其它值。
可變對象:該對象所指向的內存中的值能夠被改變。
不可變對象類型:bool、int、float、str、tuple、frozenset
可變對象類型:list、set、dict
常量池中的數據類型都是不可變對象類型!
5.值傳遞與引用傳遞
1. 不可變對象做爲函數參數,至關於C語言的值傳遞。
2. 可變對象做爲函數參數,至關於C語言的引用傳遞。(因列表是可變數據類型,做爲參數傳遞實則是傳遞對列表的引用,修改更新列表值後依舊引用不變)
# 值傳遞,value_a把本身的值傳遞給函數func_1的變量value_1後, # value_1的值修改了,value_a的值不會變 def func_1(value_1): print(value_1) value_1 = 2 print(value_1) value_a = 1 func_1(value_a) print(value_a) # 引用傳遞,list_a把引用傳遞給函數func_2的變量list_1後, # 修改list_1的值,list_a的值也發生的改變。 # 因此,若是list_a要再給別的函數傳的話,就是func_2修改後的值 def func_2(list_1): list_a[0] = 2 print(list_1) list_a = [1, 2] func_2(list_a) print(list_a) # 引用傳遞,當第一次調用func_3時,因爲沒有入參,默認從內存開闢 # 一塊空間將一個空列表放進去,而後傳給list_2。當list_2修改後 # 空間中的值發生變化。第二次調用func_3的時候,將第一次開闢空間的引用傳給了 # list_2,因此第二次的list_2有兩個hello。若是是3個線程的話,若是每一個線程裏面 # 循環添加100個hello,當線程結束時list_2的值多是100到300個hello。 def func_3(list_2=[]): list_2.append('hello') print(list_2) func_3() func_3()
6.深拷貝與淺拷貝
淺拷貝:內存中的值只有一份,建立一個新的引用,指向這個內存,將新引用傳遞給新對象。
深拷貝:將內存中的值拷貝一份,開闢一個新空間存進去,將新空間的引用傳遞給新對象。
淺拷貝的目的:節約內存。
深拷貝的目的:防止變量a的值修改時,影響變量b的值。
深拷貝是針對對可變對象的,不可變對象不適用,由於不可變量的值不會改變。若是變量a的值是個不可變對象,當變量a修改時他的引用指向了新的內存地址。
import copy a = [1, 2] b = a # 賦值操做是淺拷貝 print('a_id=%s, b_id=%s, b_value=%s' % (id(a), id(b), b)) a[0] = 'a' print('a_id=%s, b_id=%s, b_value=%s' % (id(a), id(b), b)) # 變量a修改時影響了變量b a = [1, 2] b = copy.deepcopy(a) # b=a[:]也是深拷貝 print('a_id=%s, b_id=%s, b_value=%s' % (id(a), id(b), b)) a[0] = 'a' print('a_id=%s, b_id=%s, b_value=%s' % (id(a), id(b), b)) # 當a修改時不會影響b a = 'hello wold' b = copy.deepcopy(a) print('a_id=%s, b_id=%s, b_value=%s' % (id(a), id(b), b)) # 由於a是不可變對象,因此即便深拷貝也不用開闢新空間,因此ab的id相同 a = 'hello agu' print('a_id=%s, b_id=%s, b_value=%s' % (id(a), id(b), b)) # 當a修改後a的引用指向了新的內存空間,因此a的id改變了
7.私有化與property
class Secret(object): __name = 'yoda' # 加上雙下劃線私有化特性 def get_name(self): return self.__name def __secret(self): # 私有化方法 print "can't find" def access(self): return self.__secret() # 訪問器訪問私有方法 A2 = Secret() print A2.__name # 訪問不到特性! 要拋異常 print A2._Secret__name # 仍是能夠從外部訪問特性 A2.__secret() # 訪問不到特性! 要拋異常 A2._Secret__secret()
# 第一種方法使用屬性 class Foo(object): def __init__(self): self.name = 'yoda' self.work = 'master' def get_person(self): return self.name, self.work def set_person(self, value): self.name, self.work = value person = property(get_person, set_person) # 建立一個新屬性person A3 = Foo() print A3.person # 輸出:('yoda', 'master') A3.person = 'skylaer', 'programer' # A3.set_person(('skylaer', 'programer111')) # 入參必須元組 print A3.person # 輸出:('skylaer', 'programer')
# 第二種方法使用屬性 class Foo: def __init__(self): self.name = 'yoda' self.work = 'master' @property def person(self): return self.name, self.work @person.setter # 若是不指定stter屬性,那麼沒法從類的外部對它的值進行設置,這對於只讀特性很是有用 def person(self, value): self.name, self.work = value A3 = Foo() print(A3.person) A3.person = 'skylaer', 'programer' print(A3.person)
8.列表生成式
range(1,100,5) # 第一個參數表示開始位,第二個參數表示結束位(不含),第三個參數表示步長,就是每5個數返回一次。 a = [i for i in range(1,10)] # 列表生成式表示返回i的值,而且返回9次,每次返回的是i的值。 a = [2 for i in range(1,10)] # 這裏表示返回2,而且返回9次,可是每次的值都是2。 a = [i for i in range10 if i%2==0] #表示在生成式內部加入if判斷,當i除以2的餘數等於0的時候將數值返回。 a = [(i,j) for i in range(5) for j in range(5)] #表示將i和j的值以元組爲元素的形式返回,當i循環一次的時候j循環5次,以此類推
9.生成器
def num(): """ 1.生成器關鍵字yield,有yield的關鍵字的代碼塊就是yield的生成器 2.生成器不能夠return 3.執行next時程序運行到yield行等號右邊的時候就會中止, 當在次使用next的時候,將會把一個None賦值給temp,由於b的值已經在上輪循環中輸出。 4.使用num().send()方法會將一個新的值賦值給temp,而後接着執行一個next """ value = 0 for i in range(6): value += 1 print('num: before yield') temp = yield value # print('num: after yield temp=%s' % temp) # next時,今後處開始,而後判斷for有無結束 a = num() # 將生成器賦值給變量a。 print('---- start test ----') rst = next(a) print('---- rst=%s ----\n' % rst) rst = next(a) print('---- rst=%s ----\n' % rst) rst = a.send('666') # send時num生成器會把666賦值給temp,而後接着執行一個next print('---- after send rst=%s----\n' % rst) rst = next(a) print('---- rst=%s ----\n' % rst) i = 1000 for n in a: # 生成器可使用for循環使用,而且不會出錯。 print('call: before send, n=%s' % n) a.send(i) print('call: after send') i += 1
10.迭代器
# for i in '',[],(),{},{:} # 能夠for循環的對象是可迭代對象。 a = (i for i in range(100)) # 列表生成式,把中括號改成小括號就能夠變爲一個列表生成器,是可迭代對象。 from collections import Iterable # 若是想驗證是不是可迭代對象,可使用isinstance()判斷是不是可迭代對象。 isinstance('abc', Iterable) # 判斷語法 a = [1, 2, 3, 4, 5] b = iter(a) # 使用iter()方法能夠將可迭代的對象轉換爲可迭代對象。
11.閉包
def num(num): # 定義函數 def num_in(num_2): # 定義函數 return num + num_2 # 返回兩個參數的和。 return num_in # 返回內部函數的引用。(變量名) a = num(100) # 將參數爲100的函數num接收,並賦值給a,只不過這個返回值是一個函數的引用。等於 a = num_in,注意這裏接收的不光是函數自己,還有已經傳遞的參數。 b = a(100) # 調用函數a,即num_in,並傳遞一個參數100,返回值給b。 print(b)
12.裝飾器
def wraps(func): # 定義了一個閉包 def func_in(): # 閉包內的函數 print('這裏是須要裝飾的內容,就是須要添加的內容') func() # 調用實參函數。 return func_in def test(): # 須要被裝飾修改的函數。 print('無參函數的測試') test = wraps(test) # 裝飾器的原理就是將原有的函數名從新定義爲以原函數爲參數的閉包。 test() # 這裏再次掉用test()的時候,實際上是將會調用閉包內的函數func_in()。因此將會起到裝飾修改的做用,最後會再次調用原函數test()。 @wraps # 裝飾器的python寫法,等價於test = function(test),而且無需調用當代碼運行道這裏,Python會自動運行。 def test(): print('無參函數的測試') test() # 這裏再次調用函數時,將會產生修改後的效果。
def wraps(func): # 定義了一個閉包 def func_in(*args, **kwargs): # 閉包內的函數,由於裝飾器運行的實則是閉包內的函數,因此這裏將須要有形參用來接收原函數的參數。 print('這裏是須要裝飾的內容,就是須要添加的內容: %s' % str(args)) a, b = args a += 10 b += 10 func(a, b) # 調用實參函數,並傳入一致的實參。 return func_in @wraps # 裝飾器的python寫法,等價於test = function(test) . def test(a, b): print('a+b=%s' % (a+b)) test(1, 1) # 這裏再次掉用test()的時候,實際上是將會調用閉包內的函數func_in()。因此將會起到裝飾修改的做用,最後會再次調用原函數test()。
def wraps(func): # 定義了一個閉包 def func_in(*args, **kwargs): # 由於裝飾器運行的實則是閉包內的函數,因此這裏將須要有形參用來接收原函數的參數。 print('這裏是須要裝飾的內容,就是須要添加的內容') num = func(*args, **kwargs) # 調用實參函數,並傳入一致的實參,而且用變量來接收原函數的返回值, return num # 將接受到的返回值再次返回到新的test()函數中。 return func_in @wraps def test(a, b): # 定義一個函數 return a + b # 返回實參的和 print(test(1, 1))
def outer(number): def wraps(func): # 定義了一個閉包 def func_in(a, b): # 閉包內的函數 a += number b += number num = func(a, b) # 調用實參函數,並傳入一致的實參,而且用變量來接收原函數的返回值, return num # 將接受到的返回值再次返回到新的test()函數中。 return func_in return wraps @outer(100) # 這裏會先運行函數wraps,傳入參數,以後會再次運行閉包函數進行裝飾。 def test(a, b):return a + b print(test(1, 1))
class Test(object): # 定義一個類 def __init__(self, func): self.__func = func def __call__(self): # 定義call方法,當直接調用類的時候,運行這裏。 print('這裏是裝飾的功能') self.__func() @Test # 類裝飾器等於test = Test(test),將函數test看成參數傳入類中的init方法,並將函數名賦值給私有屬性__func,當函數test被調用的時候,實際上是運行Test類中的call方法. def test(): print('被裝飾的函數') test() # 這裏調用的不在是函數test,而是實例對象test的call方法,會先進行裝飾,而後再調用私有屬性__func(),__func 其實就是被裝飾的函數test。
def outer(clss): # 類裝飾器 class Inner(object): def __init__(self): print('inner init') self.clss = clss() def __getattr__(self, attr): return getattr(self.clss, attr) return Inner @outer # Zoo = outer(Zoo) class Zoo(object): def __init__(self): pass def say(self): print('hello world!') zoo = Zoo() print(zoo.__class__) zoo.say()
13. 動態添加屬性和方法
class Person(object): # 建立一個類 def __init__(self, name): # 定義初始化信息。 self.name = name li = Person('李') # 實例化Person('李'),給變量li li.age = 20 # 再程序沒有中止下,將實例屬性age傳入。動態語言的特色。 Person.age = None # 這裏使用類名來建立一個屬性age給類,默認值是None。Python支持的動態屬性添加。 def eat(self): # 定義一個方法,不過這個方法再類以外。 print('%s正在吃東西。。' % self.name) import types # 動態添加方法須要使用tpyes模塊。 li.eat = types.MethodType(eat, li) # 使用types.MethodType,將函數名和實例對象傳入,進行方法綁定。而且將結果返回給li.eat變量。實則是使用一個和li.eat方法同樣的變量名用來調用。 li.eat() # 調用外部方法eat()方法。 @staticmethod # 定義靜態方法。 def test(): # 定義靜態方法,靜態方法能夠不用self參數。 print('這是一個靜態方法。') Person.test = test # 使用類名.方法名 = test的形式來方便記憶和使用,Person.test其實只是一個變量名,沒有特殊的含義。 Person.test() # 調用test方法。 @classmethod # 類方法 def test(cls): print('這是一個類方法。') Person.test = test # 定義一個類屬性等於方法名。 Person.test() # 調用方法。 class test(object): # 定義一個類。 __slots__ = ('name', 'age') # 使用slots來將屬性固定,不能進行動態添加修改。
14.元類
# 元類是隻使用type建立的類,使用type會有3個參數,第一個是類名,第二個小括號內是父類名,須要使用元組。 # 第三個字典中是類屬性,使用type可以快速的動態建立一個類。 Test = type('Test', (object,), {'num': 0}) class Test(object): # 建立一個類,等價於上邊 num = 0 def eat(self): # 定義一個函數,self做爲第一個參數。 print ('%s正在吃飯。。' % self.name) # 使用type建立一個類,可是有兩個屬性,一個是eat,一個是name,可是eat的值是函數eat的引用。 Person = type('Person', (object,), {'eat': eat, 'name': None})
15.內建屬性
__init__ #構造初始化函數,__new__以後運行 __new__ #建立實例所需的屬性 __class__ #實例所在的類,實例.__class__ __str__ #實例的字符串表示,可讀性高 __repr__ #實例的字符串表示,準確性高 __del__ #刪除實例引用 __dict__ #實力自定義屬性,vars(實例.__dict__) __doc__ #類文檔,help(類或者實例) __bases__ #當前類的全部父類 __getattribute__ #屬性訪問攔截器。
16.內建方法
range(start,stop,[,step]) #生成器 map(function, iterable, ...) # map() 會根據提供的函數對指定序列作映射。 filter(function, iterable) #filter() 函數用於過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。 reduce(function, iterable[, initializer]) #reduce() 函數會對參數序列中元素進行累積。 sorted(iterable[, cmp[, key[, reverse]]]) #sorted() 函數對全部可迭代的對象進行排序操做。sort 與 sorted 區別: sort 是應用在 list 上的方法,sorted 能夠對全部可迭代的對象進行排序操做。 list 的 sort 方法返回的是對已經存在的列表進行操做,而內建函數 sorted 方法返回的是一個新的 list,而不是在原來的基礎上進行的操做。