-
模塊循環導入問題
-
深拷貝和淺拷貝
-
位運算
-
獲取私有屬性的值
-
property的使用
-
迭代器
-
閉包
-
裝飾器
-
python動態添加屬性以及方法
-
生成器
1.模塊循環導入問題
#vi a.py
from b import b
def a():
print('-----a-----')
b()
a()
#vi b.py
from a import a
def b():
print('-----b-----')
def c():
print('------c-----')
a()
c()
#python3 a.py的結果是:ImportError:cannot import name 'a'
解決辦法:不要互相調用,另外寫個
主模塊去調它們(子模塊)
2.深拷貝與淺拷貝
#淺拷貝
a = [11,22,33]
b = a
id(a) == id(b) #True
#深拷貝
a = [11,22,33]
import copy
c = copy.deepcopy(a)
id(a) == id(b) #False
#copy與deepcopy的區別
copy只拷貝第一層引用;deepcopy是遞歸拷貝全部引用
當copy遇到元組時,會進行淺拷貝(只指向)
3.位運算
& 按位與
| 按位或
^ 按位異或
~ 按位取反
<< 按位左移
>> 按位右移
用途:直接操做二進制,省內存,效率高
按位移:
8>>1 4
8<<1 16
按位與:
全1才1不然0:只有對應的兩個二進制均爲1時,結果位才爲1,不然爲0
按位或:
有1就1 只要對應的二個二進位有一個爲1時,結果位就爲1,不然爲0
按位異或:
不一樣爲1 只要對應的二進位相異(不相同)時,結果爲1,不然爲0
取反:
~9 = -10
4.獲取私有屬性的值:
class Test(object):
def __init__(self):
self.__num = 100
def setNum(self, newNum):
self.__num = newNum #修改私有屬性的值
def getNum(self):
return self.__num #返回私有屬性的值
t = Test()
#print('t.__num')
#t.__num = 200
#print(t.__num)
print(t.getNum())
t.setNum(39)
print(t.getNum())
#私有化的本質是把私有屬性給更名了。如_類名__num
5.property的使用:
class Test(object):
def __init__(self):
self.__num = 100
def setNum(self, newNum):
self.__num = newNum #修改私有屬性的值
def getNum(self):
return self.__num #返回私有屬性的值
num = property(getNum, setNum)
t = Test()
t.num = 200 #至關於t.setNum(9)
print(t.num)
注意點:
t.num 究竟是調用getNum()仍是setNum(),要根據實際的場景來判斷;
若是是給t.num賦值,那麼必定調用setNum();
若是是獲取t.num的值,那麼就必定調用getNum();
property的做用:至關於把方法進行了封裝,開發者在對屬性設置數據的時候更方便了
#使用裝飾器
class Test(object):
def __init__(self):
self.__num = 100
@property
def num(self):
return self.__num
@num.setter
def
num(self, newNum):
self.__num = newNum
t = Test()
t.num = 200
print(t.num)
6.迭代器:
判斷是否爲Itarable類型
from collections import Iterable
a = isinstance('abv', Iterable)
print(a)
#判斷是否爲Iterator類型
from collections import Iterator
a = isinstance('ac', Iterator)
print(a)
使用iter()函數把Iterable變成Iterator
a = isinstance(iter('abc'), Iterator)
print(a)
7.閉包:
#函數裏面套用函數,裏面的函數用到了外面函數的參數,就叫作閉包
def test(number):
def test2(number2):
print('-----%s-----'%number2)
return number+number2
return test2
#返回函數的地址
ret = test(100) #ret已經記住了外部的參數
print(ret(20))
#一個閉包的實際例子
def line_conf(a, b):
def line(x):
return a*x + b
return line
line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5))
print(line2(5))
#函數的最終形式(y=x+!)(y=4x+5)
#1.閉包優化了變量,原來須要類對象完成的工做,閉包也能夠完成
#2.因爲閉包引用了外部函數的局部變量,則外部函數的局部變量沒有及時釋放,消耗內存
#初始設計
def function(a,b,x):
print(a*x+b)
function(1,1,0)
8.裝飾器:
#裝飾器第一個版本
def base(func):
def inner():
print('-----裝飾器-----')
func()
return inner
def a():
print('-----a------')
def b():
print('-----b------')
innerFunc = base(b)
innerFunc()
裝飾器的第二個版本
def base(func):
def inner():
print('-----正在驗證權限-----')
if False:
func()
else:
print('沒有權限')
return inner
@base
def a():
print('-----a------')
@base
def b():
print('-----b------')
b()
#裝飾器的執行順序,快遞(裝的時候是從裏往外裝,拆的時候從外往裏拆)
#coding:utf-8
def w1(func):
print('-----正在裝飾1-----')
def inner():
print('-----正在驗證權限1-----')
func()
return inner
def w2(func):
print('-----正在裝飾2-----')
def inner():
print('-----正在驗證權限2-----')
func()
return inner
@w1
@w2
def f1():
print('-----f1-----')
#有參數
def func(functionName):
print('-----func-----1---')
def func_in(a, b): #若是a,b沒有定義,那麼會致使下面的調用失敗
print('----func_in----1----')
functionName(a, b) #要把a, b看成實參進行傳遞
print('----func----2----')
return func_in
@func
def test(a, b):
print('-----test-a=%d, b=%d-----'%(a, b))
test(11,22)
#不肯定參數
def func(functionName):
print('-----func-----1---')
def func_in(*args, **kwargs): #若是a,b沒有定義,那麼會致使下面的調用失敗
print('----func_in----1----')
functionName(*args, **kwargs) #要把a, b看成實參進行傳遞
print('----func----2----')
return func_in
@func
def test(a, b, c):
print('-----test-a=%d, b=%d-----'%(a, b, c))
@func
def test2(a, b, c, d):
print('-----test-a=%d, b=%d, c=%d, d=%d---'%(a, b, c, d))
test(11,22,33)
test2(22,33,44,55)
#裝飾器對對帶有返回值的函數進行裝飾
#解ret爲None的bug
def func(functionName):
print('-----func-----1---')
def func_in():
print('----func_in----1----')
functionName()
print('----func----2----')
return func_in
@func
def test():
print('-----tes-----')
return 'haha'
ret = test()
print('test return value is %s'%ret)
#由於test()指向了func_in(),而func_in由調用了test(),而return的返回值卻沒有變量來接收,所以只須要找一個變量來接收functionName()的返回值就行了
#通用裝飾器
def func(functionName):
def func_in(*args, **kwargs):
ret = functionName(*args, **kwargs)
return ret
return func_in
@func
def test():
print('-----test1-----')
return 'haha'
@func
def test2():
print('-----test2-----')
@func
def test3(a):
print('----test3----a=%d--'%a)
ret = test()
print('test return value is %s'%ret)
a = test2()
print('test2 return value is %s'%a)
test3(11)
#帶有參數的裝飾器
def func_arg(arg):
def func(functionName):
def func_in():
print('-----記錄日誌--arg=%s---'%arg)
if arg == 'heihei':
functionName()
functionName()
else:
functionName()
return func_in
return func
#1.先執行func_arg('heihei')函數,這個函數return的結果是func這個函數的引用
#2.@func
#3.使用@func對test進行裝飾
#帶有參數的裝飾器,可以起到在運行時,有不一樣的功能
@func_arg('heihei')
def test():
print('-----test-----')
test()
9.動態添加屬性和方法
做用域:
LEGB規則:
找一個變量,先找局部,再找有沒有閉包,再找全局變量,再找內鍵
#爲類動態添加屬性
class mate(object):
def __init__(self, Newname, Newage):
self.name = Newname
self.age = Newage
laowang = mate('老王', 18)
爲變量添加單一屬性
laowang.addr = '北京'
print(laowang.addr)
#爲類添加屬性
mate.addr = '中國'
print(laowang.addr)
#爲類動態添加方法
import types
class mate(object):
def __init__(self, Newname, Newage):
self.name = Newname
self.age = Newage
def eat(self):
print('----eat----')
def run(self):
print('-----run-----')
wang = mate('老王', 18)
wang.run = types.MethodType(run, wang)
wang.run()
#靜態方法添加
@staticmethod
def test():
print('-----static method---')
p.test = test
p.test()
__slots__方法
使用__slots__來限制class實例能添加的屬性,可是僅能對當期的類添加限制,對繼承的子類沒有限制
__slots__ = [‘name’, ‘age’]
10.生成器:
第一種生成器:把列表生成式的[]變爲()
a = [x*2 for x in range(10)]
a = (x*2 for x in range(10))
print(a)
next(a)
建立生成式方法二
def creatNum():
print('-----start-----')
a, b = 0, 1
for i in range(5):
print('-----1-----')
yield b
print('-----2-----')
a, b = b, a+b
print('-----stop-----')
a = creatNum()
for num in a:
print(num)
#send的使用
def test():
i = 0
while i <5:
temp = yield i
print(temp)
i += 1
t = test()
t.__next__()
t.send('haha')
第一次調用send的解決辦法:
1.先用next,在用send
2.send(None),再使用send
#多任務(協程)
def test1():
while True:
print('-----1-----')
yield None
def test2():
while True:
print('-----2-----')
yield None
t1 = test1()
t2 = test2()
while True:
t1.__next__()
t2.__next__()