python基础知识归纳

1. python中的list和array的不同之处

list是python的内置数据类型,list中的每个元素的类型不必相同,array中的每个元素的类型必须相同,一般使用numpy中的array.创建list用[],创建array一般用np.array(tuple)或者np.array((list)),也可以用np.arange(start,end1,step)或者np.linspace(start,end2,step),end1不包含,end2包含,并且step必须合理。
list常用方法有:append(),insert(),extend(),pop(),remove(),sort(),reverse(),len(),max(),min(),list(),enumerate()。

2. python的list和tuple的区别

tuple的每一项是不支持赋值,list里面的元素是支持赋值的

a = (1,2)
a[1]=0     #报错
b = [1,2]
b[1]=3   #通过

这里实际设涉及到Python中的可变类型和不可变类型。不可变类型,只要值相同,都指向同一个地址;对于可变类型,值相同,他们也不一定指向内存地址。可变类型里面的元素是可以重新赋值的,不可变类型里面的元素值是不可以重新赋值的。不可变类型有:数字,字符串,元组;可变类型有:列表,字典

3.python中字典用法

字典的特性:字典值可以没有任何限制,但是键不行,键必须满足两个条件:
1)不允许同一个键出现两次。相同键时,后面的值会覆盖前面的值。
2)键必须是不可变的,只能用数字,字符串,元组充当

常用方法:

dict.clear()清空字典里面的元素
dict.copy()返回一个字典的浅复制
dict.fromkeys(seq [,val])创建一个字典,以seq中的元素为key,val为对应的value
dict.get(key,default=None)返回指定键的值,如果值不在字典中返回default值
dict.kas_key(key)如果key在dict里面,返回true,否则返回fasle
dict.items()以list形式返回可遍历的(key,value)元组数组
dict.keys()以list形式返回字典里有的key
dict.values()以list形式返回字典里有的value
dict.update(dict2)将dict2里面的键值对更新到dict里
dict.pop(key [, default])删除字典给定key所对应的值,返回值为被删除的值,key必须给出,否则返回default

python不同于list,追加元素和赋值形式一样,eg:

mydict = {'id':'0002'}
mydict['id'] = '0001'       #assign a new value
mydict['name'] = 'python'   #add new item
a = mydict.pop('id')
print(a)
b = mydict.pop('id','deleted')  #set default value, when key has been pop
print(b)
print(len(mydict))

print(mydict['id'])     #keyError
print(mydict.get(id))  #return None

get方法和[]形式都可以获取字典里面的值,但是当key不存在的时候,[]形式会报错,而get方法会返回None。为安全起见,以key获取value时,用get方法比较好值得注意的keys(),values()方法返回的,<class ‘dict_keys’>,不支持索引,要用list将其转化为索引。

4.python常用的内置函数
4.1常用的数学函数:

函数名说明
divmod(a,b)返回a除以b的商和余数
max()/min()返回可迭代对象中元素的最大/小值,或者所有参数的最大/小值
pow(a,b)返回两个数值的幂运算,即a的b次方
round(a,b)对浮点数a保留b位
sum()对元素类型是数值的可迭代对象进行元素求和
abs()求数值的绝对值
print(divmod(5,2.1))
print(max([1,5,2]))  #iterator
print(max(1,2,4))    #multi-arguments
print(sum([1,2]))
print(round(2.323423,3))  #2.323

这里注意min()和max()函数,它接收的可以是多个参数,也可以是一个迭代器对象,建议使用迭代器的方式。

4.2 处理可迭代对象的函数:

函数名说明
all()判断可迭代对象的每一个元素是否都为True值,是就返回True
any()判断可迭代对象的元素是否有为True值的元素,有就返回True
filter()使用指定方法过滤可迭代对象的元素
map()使用指定方法去作用传入的每个可迭代对象的元素并生成新的可迭代对象
next()返回可迭代对象中的下一个元素
reversed()反转序列生存新的可迭代对象
print(all([1,2,3]))      #True
print(all([1,2,0]))      #False
print(any([0,0,0]))      #False
print(any([1,0,0]))      #True

#过滤奇数留下偶数:
a = [i for i in range(10)]
def odd(i):
    return i % 2 == 0
print(list(filter(odd, a)))
print(list(filter(lambda x:x%2==0, a)))  #lambda形式

补充说明:filter()函数返回的是一个迭代器对象,需要使用list()来将其转化为列表

#操作迭代器的每一个元素
def add_ten(x):
    return x+10
a = [i for i in range(10)]
print(list(map(add_one,a)))

说明:map()和filter()函数的区别在于filter第一个参数的函数返回值为bool值,为False则被过滤掉对应的元素。而map()函数里面的第一个参数所表示的函数的返回值直接代替对应的元素,从而生成新的可迭代对象。

#迭代器遍历
a = iter('adfb')
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a, 'end'))

使用next()函数遍历迭代器时,当next到最后一个元素时,如果继续访问则会出现StopIteration异常,可以设默认值(第二个参数),用来判断结束循环的条件。

#sorted对元素为字典的list按key升序
a = [{1:'b'},{2:'c'},{3:'d'},{5:'f'},{4:'e'}]
b = sorted(a,key=lambda item:list(item.keys())[0],reverse=False)
print(b)

#sorted对dict的key排序,实际是先转化为元素为元组的list,然后对一个元素排序,
最后得到也是一个元组列表,需要用dict()将其转化为dict。
a = {1:'b',2:'c',3:'d',5:'f',4:'e'}
b = sorted(a.items(),key=lambda item:item[0])
print(dict(b))

使用sorted函数主要考虑key参数的赋值(用于指定排序)

5. 迭代器和可迭代对象的理解
在python中,凡是可以用for循环来遍历的对象,都被看作是可迭代对象(Iterable),严格意义上只有实现了_iter_()方法才算是,实现了_getitem_()虽然可以for循环迭代,用isinstance判断是否为可迭代对象值为False,这是因为__getitem__遵循的是旧版本的协议,它支持的是索引下表遍历。
凡是可以用next()遍历的对象,都是迭代器(Iterator),迭代器一定是可迭代对象,反之则不一定成立。可以用collections模块的isinstance函数来判断

from collections import Iterable, Iterator
a1 = 'abcdef'
print(isinstance(a1,Iterator))     #False
print(isinstance(a1,Iterable))     #True

b1 = iter(a1) #实际上把a1转化为了列表迭代器
print(isinstance(b1,Iterator))     #True
print(isinstance(b1,Iterable))     #True 

for item in a1:       #因为字符串是可迭代的,所以可以直接用for循环来遍历
print(item)

要想真正理解清楚迭代器和可迭代对象必须知道这三个方法的关系:_getitem_(), _iter_(), _next_()
如果一个类实现了_iter_()或者_getitem_()方法,我们就称这个类为可迭代的类;
如果一个类同时实现了_iter_()和_next_()这两个方法(只不过他的_iter_()方法返回的是他自己本身self),这个类就是迭代器类。
所以python中的list,str,tuple这些内置对象被认为是可迭代对象,因为他们都实现了_iter_()或者_getitem_()方法,他们并没有实现_next_()方法,所以不是迭代器,不能直接用next()函数来一步一步来获取他们的各个元素。
迭代器实现了访问容器对象内各元素的方法,它接受一个容器对象,然后就可以访问容器里面的元素,它起到了封装实现细节的作用。

class MyIterableObject(object):
    def __init__(self, text):
        self.text = text
        self.sub_text = text.split(' ')
        
    '''#被注释,不然会报错
    def __iter__(self):
        print('in iter func')
        return self.sub_text
    '''
    
    def __getitem__(self, index):
        print('in getitem func')
        print(index)
        return self.sub_text[index]

iterable_object = MyIterableObject('Hello, python world!')
for item in iterable_object:
    print(item)

for循环的机制是先判断可迭代对象的有没有实现_iter_()方法,如果实现了就直接调用_iter_()方法,通常该方法也只是返回一个迭代器对象而已,说可迭代对象不准确,例如上述代码中返回的是一个list,如果没有实现_iter_(), 就会调用该可迭代对象的_getitem_()方法完成遍历。注意同时实现了这两个方法,也只会调用_iter_()方法。这里说明一点,上述代码只是模拟实现了一个可迭代对象,实现了list的类似的功能。至于list这个可迭代对象是怎么实现的,这里先不涉及,以后再python源码进阶篇中分析。
上述分析的是for循环针对于可迭代对象的机制,虽然迭代器对象也是可迭代的,但是他的特殊性在于实现了_next_()方法。

class MyIterableObject(object):
    def __init__(self, text):
        self.text = text
        self.sub_text = text.split(' ')

    def __iter__(self):
        print('in interable iter func')
        return MyIterator(self.sub_text)


class MyIterator(object):
    def __init__(self, container_object):
        self.container = container_object
        self.index = 0

    def __next__(self):
        print('in iterator next function')
        try:
            element = self.container[self.index]

        except IndexError:
            raise  StopIteration()
        self.index += 1
        return element

    def __iter__(self):                        #此方法在里面并没有调用到
        print('in iterator function')           
        return self

iterable_object = MyIterableObject('Hello, python world!')
for item in iterable_object:
    print(item)

如果实现了_next_(), 他就是迭代器,迭代器本身也是可迭代的,所以他也会实现_iter_()方法,他返回的是自己本身。但是可迭代对象的_iter_()方法也可以返回其他可迭代对象,例如上述的代码中,MyIterableObject实例是一个可迭代对象,它的_iter_()方法返回的是MyIterator实例迭代器,并不是本身,当对iterable_object进行for循环遍历时,会直接调用MyIterableObject实例的_iter_()方法,(注意并没有调用MyIterator的_iter_()方法,因为for循环遍历的是MyIterableObject的实例iterable_object) ,然后返回了一个迭代器对象。那么问题来了,for循环是怎么遍历每一个元素的,或者说_next_()方法有没有被调用,什么时候被调用?,其实for循环了做两件事:
(1)先调用要遍历对象的_iter_()方法,(2)再调用_iter_()方法返回对象的_next_()方法,一步一步遍历容器里的元素。
注意这两个过程是连续的,自动完成的,不要想着怎么在for循环语句中获取__iter__()返回的对象,然后用next()函数一步一步遍历元素,因为你所想的实际上是在实现for的功能。当然知道这种思想后,你完全可以自己实现一个和for循环有一样功能的类。
回到上面的例子,调用完MyIterableObject实例的_iter_()方法后,for循环实际操作的操作的_iter_()方法返回的MyIterator实例,即他调用的_next_()方法是MyIterator实例,没有MyIterableObject实例啥事了。
再回顾第一个样例他干了一件什么事:首先知道list不是迭代器(用isinstance方法判断,或者next() list实例会报错,说明没有实现_next__方法,也就不是迭代器)
当for循环操作MyIterableObject实例时,调用了他的_iter
()方法,返回的是一个list,但是list不是迭代器,没有实现_next_()方法,所有就会报错。如果MyIterableObject实现的是_getitem_()方法,for循环就会以旧的协议,按照下标索引值从0开始遍历,反复调用_getitem_()方法,直到发生IndexError异常(这个过程也是封装在for循环内,不可见)
相信读到这,你已经明白了迭代器和可迭代对象的关系了!我再总结他们如下:
可迭代对象一定实现了_iter_()方法,并且返回的是一个迭代器;因为迭代器本身就是可迭代对象,所以它也一定要实现_iter_()方法,返回一个迭代器(就是它自己本身),同时它还必须实现_next_()方法,供for循环遍历。for循环遍历可迭代对象遵循新旧两种迭代协议。新协议过程是:先调用可迭代对象的_iter_()方法,然后再调用其返回的迭代器的_next_()方法来完成遍历;旧协议过程为:for循环直接以下标索引值为0的形式调用对象的的_getitem_()方法完成,直到发生IndexError错误。严格意义上,仅实现了_getitem_() 方法的对象不算是可迭代对象。

6.Iter()函数的作用:
上一个节讲可迭代对象并不一定是迭代器(没有实现_next_()方法),那么如何将可迭代对象转化为迭代器呢?直接源码添加_next_()方法很low,Python开发者,就提供了Iter()函数,供使用者将可迭代对象转化为迭代器,可以把Iter()函数看作是一个迭代器工厂。list本来不是迭代器, 作为参数传递给Iter()函数后,就可以返回一个list迭代器。然后可以使用next()方法遍历了

from collections import Iterable, Iterator
mylist = [1,3,5]
print(isinstance(mylist,Iterable))        #True
print(isinstance(mylist,Iterator))        #False
for item in mylist:
    print(item)
    
mylist_iterator = iter(mylist)
print(isinstance(mylist_iterator,Iterable))   #True
print(isinstance(mylist_iterator,Iterator))   #True

两次for循环遍历都没报错,第一次是以旧协议遍历,第二次是以新协议遍历的。同时也应该能够猜测原生list的源码,应该实现了_iter_()方法和__getitem__()方法,没有实现_next_()方法。

7. 生成器和yield的关系

参考文献:
其他博文+https://blog.csdn.net/zhusongziye/article/details/80246910

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值