一、类与类的关系

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

  • 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

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的更多相关文章

  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面向对象双下划线方法与元类

    目录 双下划线方法(__) 元类简介 产生类的两种表现形式 元类的基本使用 元类进阶操作 __new__方法 双下划线方法(__) 面向对象中的双下方法也有一些人称之为是魔法方法,有些双下方法不需要刻 ...

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

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

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

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

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

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

  8. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

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

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

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

随机推荐

  1. JMETER并发压测-自定义不同请求参数

    背景 虽然可以请求相同的接口做测试,但是请求参数每次都是相同的.为了模拟不同的用户,请求不同的参数,所以要自定义参数来做多线程并发压力测试. 点赞再看,关注公众号:[地藏思维]给大家分享互联网场景设计 ...

  2. spring-boot-route(二)读取配置文件的几种方式

    Spring Boot提供了两种格式的配置文件,分别是properties 和 yml.Spring Boot最大的特点就是自动化配置,如果我们想修改自动化配置的默认值,就可以通过配置文件来指定自己服 ...

  3. 一文搞懂AQS及其组件的核心原理

    @ 目录 前言 AbstractQueuedSynchronizer Lock ReentrantLock 加锁 非公平锁/公平锁 lock tryAcquire addWaiter acquireQ ...

  4. 087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点

    087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点 本文知识点:封装的概念和特点 说明:因为时间紧张,本人写博客过程中只是对 ...

  5. 安装、验证安装 Oracle Database XE 11gR2

    操作系统:Windows 10 x64 第一节:下载 Oracle Database XE 11gR2 第二节:安装.验证安装 Oracle Database XE 11gR2 第三节:Oracle ...

  6. 《C++primerplus》第8章练习题

    1.(简单用一下引用变量,没有采用书中的题目)定义一个替身结构体,存储名字(char[])和力量值(int).使用结构体引用作为形参写两个函数,一个不加const,使得能对定义的结构体做修改,另一个加 ...

  7. Jmeter之『JSR223脚本』

    Json处理(通过JS) 对于Json字符串,需要使用单引号『''』(因为Json中已存在双引号) // String转为Object var jsonObj = JSON.parse('${data ...

  8. RHSA-2017:2679-重要: 内核 安全更新(需要重启、存在EXP、代码执行)

    [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 修复命令: 使用root账号登陆She ...

  9. rxjs入门5之创建数据流

    一 创建同步数据流 1.creat Observable.create = function (subscribe) { return new Observable(subscribe); }; 2. ...

  10. 多测师讲解自动化测试 _RF定位iframe框_高级讲师肖sir

    Open Browser https://mail.163.com/ gc Maximize Browser Window sleep 2 #进入if框 Comment Input Text name ...