python列表嵌套字典取值_Python彩蛋、字典、列表高级用法以及一些重要概念

二、彩蛋

1、python之禅

import this

05411fec94372b723ba57abc9bb5191d.png

《python之禅》,作者蒂姆·彼得斯优美总比丑陋好。(编程也是一门艺术,也以美为追求)明了优于含蓄。(代码表现的是逻辑,应当清晰有条理)简单胜于复杂。(简单的代码易于被人理解,代码是给人看的,被机器执行的)复杂总比杂乱无章好。(就算复杂也需要有条不紊)扁平比嵌套好。稀疏比密集好。可读性很重要。不能以特例的实用性来打破这些规则。错误不应该悄无声息地过去。除非你确定需要这样做。面对模棱两可,最好不要盲目去猜测。应该有一种————最好只有一种————显而易见解决方案。尽管这种方式一开始可能不太明显,因为你不是Python之父(这里的Dutch是指Guido)。现在开始做总比没有行动强。但做之前要三思而行。如果实现方案很难解释,那就不是一个好方案。如果实现方案很容易解释,那么它可能是个好方案。命名空间是一个伟大的想法——让我们更多的使用起来吧!

二、类与类的关系

•  is-a 继承

         继承是指一个类(称为子类、子接口)继承另外一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力。

•  has-a 关联/聚合/合成

         关联体现的是两个类之间语义级别的一种强依赖关系,比如我和我的朋友,  这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,  一般是长期性的,而且双方的关系一般是平等的。关联可以是单向、双向的。  表现在代码层面,为被关联类B以类的属性形式出现在关联类A中,  也可能是关联类A引用了一个类型为被关联类B的全局变量。

         聚合是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系。此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。比如计算机与CPU、公司与员工的关系等,比如一个航母编队包括海空母舰、驱护舰艇、舰载飞机及核动力攻击潜艇等。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合。它同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束,比如人和人的大脑。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。

•  use-a 依赖

        简单的理解,依赖就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖。表现在代码层面,为类B作为参数被类A在某个method方法中使用。

类与类关系的强弱程度依次为:组合>聚合>关联>依赖

2、python漫画

import antigravity

f04473f4cc4e24a5751d0a6713db24e1.png

3、查看帮助

#查看关键字help("keywords")

三、字典高级用法

1、字典推导式

list1 = ['a','b','c']dict1 = {k:i for i,k in enumerate(list1) }print(dict1)

结果为:{'a': 0, 'b': 1, 'c': 2}

2、字典按值排序

方式1:

d = {'a': 1,'b': 6,'c': 55,'d': 1,'f': 0}sort = sorted(zip(d.values(),d.keys()))sort_d = {v:k for k,v in sort}print(sort_d)

结果为:{'f': 0, 'a': 1, 'd': 1, 'b': 6, 'c': 55}

方式2:

d = {'a': 1,'b': 6,'c': 55,'d': 1,'f': 0}print({k:d[k] for k in sorted(d,key=d.get)})

结果为:{'f': 0, 'a': 1, 'd': 1, 'b': 6, 'c': 55}

方式3:python

d = {'a': 1,'b': 6,'c': 55,'d': 1,'f': 0}print(d.items())print(dict(sorted(d.items(),key=lambda v:v[1])))

结果为:dict_items([('a', 1), ('b', 6), ('c', 55), ('d', 1), ('f', 0)]){'f': 0, 'a': 1, 'd': 1, 'b': 6, 'c': 55}

方式4:

from operator import  itemgetterd = {'a': 1,'b': 6,'c': 55,'d': 1,'f': 0}print( dict(sorted(d.items(),key=itemgetter(1))))

结果为:dict_items([('a', 1), ('b', 6), ('c', 55), ('d', 1), ('f', 0)]){'f': 0, 'a': 1, 'd': 1, 'b': 6, 'c': 55}

3、字典值过滤

dict1 = {'a': 1,'b': 6,'c': 55,'d': 1,'f': 0}# 方式1dict1_gt1 = {key: value for key, value in dict1.items()                    if value > 1}print(dict1_gt1)# 方式2dict1_gt2 = {x:dict1[x] for x in filter(lambda x:dict1[x] > 1,dict1)}print(dict1_gt2)

结果为:{'b': 6, 'c': 55}{'b': 6, 'c': 55}

4、get()方法

d = {'a':1,'b':2}print(d.get('c',3))print(d.get('a'))print(d.get('d',None))

结果为:31None

get()方法可以获取给定的键名的值,如果键名不存在,最好给定一个默认值为None作为返回值。

5、合并字典

方式1:

d1 = {'hello':1}d2 = {'world':2}print({**d1,**d2})

结果为:{'hello': 1, 'world': 2}

方式2:

d1 = {'hello':1}d2 = {'world':2}print(dict(d1.items()| d2.items()))

结果为:{'hello': 1, 'world': 2}

方式3:

d1 = {'hello':1}d2 = {'world':2}d1.update(d2)print(d1)

结果为:{'hello': 1, 'world': 2}

四、List高级用法

1、查找最大或最小的N个元素

使用堆区的大根堆与小根堆来实现。

大根堆:数据以类似树的结构把按大到小排序;

小根堆:数据以类似树的结构把按小到大排序.

import heapqlist1 = [34, 25, 12, 99, 87, 63, 58, 78, 88, 92]list2 = [        {'name': 'IBM', 'shares': 100, 'price': 91.1},        {'name': 'AAPL', 'shares': 50, 'price': 543.22},        {'name': 'FB', 'shares': 200, 'price': 21.09},        {'name': 'HPQ', 'shares': 35, 'price': 31.75},        {'name': 'YHOO', 'shares': 45, 'price': 16.35},        {'name': 'ACME', 'shares': 75, 'price': 115.65}    ]# 列表取前5个最大的值print(heapq.nlargest(5, list1))# 列表取前5个最小的值print(heapq.nsmallest(3, list1))# 元素按'price'排序取前2个最大的值print(heapq.nlargest(2, list2, key=lambda x: x['price']))print(heapq.nlargest(2, list2, key=lambda x: x['shares']))

结果为:[99, 92, 88, 87, 78][12, 25, 34][{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}][{'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]

2、查找列表中元素出现频率较多的前三个元素

import randomfrom collections import Counterlist1 = [random.randint(1,10) for i in range(20)]counter = Counter(list1)print(list1)# 查找出现频率最多的前3个元素print(counter.most_common(3))

结果为:[10, 8, 7, 2, 10, 7, 6, 9, 1, 10, 7, 3, 3, 10, 8, 10, 4, 6, 8, 10][(10, 6), (8, 3), (7, 3)]

10出现6次,8和7各出现3次。

3、函数Counter的使用

from collections import Counterstr1 = 'hello world'# 字符串翻转str2 = ''.join([i for i in reversed(str1)])print(str2)print(Counter(str1))print(Counter(str2))# 字符串组成成分是否一样print(Counter(str1) == Counter(str2))

结果为dlrow ollehCounter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})Counter({'l': 3, 'o': 2, 'd': 1, 'r': 1, 'w': 1, ' ': 1, 'e': 1, 'h': 1})True

说明str1和str2是由相同字母组成的(顺序可能不同)的字符串。

4、查找频率出现最高的元素

import random#查找列表中频率最高的值list1 = [random.randint(1,10) for i in range(20)]print(list1)print(max(set(list1),key=list1.count))

结果为:[4, 5, 2, 3, 3, 5, 5, 1, 2, 4, 1, 3, 7, 6, 5, 9, 8, 8, 3, 3]3

5、二维数组转置

'''二维数组转置1 23 45 61 3 52 4 6'''str1 = [[1,2],[3,4],[5,6]]print(*str1)print(list(zip(*str1)))

结果为:[1, 2] [3, 4] [5, 6][(1, 3, 5), (2, 4, 6)]

6、通过map()方法把元素连接成字符串

items = ['hello','world']print(' '.join(items))numbers = [1,2,3,4]print(' '.join(map(str,numbers)))data = [1,True,'hello','world']print(' '.join(map(str,data)))

结果为:hello world1 2 3 41 True hello world

7、获取列表最大值最小值的索引

items = [1,45,23,34,23,89,0]print(items.__getitem__(2))print(min(range(len(items)),key=items.__getitem__))print(max(range(len(items)),key=items.__getitem__))

结果为:2365

items.__getitem__(2)的作用是通过索引获取对应的元素。

五、元类

•  元数据 - 描述数据的数据

•  元类 - 描述类的类

元类是不能直接创建实例的,否则会报错,错误信息为:

Can't instantiate abstract class A with abstract methods salary

# 导入创建元类的包from abc import ABCMeta, abstractmethod# 元数据 - 描述数据的数据# 元类 - 描述类的类class Employee(metaclass=ABCMeta):    __slots__ = ('name',)    def __init__(self, name):        self.name = name    @property    @abstractmethod    def salary(self):        passclass Manager(Employee):    __slots__ = ('name',)    @property    def salary(self):        return 15000class Programmer(Employee):    __slots__ = ('name', '_working_hour')    def __init__(self, name):        super(Programmer, self).__init__(name)        self._working_hour = 0    @property    def working_hour(self):        return self._working_hour    @working_hour.setter    def working_hour(self, working_hour):        self._working_hour = working_hour \            if working_hour > 0 else 0    @property    def salary(self):        return 200 * self.working_hourclass Salesman(Employee):    __slots__ = ('name', 'sales')    def __init__(self, name):        super(Salesman, self).__init__(name)        self.sales = 0    @property    def salary(self):        return 1800 + self.sales * 0.05def main():    emps = [        Manager('刘备'), Programmer('诸葛亮'),        Programmer('关羽'), Salesman('张飞'),        Salesman('马超'), Programmer('黄忠')    ]    for emp in emps:        # 有了__slots__限制,所以不能添加不存在的属性        # emp.gender = 'Male'        if isinstance(emp, Programmer):            hour = int(input(f'请输入{emp.name}本月工作时间: '))            emp.working_hour = hour        elif isinstance(emp, Salesman):            sales = float(input(f'请输入{emp.name}本月销售额: '))            emp.sales = sales        print('%s月薪为: %.2f元' % (emp.name, emp.salary))if __name__ == '__main__':    main()

•  @property

 把方法属性化,在调用方法时可以不用括号,可以直接赋值。

•  @abstractmethod

 把方法设置成抽象方法,具体功能由子类实现。

•_working_hour

 受保护的属性,不能直接访问,要通过setter装饰器来访问

      @property      def working_hour(self):          return self._working_hour       @working_hour.setter      def working_hour(self, working_hour):          self._working_hour = working_hour \              if working_hour > 0 else 0

•  __slots__

 限制属性数量,可以起到压缩内存的作用。

六、多重继承

class A:    def foo(self):        print('foo() in A')class B(A):    def foo(self):        print('foo() in B')class C(A):    def foo(self):        print('foo() in C')class D(C, B):    passdef main():    print(D.__mro__)    obj = D()    obj.foo()    # 判断实例obj是否属于C类    print(isinstance(obj,C))if __name__ == '__main__':    main()

结果为:(,,,,)foo() in BTrue

•  __mro__

 查看类中的属性和方法继承顺序。

 python2和python3使用的继承顺序算法不一样.python2用的是类似深度算法,第一个父类找不到属性或方法,就会去第一个父类的分类中查找,直到找到为止,找不到就会报错。python3用的是类似广度算法,第一个父类找不到,就会去第二个父类中查找。

七、生成器和迭代器

1.可迭代对象

但凡内置有iter方法的对象,都称为可迭代对象。可迭代的对象 如:str,list,tuple,dict,set,文件对象.。

2、迭代器对象

1既内置又next方法的对象,执行该方法可以不依赖索引取值 2.又内置有iter方法的对象,执行迭代器的iter方法得到的依然是迭代器本身

迭代器一定是可迭代对象,可迭代对象不一定是迭代器对象,文件对象本身就是一个迭代器对象.

3、for循环本质为迭代器循环

工作原理:  1.先调用in后对象的iter方法,将其变成一个迭代器对象  2.调用next(迭代器),将得到的返回值赋值给变量名  3.循环往复直到next(迭代器)抛出异常,for会自动捕捉异常然后结束循环

 ps:可以从for的角度,分辨但凡可以被for循环取值的对象就是可迭代对象

4、迭代器优点

1.提供了一种通用不依赖索引的迭代取值方式 2.同一时刻在内存中只存在一个值,更节省内存

5、迭代器缺点

1.取值不如按照索引的方式灵活,不能取指定的某一个值,只能往后取,不能往前取 2.无法预测迭代器的长度

6、生成器

生成器就是一种自定义的迭代器,本质为迭代器 但凡函数内包含yield关键字,调用函数不会执行函数体代码,会得到一个返回值,该返回值就是生成器对象。yield只能在函数内使用 1.yield提供了一种自定义迭代器的解决方案 2.yield可以保存函数的暂停的状态 3.yield对比return:相同点,都可以返回值,值得类型与个数没有限制,不同点:yield可以返回多次值,而return只能返回一次值函数就会结束

"""生成器和迭代器"""# 用循环的方式实现斐波那契数列求解def fib(n):    a, b = 0, 1    for _ in range(n):        a, b = b, a + b    return a# 用生成器的方式实现斐波那契数列求解def fib2(n):    a, b = 0, 1    for _ in range(n):        a, b = b, a + b        yield a# 重写__iter__和__next__方法实现生成器class Fib3:    def __init__(self, n):        self.n = n        self.a, self.b = 0, 1        self.idx = 0    def __iter__(self):        return self    def __next__(self):        if self.idx << span=""> self.n:            self.a, self.b = self.b, self.a + self.b            self.idx += 1            return self.a        raise StopIteration()def main():    print(tuple(Fib3(20)))    fib3 = Fib3(20)    for val in fib3:        print(val)    print(fib)    print(fib(20))    gen = fib2(20)    print(gen)    for val in gen:        print(val)           # 生成式    gen2 = (x ** 3 for x in range(1, 11))    print(gen2)    for val in gen2:        print(val)if __name__ == '__main__':    main()

省空间:生成器

省时间:生成式

一般优化是节省时间:使用缓存。

八、混入

class SetOnceMappingMixin:    __slots__ = ()    def __setitem__(self, key, value):        if key in self:            raise KeyError(str(key) + ' already set')        return super().__setitem__(key, value)class SetOnceDict(SetOnceMappingMixin, dict):    passdef main():    dict1 = SetOnceDict()    try:        # 已经存在的key中的值保持不变        dict1['username'] = 'jackfrued'        dict1['username'] = 'hellokitty'        dict1['username'] = 'wangdachui'    except KeyError:        pass    print(dict1)if __name__ == '__main__':    main()

结果为:{'username': 'jackfrued'}

python的mixin可以实现程序在运行的过程中,动态修改一个类的继承关系。

九、git

查看分支git branch创建分支git branch develop  切换分支git checkout develop创建并切换分支git checkout -b develop创建并切换分支git checkout - b issue123切换分支git checkout develop删除分支git branch -d issue123所有文件放到暂存区git add .查看暂存区状态git status提交git commit -m '提交信息'查看日志git log文件还没放到暂存区时的文件回退git checkout -- 文件提交文件后想回到其它版本git reset --hard 文件哈希id 或者版本号git checkout master合并git merge --no-ff develop强行删除还没合并的分支git branch D推送到服务器git push拉取git pull

如果觉得文章有用,点个“在看”呗!

d13260b0a21a29a6dde8373d255efd95.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值