python核心编程

元类
    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]: L
Out[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不同

发表评论