python核心编程

来源:互联网 发布:mysql进程意外终止 编辑:程序博客网 时间:2024/06/03 22:04
元类
    1 类也是对象
        在大多数编程语言中,类就是对象的蓝图,在python中仍然成立,但在Python中类也是对象
class ObjectCreator(object):…       pass
    

将在内存中创建一个对象,名字就是ObjectCreator。这个对象(类对象ObjectCreator)拥有创建对象(实例对象)的能力。但是,它的本质仍然是一个对象,于是乎你可以对它做如下的操作:

  1. 你可以将它赋值给一个变量
  2. 你可以拷贝它
  3. 你可以为它增加属性
  4. 你可以将它作为函数参数进行

动态语言
    在运行时动态绑定属性
生成器
    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。
    在Python中,这种一边循环一边计算的机制,称为生成器:generator
创建生成器:
    要创建一个生成器,有很多种方法。第一种方法很简单,只要把一个列表生成式的 [ ] 改成 ( )
#普通列表In [15]: L = [ x*2 for x in range(5)]In [16]: LOut[16]: [0, 2, 4, 6, 8]

生成器创建

In [17]: G = ( x*2 for x in range(5))

In [18]: G
Out[18]: <generator object <genexpr> at 0x7f626c132db0>
#获取数值
In [19]: next(G)
Out[19]: 0

In [20]: next(G)
Out[20]: 2

In [21]: next(G)
Out[21]: 4

In [22]: next(G)
Out[22]: 6

In [23]: next(G)
Out[23]: 8

In [24]: next(G)

StopIteration Traceback (most recent call last)
<ipython-input-24-380e167d6934> in <module>()
—-> 1 next(G)

StopIteration:

In [25]:
In [26]: G = ( x*2 for x in range(5))

In [27]: for x in G:
….: print(x)
….:
0
2
4
6
8

生成器的创建2

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的 for 循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, …


In [28]: def fib(times): 
....: n = 0
....: a,b = 0,1
....: while n<times:
....: print(b)
....: a,b = b,a+b
....: n+=1
....: return 'done'
....:

In [29]: fib(5)
1
1
2
3
5
Out[29]: 'done'

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:


In [30]: def fib(times): 
….: n = 0
….: a,b = 0,1
….: while n<times:
….: yield b
….: a,b = b,a+b
….: n+=1
….: return ‘done’
….:

In [31]: F = fib(5)

In [32]: next(F)
Out[32]: 1

In [33]: next(F)
Out[33]: 1

In [34]: next(F)
Out[34]: 2

In [35]: next(F)
Out[35]: 3

In [36]: next(F)
Out[36]: 5

In [37]: next(F)

StopIteration Traceback (most recent call last)
<ipython-input-37-8c2b02b4361a> in <module>()
—-> 1 next(F)

StopIteration: done


In [38]: for n in fib(5): 
....: print(n)
....:
1
1
2
3
5


迭代器:
    迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

1. 可迭代对象

以直接作用于 for 循环的数据类型有以下几种:

一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;

一类是 generator ,包括生成器和带 yield 的generator function。

这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable 。


闭包:

    

在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包

#定义一个函数 
def test(number):
#在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包def test_in(number_in):    print("in test_in 函数, number_in is %d"%number_in)    return number+number_in#其实这里返回的就是闭包的结果return test_in

给test函数赋值,这个20就是给参数number

ret = test(20)

注意这里的100其实给参数number_in

print(ret(100))

注意这里的200其实给参数number_in

print(ret(200))

内部函数对外部函数作用域非全局变量的引用 则称内部函数为闭包
    闭包的实践
#创建直线方程y = kx+b的例子  
def line_conf(a,b):
def line(x):
nonlocal a
nonlocal b
return a*x+b
return line

line1 = line_conf(1,1)
line2 = line_conf(2,3)

print (line1(2))
print(line2(2))


装饰器
    
#### 第一波 #### 
def foo():
print(‘foo’)

foo #表示是函数
foo() #表示执行foo函数

第二波

def foo():
print(‘foo’)

foo = lambda x: x + 1

foo() # 执行下面的lambda表达式,而不再是原来的foo函数,因为foo这个名字被重新指向了另外一个匿名函数


需求
初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。业务部门使用基础功能时,只需调用基础平台提供的功能即可。如下:

############### 基础平台提供的功能如下 ###############

def f1():
print(‘f1’)

def f2():
print(‘f2’)

def f3():
print(‘f3’)

def f4():
print(‘f4’)

######### 业务部门A 调用基础平台提供的功能

f1()
f2()
f3()
f4()

######### 业务部门B 调用基础平台提供的功能

f1()
f2()
f3()
f4()

目前公司有条不紊的进行着,但是,以前基础平台的开发人员在写代码时候没有关注验证相关的问题,即:基础平台的提供的功能可以被任何人使用。现在需要对基础平台的所有功能进行重构,为平台提供的所有功能添加验证机制,即:执行功能前,先进行验证。

写代码要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:

  • 封闭:已实现的功能代码块
  • 开放:对扩展开发
如果将开放封闭原则应用在上述需求中,那么就不允许在函数 f1 、f2、f3、f4的内部进行修改代码,
def w1(func): 
def inner():
# 验证1
# 验证2
# 验证3
func()
return inner

@w1
def f1():
print('f1')
@w1
def f2():
print('f2')
@w1
def f3():
print('f3')
@w1
def f4():
print('f4')


python解释器就会从上到下解释代码,步骤如下:

  1. def w1(func): ==>将w1函数加载到内存
  2. @w1
没错, 从表面上看解释器仅仅会解释这两句代码,因为函数在 没有被调用之前其内部代码不会被执行

从表面上看解释器着实会执行这两句,但是 @w1 这一句代码里却有大文章, @函数名 是python的一种语法糖

上例@w1内部会执行以下操作:

    执行w1函数 ,并将 @w1 下面的函数作为w1函数的参数,即@w1 等价于 w1(f1) 所以,内部就会去执行:

@w1 
def w1(func):
def inner():
# 验证1
# 验证2
# 验证3
func()
return inner

语法糖

执行过程

def w1(f1):
# 验证1
# 验证2
# 验证3
f1()
return inner


示例:
# -- coding: utf-8 -- 
“””
Created on Thu Aug 10 18:01:24 2017

@author: liaoxianfu
“”“

定义函数,实现包裹数据

def Bold(func):
def wrapped():
return “<b>”+func()+”</b>”
return wrapped

def Itailc(func):
def wrapped():
return “i”+func()+”</i>”
return wrapped

@Bold

def test1():
return “hello world 1”

@Itailc

def test2():
return “Heloord world 2”

@Bold
@Itailc

def test3():
return “Hello world 3”

print(test1())
print(test2())
print(test3())

运行结果:
runfile(‘C:/Users/liaoxianfu/demo1.py’, wdir=’C:/Users/liaoxianfu’) 
<b>hello world 1</b>
iHeloord world 2</i>

runfile(‘C:/Users/liaoxianfu/demo1.py’, wdir=’C:/Users/liaoxianfu’)
<b>hello world 1</b>
iHeloord world 2</i>
<b>iHello world 3</i></b>

装饰器的功能
  1. 引入日志
  2. 函数执行时间统计
  3. 执行函数前预备处理
  4. 执行函数后清理功能
  5. 权限校验等场景
  6. 缓存

1 日志
#无参数的函数

日志

from time import ctime,sleep

def timefun(func):
def wrappedfunc():
print(“%s runned at %s”%(func.name,ctime()))
func()
return wrappedfunc

@timefun

def foo():
print (“runing “)

foo()
sleep(2)
foo()

过程分析 
@timefun
表示语法糖相当于将timefun(foo)传入

foo = timefun(foo)

实际上在16行调用的foo相当于经过timefun(foo)处理后的函数
timefoo(foo)的返回值就是wrappedfunc()的内部函数
即:
foo()函数的调用等价于调用wrappedfunc()函数
内部函数被引用,所以timefun(func)中的func没有被释放,
即func保存的示原来的foo函数

被装饰的函数有参数
#被装饰的函数有参数

日志

from time import ctime,sleep

def timefun(func):
def wrappedfunc(a,b):
print(“%s runned at %s”%(func.name,ctime()))
print(a,b)
func(a,b)
return wrappedfunc

@timefun

def foo(a,b):
print (“runing “+str(a+b))

foo(3,5)
sleep(2)
foo(1,2)

运行结果
foo runned at Thu Aug 10 18:59:37 2017 
3 5
runing 8
foo runned at Thu Aug 10 18:59:39 2017
1 2
runing 3

被装饰的函数有不定的参数

from time import ctime,sleep

def timefun(func):
def wrappedfunc(*args,**kwargs):
print(“%s runned at %s”%(func.name,ctime()))

    func(*args,**kwargs)return wrappedfunc

@timefun

def foo(a,b):
print (“runing “+str(a+b))

@timefun
def foo1(a,b,c):
print (“runing “+str(a+b+c))

foo(3,5)
sleep(2)
foo1(1,2,3)

装饰器的return以及外部参数
#被装饰的函数有参数

日志

from time import ctime,sleep

def timeargs(pre=”helo”):
def time(func):
def wapperd():
print(“func name is %s runing times is %s”%(func.name,ctime()))
#print(func())
return func()
return wapperd
return time

@timeargs(‘123’)

def foo():
return “Helo World”

print(foo())
sleep(2)
print(foo())



作用域

== && is
  • is 是比较两个引用是否指向了同一个对象(引用比较)。
  • == 是比较两个对象是否相等。
例子:
a = [11,22]

b = copy.deepcopy(a)

b is a
Out[24]: False

b == a
Out[25]: True


深拷贝、浅拷贝

1. 浅拷贝

  • 浅拷贝是对于一个对象的顶层拷贝

通俗的理解是:拷贝了引用,并没有拷贝内容

2. 深拷贝

  • 深拷贝是对于一个对象所有层次的拷贝(递归)

3. 拷贝的其他方式

浅拷贝对不可变类型和可变类型的copy不同

















原创粉丝点击