列表推导式+生成器+面向对象一(对象的结构+类的定义)2020-22-23

1. 列表推导式

推导式主要分为列表推导式,字典推导式和集合推导式,这里我们主要看最常用的列表推导式。
列表推导式使用简洁的代码就可以由一个旧的列表构建出一个新的列表。通常会用一个变量接受这个新的列表。
语法:[表达式 for 变量 in 旧列表]
[表达式 for 变量 in 旧列表 if 条件]

例题,过滤长度不大于3的人名。通常我们是这样做的。

names=['Lucy', 'Lily','James','Jack','Amy']
def fn(names):
	new_lst=[]
	for name in names:
		if len(name)>3:
			new_lst.append(name)
	return new_lst
r=fn(names)
print(r)

结果
在这里插入图片描述
下面我们通过列表推导式来解决同样的问题

result=[name for name in names if len(name)>3]
print(result)

结果
在这里插入图片描述
我们看到比上面是一样的结果,代码却更简洁。
例题,把首字母有大写的名字都选出来。

 names=['Lucy', 'Lily','James','Jack','Amy','tom','bob','John']
 result=[name.capitalize for name in names if len(name)>3]
 print(result)

结果

在这里插入图片描述
结果我们看到列表中存储的是对象。
我们忘记了调用,caplitalize()后面一定要加括号,然后救出现下面的结果了。
在这里插入图片描述
例题:1-100之间能够被3和5整除的数:

result=[x for x in range(1,101) if x%3==0 and x%5==0]
print(result)

结果
在这里插入图片描述

2. 生成器

在需要使用列表时,通过列表推导式我们可以直接创建出一个列表,但受内存限制,我们不可能创建一个无限大的列表,而这个时候我们仅仅需要访问列表中的几个元素,那么我们可不可以键创建几个我们需要的元素,这就在一定的程度上优化了内存。那么Python中有一边循环一边计算的机制,就是生成器。生成器解决了资源优化问题。

2.1 通过列表推导式得到生成器

例子,通过遍历一个列表,让列表中的每个元素都乘3,得到一个新的列表。

new_list=[x*3 for x in range(10)]
print(new_list)

在这里插入图片描述
现在我把这个列表推导式改成生成器

new_list=[x*3 for x in range(10)]
new_list_01=(x*3 for x in range(10))
print(type(new_list))
print(type(new_list_01))

在这里插入图片描述
可以看到第一个返回的是一个列表对象,第二个返回的是一个generator对象,其实也就是生成器对象。
现在我需要三个元素,怎么生产呢?
方式一:调用生成器的__next__()方法。

new_list_01=(x*3 for x in range(10))
print(new_list_01.__next__())
print(new_list_01.__next__())
print(new_list_01.__next__())

在这里插入图片描述
这样我就生产了三个元素。
方式二:通过next()函数

new_list_01=(x*3 for x in range(10))
print(next(new_list_01) ) 
print(next(new_list_01) ) 
print(next(new_list_01) ) 
print(next(new_list_01) ) 

这样我就生成了四个元素。
在这里插入图片描述
其实在实际中,我们可以把重复的代码用循环来写。

2.2 通过函数的方式来得到生成器

例题:

i=0
while True:
	i+=1
	print(i)

这本是一个死循环,我们改动一下。

def fn():                                        
    i=0                                          
    while True:                                  
        i+=1                                     
        yield i  # yield跟return很像,是生成器的标志。       
print(type(fn()))

结果
在这里插入图片描述

可以看到返回的是generator对象,即生成器。
那么,我们就可以用上面所说的两种方式生产所需要的元素了。
在这里插入图片描述

2.3 迭代器和生成器的关系

首先我们要了解几个概念,什么叫迭代。迭代在Python程序中实际上就是在序列中获得一个元素的过程。然后是什么叫可迭代。像列表,字典,元组,集合,也包含生成器,都是可迭代对象,其中的元素都是可迭代的。如何判断一个对象是否是可迭代的呢?我们可以用isinstance()来检查一个对象是否是另一个对象的实例。如果是,就返回True,不是则返回False。
例题:判断a='1’是不是str的实例。

a='1'
b=1
print(isinstance(a,str))

在这里插入图片描述
在这里插入图片描述
下面我们举例用isinstance()来判断一个列表是不是可迭代对象(Iterable,可迭代的)。

lst=[1,2,3,4,5,6,7]
print(isinstance(lst,Iterable)  # 前者是不是后者的实例。

在这里插入图片描述
出现报错,提示要导入一个模块,把鼠标放在这个位置,按alt+shift+enter就会出现选项,选择第一项回车。就自动导入模块了。

from collections import Iterable               
                                               
lst=[1,2,3,4,5,6,7]                            
print(isinstance(lst,Iterable)  # 前者是不是后者的实例。  


结果
在这里插入图片描述
虽然出现了返回值,但是有如下提示:

DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
  from collections import Iterable

说以后不再是import collections 而是import collections.abc,所以我们改一下:
在这里插入图片描述
结果顺利运行了。Python升级的很快,所以要跟紧开发者的步伐。
我们再试几次:

from collections.abc import Iterable
print(isinstance('abcd',Iterable)
print(isinstance(123,Iterable)

结果
在这里插入图片描述
列表、字符串返回的是True,整数返回的是False。
现在我再用同样的方法判断一下生成器是不是可迭代对象:
在这里插入图片描述
报错了,因为我把生成器的小括号写成了中括号,你可不要记错了哦。记得把

from collections import Iterable 

改成

from collections.abc import Iterable 

不然又会报错。
在这里插入图片描述
可以看到,生成器是可迭代对象,那么可迭代的对象是不是迭代器呢?

2.4 迭代器

可被next()函数调用,并不断返回下一个值的对象,成为迭代器。可迭代的对象不是迭代器。Iterable!=Iterator,所以大家要注意。我们验证一下。
例题,验证列表是不是迭代器。

lst=[1,2,3,4,5]    
print(next(lst) )  

结果报错了:

  File "D:/work/基础/Day12/课堂代码/Demo01.py", line 68, in <module>
    print(next(lst) )
TypeError: 'list' object is not an iterator

说列表对象不是迭代器。但是可以转化为迭代器。
例题:

lst=[1,2,3,4,5]    
lst=iter(lst)
print(next(lst) )  

在这里插入图片描述
结果我们看到正确的返回了第一个值,这里用iter()函数转化了一下,把可迭代对象转化成迭代器。记得,iter是小写哦。这些知识都是容易成为面试题的。
总结:

  • 生成器也可以被next()函数直接调用,所以生成器也是迭代器,在2.3里我们验证过生成器也是可迭代对象,所以,生成器既是可迭代对象,又是迭代器
  • 列表,元组,字典,集合等属于可迭代对象,不能直接被next()函数调用,但是可以用iter()函数转化成迭代器。

3. 对象的基本结构

我们直到,所有的程序都写在内存当中。代码都存储在硬盘中。中央处理器cpu处理代码。在硬盘和处理器之间有个内存。最终的数据都传送到内存中等待执行。所以内存越大电脑性能越快。

  • 对象就是内存中专门存储指定数据的区域
  • 对象实际就是一个容器,专门来存储数据的容器。

3.1 对象的结构

对象有

  • id 地址。一般叫着标识,用来标识对象的唯一性,每个对象的id是唯一的、,就像人的身份证。
  • type 类型。用来标识当前对象所属的圈圈。类型决定了对象有哪些功能。如果是人类,就能说话,制造工具,直立行走等功能。一旦对象被创立就不能更改了,除非强制转换。
  • value 值。就是对象中存储的具体数据。有些数据可以改变,有些事不可改变的。要看是否事可变对象。
    Python就是一个面向对象的语言。
    例子,孩子吃瓜:
    这是这样一个过程:
    妈妈骑车出门,
    到商店买瓜,
    回到家,
    把刮切开给孩子,
    孩子吃到瓜。
    这是一个面向过程的例子。好处是逻辑步骤非常的清晰。
    如果编程面向对象的话就是这样的,我对孩子的妈妈说:去给孩子买个瓜。其他的不管了,最后我只要得到一个结果,孩子吃到瓜。而妈妈买瓜的过程,被封装在一个对象里,只需要调用就行了。
    面向过程的优点是步骤清晰,把整个逻辑分解成一个个小步骤去执行,非常符合人的思维。缺点是复用性低,一旦有新的需求,需要逐个去改。面向对象编程的优点是代码比较容易维护,容易复用。缺点是不太符合人的思维逻辑,编写起来比较麻烦。

4. 类的简介

我们只是用python提供的类是不能满足我们的要求的,所以我们需要自己创建类。类就好比造汽车的一张图纸,可以造成千上万两汽车。我们也称对象是类的实例。

4.1 类的定义

现在我们定义一个简单的类

class myclass:
	pass
mc1=myclass()  #mc1是myclass整个类创建出来的对象,或者说mc1是myclass这个类的实例。
mc2=myclass()
mc3=myclass()
mc4=myclass()
r=isinstance(mc1,myclass)
print(r)

在这里插入图片描述
返回结果是True说明mc1是myclass这个类的实例。后面mc2,mc3,mc4都是myclass类的实例。可以验证。类也是一个对象。类是一个用来创建对象的对象。
我们来看看类的对象类型,以及id。

class myclass:
	pass
mc1=myclass()  #mc1是myclass整个类创建出来的对象,或者说mc1是myclass这个类的实例。
mc2=myclass()
mc3=myclass()
mc4=myclass()
print(id(myclass),type(myclass))
print(id(mc1),type(mc1))
print(id(mc2),type(mc2))

在这里插入图片描述
可以看到myclass的类型为type类。定义类其实就是定义了一个type类型的对象。
可以给类的对象添加值。如:

class myclass:
	pass
mc1=myclass()  #mc1是myclass整个类创建出来的对象,或者说mc1是myclass这个类的实例。
mc2=myclass()
mc3=myclass()
mc4=myclass()
mc1.name='钢铁侠'
print(mc1.name)

在这里插入图片描述
:类和对象都是对现实生活中事物的抽象。实际上所有事物都有两部分组成:

  • 属性(数据)
  • 方法(行为)
    在类的代码块中我们可以定义变量,作为公共属性,所有的实例对象都可以访问。

例题:

class myclass:
	name='钢铁侠'
mc1=myclass()  #mc1是myclass整个类创建出来的对象,或者说mc1是myclass这个类的实例。
mc2=myclass()
mc3=myclass()
mc4=myclass()
print(mc1.name,mc2.name,mc3.name,mc4.name)

在这里插入图片描述
可以看到,所有类的实例都可以访问name这个属性。

在类中定义的函数我们都成为类的方法

class myclass:
	name='钢铁侠'
mc1=myclass()  #mc1是myclass整个类创建出来的对象,或者说mc1是myclass这个类的实例。
mc2=myclass()
mc3=myclass()
mc4=myclass()
def speak(a):  #这里必须定义一个形参,而调用的时候却不需要传递实参,这个后面再讲。
	print('hello')

下面我们调用一下这个方法

class myclass:          
    name='金刚侠'          
    def speak(self):    # 定义函数时这里要定义一个形参,而实际调用时不需要传参,这个后面再讲。
        print('hello')  
p1=myclass()            
p1.speak()  

结果
在这里插入图片描述
调用方法的语法
对象.方法名()
函数的调用,定义几个形参传入几个实参。
方法的调用,定义至少一个形参,调用时默认传递一个参数。

5. 作业

5.1 写博客梳理知识

5.2 课堂代码敲三遍起步

猜你喜欢

转载自blog.csdn.net/m0_46738467/article/details/109991960
今日推荐