浅拷贝:
拷贝的是地址引用。可以找到共同的内容
一方修改了,另一方受影响
a = [1,2,3,4]
b = a
print(id(a)) #2540558597256
print(id(b)) #2540558597256
a.append(5)
print(a) #[1, 2, 3, 4, 5]
print(b) #[1, 2, 3, 4, 5]
深拷贝:
b = copy.deepcopy(a)
b得到的内容与a的内容完全一样,地址不一样。
就算a中有对象引用,b中对应的引用的对象依然是内容一样,地址不一样。
递归拷贝
注意:
如果是一个不可变对象(内部存储还是不可变对象),深拷贝的结果 = 浅拷贝,地址一样
copy.copy
b = copy.copy(a)
import copy
a = [1,2,3,4]
#相当于深拷贝
b = copy.copy(a)
print(id(a))
print(id(b))
a.append(5)
print(a)
print(b)
print(''50)
a = (1,2,3,4)
#相当于浅拷贝
b = copy.copy(a)
print(id(a))
print(id(b))
a = [11,22,33]
b = [44,55,66]
c = [a,b]
d = copy.copy(c)
print(id(c))
print(id(d))
print(c)
print(d)
print(''50)
a.append(120)
#c[0].append(120)
print(c)
print(d)
print(''50)
a = [11,22,33]
b = [44,55,66]
c = (a,b)
d = copy.copy(c)
print(id(c))
print(id(d))
print(c)
print(d)
print(''50)
a.append(120)
#c[0].append(120)
print(c)
print(d)
私有的内容,对外不能直接访问。
如果想对外访问,需要提供可以访问的方法,比如这里的getMoney,setMoney
调用的时候比较麻烦。
能不能像操作属性一样呢?
属性名 = property(get,set)
class Money(object):
def __init__(self):
self.__money = 0
def getMoney(self):
return self.__money
def setMoney(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
m = Money()
print(m.getMoney())
m.setMoney(10)
print(m.getMoney())
class Money(object):
def __init__(self):
self.__money = 0
def getMoney(self):
return self.__money
def setMoney(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
money = property(getMoney,setMoney)
m.money = 120 #相当于上面的m.setMoney(120)
print(m.money) #相当于上面的m.getMoney
#或者是
print(Money.money)
class Money(object):
def __init__(self):
self.__money = 0
@property
def money(self):
return self.__money
@money.setter
def money(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
m = Money()
print(m.money)
m.money = 120
print(m.money)
如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个生成器,有很多种方法。第一种方法很简单,只要把一个列表生成式的 [ ] 改成 ( )
#列表生成式
ls = [x for x in range(100)]
print(ls)
#生成器
ge = (x**2 for x in range(1000))
print(ge)
print(type(ge))
i = 0
while i<19:
next(ge)
i+=1
print(next(ge))
总结
生成器保存的是算法,每次调用 next(G) ,就计算出 G 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出 StopIteration 的异常。当然,这种不断调用 next() 实在是太变态了,正确的方法是使用 for 循环,因为生成器也是可迭代对象。所以,我们创建了一个生成器后,基本上永远不会调用 next() ,而是通过 for 循环来迭代它,并且不需要关心 StopIteration 异常。
yield 值
调用函数,得到一个生成器对象。这个函数没有执行
next调用1得到的对象,如果遇到了yield,代码会阻塞,next的返回值就yield后的值
def fib(times):
print('0….')
n = 0
a,b = 0,1
while n<times:
print('1….')
yield b
print('2….')
a,b = b,a+b
n+=1
print('3….')
ge = fib(5)
print(ge)
print(''50)
m = 0
while m<5:
print(next(ge))
m+=1
第一种和第二种,一旦生成器确定,算法不能改变。
这里的例子,定义了变量(temp),可以使用send发送参数,发给这里变量。
根据这个变量的值的不同,可以改变算法的逻辑。
所以,这种写法的作用:在运行过程中,可以改变算法
def gen():
i = 0
while i<1000:
temp = yield i
if temp==True:
#逻辑代码
print('执行A计划')
i+1
else:
#逻辑代码
print('执行B计划')
i+=2
myGenerator = gen()
ret = next(myGenerator)
print(ret)
#1、为当前停止的代码的左侧变量赋值
#2、生成器往下走一个行,返回yield值
ret = myGenerator.send(True)
print(ret)
ret = myGenerator.send(False)
print(ret)
import time
def test1():
while True:
print("--王者荣耀--")
#time.sleep(2)
yield None
def test2():
while True:
print("--music--")
yield None
def main():
t1 = test1()
t2 = test2()
while True:
t1.__next__()
t2.__next__()
main()
总结
生成器的特点:
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
以直接作用于 for 循环的数据类型有以下几种:
这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable 。
isinstance(对象,Iterable)
如果结果为True
只是表示,这些对象以使用for循环迭代遍历,可以使用next
import collections
ge = (x for x in range(10))
print(isinstance(ge,collections.Iterable)) #True
print(isinstance(ge,collections.Iterator)) #True
print(next(ge)) #0
print('************************华丽的分割线************************')
ls = [x for x in range(10)]
print(isinstance(ls,collections.Iterable)) #True
print(isinstance(ls,collections.Iterator)) #False
for i in ls:
print(i) #0-9的数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。
把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:
ls = [33,4,5,6,7,8]
it=iter(ls)
for i in range(len(ls)):
print(next(it)) #33-8的数
总结
def test1():
print("--- in test1 func----")
#调用函数
test1()
#此是ret引用函数
ret = test1
print(id(ret)) #18779264
print(id(test1)) #18779264,地址都一样,说明指向同一个内存地址
#通过引用调用函数
ret() #--- in test1 func----
在函数内部再定义一个函数,并且这个内部函数用到了外部函数的局部变量
那么将这个内部函数以及用到的一些局部变量称之为闭包
def outer(num):
print('outer…')
def inner():
print('num=%s'%num)
return inner
ret = outer(100) #outer…
ret() #num=100
ret() #num=100
def line_conf(a, b):
def line(x):
return a*x + b
return line
line1 = line_conf(2,3)
print(line1(10)) #23
line2 = line_conf(3,4)
print(line2(10)) #34
闭包的优缺点
def outer(func):
print('outer...')
def inner():
print('inner...')
func()
return inner
def save():
print('save...')
ret = outer(save) #outer
ret() #inner... save...
def login(func):
def inner():
name = input('输入用户名:')
pwd = input('输入密码:')
if name=='laowang' and pwd=='123':
func()
else:
print('赶紧去登录。。。。。。')
return inner
@login
def save():
print('save...')
save()
多个装饰器,按照从内往外(从下往上)先后顺序执行
为了方便记忆:可以理解为先写后运行,先写后结束
def makeBold(fn):
print('makeBold…')
def wrapped():
return "--1--" + fn() + "--1--"
return wrapped
def makeItalic(fn):
print('makeItalic…')
def wrapped():
return "--2--" + fn() + "--2--"
return wrapped
@makeBold
@makeItalic
def test():
return "hello world-test"
print(test())
#结果
#makeItalic…
#makeBold…
#--1----2--hello world-test--2----1--
无参数的函数
from time import ctime, sleep
def timefun(func):
def wrappedfunc():
print("%s called at %s"%(func.name, ctime()))
func()
return wrappedfunc
@timefun
def foo():
print("I am foo")
foo() #foo called at Thu Jul 20 16:03:59 2017
#I am foo
sleep(2)
foo()
foo = timefun(foo)
#foo先作为参数赋值给func后,foo接收指向timefun返回的wrappedfunc
foo()
#调用foo(),即等价调用wrappedfunc()
#内部函数wrappedfunc被引用,所以外部函数的func变量(自由变量)并没有释放
#func里保存的是原foo函数对象
被装饰的函数有参数
def timefun(func):
def wrappedfunc(a, b):
print("%s called at %s"%(func.name, ctime()))
print(a, b)
func(a, b)
return wrappedfunc
@timefun
def foo(a, b):
print(a+b)
foo(3,5)
#foo called at Thu Jul 20 16:07:48 2017
#3 5
#8
被装饰的函数有不定长参数
from time import ctime, sleep
def timefun(func):
def wrappedfunc(args, kwargs):
print(args)
print(kwargs)
print("%s called at %s"%(func.name, ctime()))
func(args,kwargs)
return wrappedfunc
@timefun
def foo(a, b, c,num):
print(a+b+c)
print(num)
foo(3,5,7,num=123)
#(3, 5, 7)
#{'num': 123}
#foo called at Thu Jul 20 16:11:06 2017
#15
#123
装饰器中的return
from time import ctime, sleep
def timefun_arg(pre="hello"):
def timefun(func):
def wrappedfunc():
print("%s called at %s %s"%(func.name, ctime(), pre))
return func()
return wrappedfunc
return timefun
@timefun_arg("wangcai")
def foo():
print("I am foo")
@timefun_arg("python")
def too():
print("I am too")
foo()
#foo called at Thu Jul 20 16:23:48 2017 wangcai
#I am foo
print('华丽的分割线')
too()
#too called at Thu Jul 20 16:23:48 2017 python
#I am too
总结:
一般情况下为了让装饰器更通用,可以有return
装饰器带参数,在原有装饰器的基础上,设置外部变量
def haha(x):
def outer(func):
def inner():
if x%2==0:
return func()+'八'
else:
return '八'+func()
return inner
return outer
@haha(1)
def laowang():
return '老王'
print(laowang()) #八老王
类装饰器(扩展,非重点)
装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重写了__call__()方法,那么这个对象就是callable的。
class Test(object):
def init(self, func):
print("---初始化---")
print("func name is %s"%func.name)
self.func = func
def __call(self):
print("---装饰器中的功能---")
self.__func()
#说明:
#1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
#
#2. test函数相当于指向了用Test创建出来的实例对象
#
#3. 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的call方法
#
#4. 为了能够在call方法中调用原来test指向的函数体,所以在init方法中就需要一个实例属性来保存这个函数体的引用
@Test
def test():
print("----test---")
test()
showpy()#如果把这句话注释,重新运行程序,依然会看到"--初始化--"
运行结果如下:
---初始化---
func name is test
---装饰器中的功能---
----test---
动态编程语言是高级程序设计语言的一个类别,在计算机科学领域已被广泛应用。它是一类 在运行时可以改变其结构的语言 :例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。动态语言目前非常具有活力。例如JavaScript便是一个动态语言,除此之外如 PHP 、 Ruby 、 Python 等也都属于动态语言,而 C 、 C++ 等语言则不属于动态语言。----来自维基百科
class mv_hero:
def __init__(self,name,HP,MP):
self.name = name
self.HP = HP
self.MP = MP
#调用,实例化
gtx = mv_hero('cjr',10,10)
print(gtx.name) #cjr
#添加一个实例属性
gtx.XP = 100
print(gtx.XP) #100
#添加一个类属性
mv_hero.xx = 99
#gtx.xx = 111
print(gtx.xx) #99
#定义一个类方法
@classmethod
def atteck(cls):
cls.num = 100
#定义一个静态方法
@staticmethod
def test_hero():
print('--test_hero--')
#给mv_hero类绑定类方法
mv_hero.atteck = atteck
#调用刚才绑定的类方法
mv_hero.atteck()
print(mv_hero.num) #100
#给mv_hero类绑定静态方法
mv_hero.test_hero = test_hero
#调用刚才绑定的静态方法
mv_hero.test_hero() #--test_hero--
import types
#定义一个实例方法
def fly(self, speed):
print("%s在移动, 速度是 %s"%(self.name, speed))
#给mv_hero中的对象绑定实例方法
gtx.fly = types.MethodType(fly, gtx)
#调用刚才的实例方法
gtx.fly(180) #cjr在移动, 速度是 180
现在回到我们的大主题上来,究竟是为什么你会去使用这样一种容易出错且晦涩的特性?好吧,一般来说,你根本就用不上它!
'''
使用type创建类
type的第3个参数
1、字符串 类名
2、元组 父类
3、字典 类属性
'''
'''
class Test:
pass
'''
Test = type('Test',(),{})
print(Test)
Test = type('Test',(),{'name':'老王','age':10})
print(Test.name)
class Fu:
def fu(self):
print('fu...')
Zi = type('Zi',(Fu,),{})
print(Zi.__mro__)
print('***************************************华丽的分割线***************************************')
def haha(self):
print('haha...')
def __init__(self,num):
print('self...')
self.num = num
@classmethod
def hehe(cls):
print('hehe...')
Test = type('Test',(),{'name':'老王','age':10,'haha':haha,'hehe':hehe,'__init__':__init__})
t = Test(110)
t.haha()
Test.hehe()
python创建9个”HelloWorld”对象,让他只占用一个”HelloWorld”所占的内存空间,python中有这样一个机制——intern机制,靠引用计数去维护何时释放。
字符串(含有空格),不可修改,没开启intern机制,不共用对象,引用计数为0,销毁。
总结
python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略
map():map函数会根据提供的函数对指定序列做映射
map(function, sequence[, sequence, …]) -> list
·function:是一个函数
·sequence:是一个或多个序列,取决于function需要几个参数
·返回值是一个列表
参数序列中的每一个元素分别调用function函数
返回包含每次function函数返回值的list。
注意:先转成list才能print
def square(x) : # 计算平方数
… return x ** 2
map(square, [1,2,3,4,5]) # 计算列表和:1+2+3+4+5
[1, 4, 9, 16, 25]
map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]
range():
range(start, stop[, step]) -> list of integers
·start:计数从start开始。默认是从0开始。例如range(5)等价于range(0,5);
·stop:到stop结束,但不包括stop.例如:range(0,5) 是[0, 1, 2, 3, 4]没有5
·step:每次跳跃的间距,默认为1。例如:range(0,5) 等价于range(0, 5, 1)
python2中range返回列表,python3中range返回一个迭代值。如果想得到列表,可通过list函数
filter():filter函数会对指定序列执行过滤操作
filter(function or None, sequence) -> list, tuple, or string
·function:接受一个参数,返回布尔值True或False
·sequence:序列可以是str,tuple,list
·返回值是一个列表
过滤出列表中的所有奇数:
def is_odd(n):
return n % 2 == 1
newlist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(newlist)
输出结果 :
[1, 3, 5, 7, 9]
sorted()
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
sorted(iterable, key=None, reverse=False) --> new sorted list
reverse默认值为False,升序排序
>>>a = [5,7,6,3,4,1,2]
>>> b = sorted(a) # 保留原列表
>>> a
[5, 7, 6, 3, 4, 1, 2]
>>> b
[1, 2, 3, 4, 5, 6, 7]
>>> L=[('b',2),('a',1),('c',3),('d',4)]
>>> sorted(L, cmp=lambda x,y:cmp(x[1],y[1])) # 利用cmp函数
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> sorted(L, key=lambda x:x[1]) # 利用key
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(students, key=lambda s: s[2]) # 按年龄排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(students, key=lambda s: s[2], reverse=True) # 按降序
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
reduce():reduce函数会对参数序列中元素进行累积
reduce(function, sequence[, initial]) -> value
·function:该函数有两个参数
·sequence:序列可以是str,tuple,list
·initial:固定初始值
reduce依次从sequence中取一个元素,
和上一次调用function的结果做参数再次调用function。
第一次调用function时,如果提供initial参数,
会以sequence中的第一个元素和initial作为参数调用function,
否则会以序列sequence中的前两个元素做参数调用function。
注意function函数不能为None。
在Python3里,reduce函数已经被从全局名字空间里移除了,它现在被放置在fucntools模块里用的话要先引入:from functools import reduce
>>>def add(x, y) : # 两数相加
... return x + y
...
>>> reduce(add, [1,2,3,4,5]) # 计算列表和:1+2+3+4+5
15
>>> reduce(lambda x, y: x+y, [1,2,3,4,5]) # 使用 lambda 匿名函数
15
def f(x,y):
print('x=%s,y=%s'%(x,y))
return x+y
#ret = functools.reduce(lambda x, y: x+y, ['a','b','c','d'],'o')
ret = functools.reduce(f, ['a','b','c','d'],'o')
运行结果:
x=o,y=a
x=oa,y=b
x=oab,y=c
x=oabc,y=d
functools 是python2.5被引人的,一些工具函数放在此包里。
知道有这么个东西
标准库
说明
builtins
内建函数默认加载
sys
操作系统借口
functooks
常用的工具
json
编码和解码JSON对象
logging
记录日志、调试
multiprocessing
多进程
threading
多线程
copy
拷贝
time
时间
datetime
日期和时间
calendar
日历
hashlib
加密算法
random
生成随机数
re
字符串正则匹配
socket
标准的BSD Sockets API
shutil
文件和目录管理
glob
基于文件通配符搜索
更多标准库
http://python.usyiyi.cn/translate/python_352/library/index.html
在pycharm里,Ctrl+Alt+L自动排版,排版的时候注意看一看就记住了
pycharm
步骤:
手机扫一扫
移动阅读更方便
你可能感兴趣的文章