python的一些知识点小结(1)

关于字典和列表的使用区别

和list比较,dict有以下几个特点:

查找和插入的速度极快,不会随着key的增加而变慢;
需要占用大量的内存,内存浪费多。
而list相反:

查找和插入的时间随着元素的增加而增加;  (数据结构是链表式的和顺序表形式的)
占用空间小,浪费内存很少。
所以,dict是用空间来换取时间的一种方法。

dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。

这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。

要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key

列表生成式

  • 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。
普通生成式
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

加上if判断 做为筛选
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100

后边两个可迭代对象  相当于for循环的嵌套
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

课后习题

输入:
L1 = ['Hello', 'World', 18, 'Apple', None]
输出:
['hello', 'world', 'apple']
测试:
[x.lower() for x in l1 if isinstance(x, str)]

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

生成器的创建方式:

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

调用生成器:
    通过next(g)  来调用生成器, 返回需要的内容  迭代到最后一个元素的时候 会抛出 stopIteration 异常来结束迭代
    >>> next(g)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration

使用for循环来迭代生成器
>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)


使用生成器来完成斐波纳挈数列
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1

for i in fibZ(5):
    print i

生成器函数和普通函数的区别



generator是非常强大的工具,在Python中,可以简单地把列表生成式改成
generator,也可以通过函数实现复杂逻辑的generator。

要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素
,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环
随之结束。

普通函数调用直接返回结果
生成器函数调用返回的是一个生成器的对象

高阶函数的简单分析

一个函数可以接受另外一个函数做为参数, 这种函数就称为高阶函数

def add(x, y, f):
    return f(x) + f(y)

x = -5
y = 6
f = abs
f(x) + f(y) ==> abs(-5) + abs(6) ==> 11
return 11

内建函数

map 和 reduce 函数的使用:
map函数: 接收一个函数 和一个可迭代的对象 iterable (会依次的把后面的可迭代对象的元素作用于前面的函数上) 返回的是另外一个iterator 迭代器, 迭代器是惰性的 可减少内存空间的使用
简单实例:

>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
再看reduce的用法。reduce把一个函数作用在一个序列[x1,x2,...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
>>> from functools import reduce
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])

使用map和reduce 配合 把一个字符串转换成为一个整数

from functools import reduce

def char2num(s):
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]  # 按照键来进行取值

def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))

课后练习

利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。
输入:['adam', 'LISA', 'barT'],
输出:['Adam', 'Lisa', 'Bart']:

def normalize(name):
    return name.lower().title()
L1 = ['adam', 'LISA', 'barT']
L2 = list(map(normalize, L1))
print L2
利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456def str2float(s):
    nums = map(lambda ch: CHAR_TO_FLOAT[ch], s)
    point = 0
    def to_float(f, n):
        nonlocal point
        if n == -1:
            point = 1
            return f
        if point == 0:
            return f * 10 + n
        else:
            point = point * 10
            return f + n / point
    return reduce(to_float, nums, 0.0)

print(str2float('0'))
print(str2float('123.456'))
print(str2float('123.45600'))
print(str2float('0.1234'))
print(str2float('.1234'))
print(str2float('120.0034'))




def demo(m):
"""判断是不是回文数字"""
    n = list(str(m))
    n.reverse()
    print n
    if "".join(n) == str(m):
        return True


filter(demo, list)

sorted 排序的课后习题

按照名称进行排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
sorted(L,key=lambda x:x[0])  会把每个列表中的元素就行遍历 然后传递给 key执行的函数 \


dict.items()  返回的是一个列表 列表中的元素 是一个个的元组

高阶函数 返回函数

函数的嵌套 会形成闭包的概念, 多次调用闭包 之间的结果是不受影响的

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。装饰器就是特殊的高阶函数 加上函数的嵌套来组合成的

但是在使用高阶函数返回函数的时候 需要注意:

闭包

注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。

另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()
在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都返回了。

你可能认为调用f1(),f2()和f3()结果应该是149,但实际结果是:

>>> f1()
9
>>> f2()
9
>>> f3()
9

全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs


    小结

一个函数可以返回一个计算结果,也可以返回一个函数。

返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量

匿名函数中的一点

函数名称的可以使用name 来获取到函数的名称

@functools.wraps(func) 使用 wraps(func) 来装饰使用的内部的函数

完整版的装饰器
import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

sys 模块的使用

sys模块有一个argv变量,用list存储了命令行的所有参数。argv至少有一个元素,因为第一个参数永远是该.py文件的名称

使用solt 累的属性来显示可能给累绑定的属性

class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称


>>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25 # 绑定属性'age'
>>> s.score = 99 # 绑定属性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'



由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。

使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:

mkvirtualenv.bat –python==C:\Python\Python36-32\python.exe py3 指定版本号的安装

使用枚举类

确定元类的使用情况 哪些地方会使用到元类

redis
mongod
mysql
flask
django
restful-api
单元测试
文档测试 


def abs(n):
    '''
    Function to get absolute value of number.

    Example:

    >>> abs(1)
    1
    >>> abs(-1)
    1
    >>> abs(0)
    0
    '''
    return n if n >= 0 else (-n)


    无疑更明确地告诉函数的调用者该函数的期望输入和输出。

    并且,Python内置的“文档测试”(doctest)模块可以直接提取注释中的代码并执行测试。

文件读写的操作

for  else  的使用:
    当for语句正常执行的话, else 语句也就能正常的进行执行, 


    实例:
        for item in range(10):
            print(item)
        else:
            print("else")
        这个语句是  会打印 出来 item的值 和 else 


        for item in []:
            print(item)
        else:
            print ("else")
        这个也会打印出来 else


        for item in range(10):
            print(item)
            if item == 10:
                break
        else:
            print ("else")
        如果for循环被中断了, 那么这个else  也就不能再使用了


可以通过 os.access()  来查看当前文件是不是有权限, 去进行读写的操作  或者是 文件是不是存在的

调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。另外,调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。

如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便:

for line in f.readlines():
    print(line.strip()) # 把末尾的'\n'删掉


遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

 f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值