Python核心编程
-
模块循环导入问题
-
深拷贝和浅拷贝
-
位运算
-
获取私有属性的值
-
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.动态添加属性和方法
作用域:
什么是命名空间?
名字起作用的范围
globals
locals
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__()