Python彩蛋、字典、列表高级用法、元类、混入、迭代器、生成器、生成式、git

时间:2022-08-29 12:27:26

一、类与类的关系

关注公众号“轻松学编程”了解更多。

  • is-a 继承

    继承是指一个类(称为子类、子接口)继承另外一个类(称为父类、父接口)的功能,
    并可以增加它自己的新功能的能力。
  • has-a 关联/聚合/合成

      关联体现的是两个类之间语义级别的一种强依赖关系,比如我和我的朋友,
    这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,
    一般是长期性的,而且双方的关系一般是平等的。关联可以是单向、双向的。
    表现在代码层面,为被关联类B以类的属性形式出现在关联类A中,
    也可能是关联类A引用了一个类型为被关联类B的全局变量。 聚合是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系。
    此时整体与部分之间是可分离的,它们可以具有各自的生命周期,
    部分可以属于多个整体对象,也可以为多个整体对象共享。
    比如计算机与CPU、公司与员工的关系等,比如一个航母编队包括海空母舰、
    驱护舰艇、舰载飞机及核动力攻击潜艇等。表现在代码层面,
    和关联关系是一致的,只能从语义级别来区分。 组合也是关联关系的一种特例,它体现的是一种contains-a的关系,
    这种关系比聚合更强,也称为强聚合。它同样体现整体与部分间的关系,
    但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束,
    比如人和人的大脑。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。
  • use-a 依赖

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

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

【参考:https://blog.csdn.net/u014470581/article/details/62036457】

二、彩蛋

1、python之禅

import this

Python彩蛋、字典、列表高级用法、元类、混入、迭代器、生成器、生成式、git

2、python漫画

import antigravity

3、查看帮助

python

#查看关键字
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  itemgetter

d = {'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}
# 方式1
dict1_gt1 = {key: value for key, value in dict1.items()
if value > 1}
print(dict1_gt1) # 方式2
dict1_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))
结果为:
3
1
None

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 heapq

list1 = [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 random
from collections import Counter list1 = [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 Counter

str1 = 'hello world'
# 字符串翻转
str2 = ''.join([i for i in reversed(str1)])
print(str2)
print(Counter(str1))
print(Counter(str2))
# 字符串组成成分是否一样
print(Counter(str1) == Counter(str2))
结果为
dlrow olleh
Counter({'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 2
3 4
5 6 1 3 5
2 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 world
1 2 3 4
1 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__))
结果为:
23
6
5

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):
pass class Manager(Employee):
__slots__ = ('name',) @property
def salary(self):
return 15000 class 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_hour class 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.05 def 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):
pass def main():
print(D.__mro__)
obj = D()
obj.foo()
# 判断实例obj是否属于C类
print(isinstance(obj,C)) if __name__ == '__main__':
main()
结果为:
(<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
foo() in B
True
  • __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 < 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):
pass def 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

后记

【后记】为了让大家能够轻松学编程,我创建了一个公众号【轻松学编程】,里面有让你快速学会编程的文章,当然也有一些干货提高你的编程水平,也有一些编程项目适合做一些课程设计等课题。

也可加我微信【1257309054】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!

公众号

Python彩蛋、字典、列表高级用法、元类、混入、迭代器、生成器、生成式、git

Python彩蛋、字典、列表高级用法、元类、混入、迭代器、生成器、生成式、git

关注我,我们一起成长~~

Python彩蛋、字典、列表高级用法、元类、混入、迭代器、生成器、生成式、git的更多相关文章

  1. Python爬虫Urllib库的高级用法

    Python爬虫Urllib库的高级用法 设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Head ...

  2. python中 字符 字典 列表之间的转换

    1 字典 转 字符 定义一个字典:dict = {'name': 'python', 'age': 7}字典转字符 可以使用str强制转换 如: str(dict) 此时dict的类型就是字符型了 2 ...

  3. Python彩蛋--zen of python

    今天早上在公交上浏览博客的时候,发现了python里面的一个小彩蛋--zen of python 一首python之歌 我们来看一看... ​ 是不是很简单,在python shell 里 输入 im ...

  4. 编写高质量的Python代码系列(四)之元类及属性

    元类(metaclass)及动态属性(dynamic attribute)都是很强大的Python特性,然后他们也可能导致及其古怪.及其突然的行为.本节讲解这些机制的常见用法,以确保各位程序员写出来的 ...

  5. python基础之反射内置方法元类

    补充内置函数 isinstance(obj,Foo)   # 判断obj是不是foo的实例 issubclass()      # 判断一个类是不是另一个类的子类 反射 什么是反射? 通过字符串来操作 ...

  6. python 面向对象专题(六):元类type、反射、函数与类的区别、特殊的双下方法

    目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3. 函数与类的区别 4. 特殊的双下方法 1. 元类type type:获取对象 ...

  7. PythonI&sol;O进阶学习笔记&lowbar;7&period;python动态属性,&lowbar;&lowbar;new&lowbar;&lowbar;和&lowbar;&lowbar;init&lowbar;&lowbar;和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  8. Python进阶:set和dict&sol;对象引用、可变性和垃圾回收&sol;元类编程&sol;迭代器和生成器

    frozenset:不可变集合,无序,不重复 dict上的特性: 1. dict的key或者set的值 都必须是可以hash的(不可变对象 都是可hash的, str, fronzenset, tup ...

  9. python dictionay(字典 )基本用法

    dict(dictionary)是一系列无序对象的集合,由键-值对构成,通过读取键来取得对应的值,具有可变,无序,异构,可嵌套的属性. dict初始化1.直接采用字典格式 2.利用dict(),[注] ...

随机推荐

  1. PHP 图片上传

    PHP上传的简单案例: Html文件: <html> <form action="index.php" name="form" method= ...

  2. 阻塞队列LinkedBlockingQueue和并发队列ConcurrentLinkedQueue

    LinkedBlockingQueue: public class LinkedBlockingQueue<E> extends AbstractQueue<E> implem ...

  3. URL中文乱码处理总结(转)

    转自:http://www.cnblogs.com/xirongliu/archive/2012/09/06/2674196.html 问题:传递中文参数的时候,接收页面出现乱码问题?当跨域操作,两套 ...

  4. 各种浏览器hack

    Hack是针对不同的浏览器去写不同的CSS样式,从而让各浏览器能达到一致的渲染效果,那么针对不同的浏览器写不同的CSS CODE的过程,就叫CSS HACK,同时也叫写CSS Hack.然后将Hack ...

  5. 24-语言入门-24-cigarettes

    题目地址: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=94    描述Tom has many cigarettes. We hypoth ...

  6. t-sql语句创建表(基础)

    create table ta1 (     id int identity(1,2) not null,     name nvarchar(20) not null,     identify v ...

  7. python中常用模块

    OS模块 python编程时,经常和文件.目录打交道,这是就离不了os模块.os模块包含普遍的操作系统功能,与具体的平台无关os.name()——判断现在正在实用的平台,Windows 返回 ‘nt' ...

  8. SQL Server 权限控制

    根据数据库Schema限制用户对数据库的操作行为 授予Shema dbo下对象的定义权限给某个用户(也就是说该用户可以修改架构dbo下所有表/视图/存储过程/函数的结构) use [Your DB N ...

  9. 51nod 1689 逛街(优先队列)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1689 题意: 题意: 枚举终点,这样就确定路上的花费,接下来只需要计算进 ...

  10. canvas制作表盘

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...