1、类
1、面向对象编程
2分钟让你明白什么是面向对象编程
面向对象与面向过程的本质的区别
面向对象编程(object oriented programming,OOP):
-
对象 + 类 + 继承 + 多态 + 消息 -
现实世界存在的任何事务都可以称之为对象,对象一般由属性+方法组成。 -
类:用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 -
当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决。
例子:
问题: 洗衣机里面放有脏衣服,怎么洗干净?
面向过程的解决方法:
- 执行加洗衣粉方法;
- 执行加水方法;
- 执行洗衣服方法;
- 执行清洗方法;
- 执行烘干方法;
面向对象的解决方法:
- 我先弄出两个对象:“洗衣机”对象和“人”对象
- 针对对象“洗衣机”加入一些属性和方法:“洗衣服方法”“清洗方法”、“烘干方法”
- 针对对象“人”加入属性和方法:“加洗衣粉方法”、“加水方法”
- 然后执行:
人.加洗衣粉; 人.加水 洗衣机.洗衣服; 洗衣机.清洗; 洗衣机.烘干
解决同一个问题 ,
面向过程编程就是将解决这个问题的过程拆成一个个方法(是没有对象去调用的),通过一个个方法的执行来解决问题。
面向对象编程就是先抽象出对象,然后用对象执行方法的方式解决问题。
1.1 面向过程和面向对象的比较
面向过程:
-
面向过程就是以过程为中心,分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。 -
优点: 性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源; 比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。 -
缺点:没有面向对象易维护、易复用、易扩展(耦合性高,导致可维护性比较差)
面向对象:
-
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。 -
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护 -
可维护性主要表现在3个方面:可理解性、可测试性和可修改性。面向对象的好处之一就是显著的改善了软件系统的可维护性。 -
缺点:性能比面向过程低
1.2 面向对象编程的特性
三大基本特性:封装,继承,多态
封装
Python封装机制及实现方法
-
封装,就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。 -
一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。 -
在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。 -
封装机制保证了类内部数据结构的完整性,因为使用类的用户无法直接看到类中的数据结构,只能使用类允许公开的数据,很好地避免了外部对内部数据的影响,提高了程序的可维护性。 -
对一个类实现良好的封装,用户只能借助暴露出来的类方法来访问数据,我们只需要在这些暴露的方法中加入适当的控制逻辑,即可轻松实现用户对类中属性或方法的不合理操作。 -
对类进行良好的封装,还可以提高代码的复用性。
继承
-
继承,指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。 -
继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 -
通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。 -
要实现继承,可以通过 “继承”(Inheritance)和“组合”(Composition)来实现。 -
继承概念的实现方式有二类:实现继承与接口继承。 实现继承是指直接使用父类的属性和方法而无需额外编码的能力; 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力。
多态
2、类的基本概念
数据成员:
- 类变量或者实例变量,用于处理类及其实例对象的相关的数据。
类变量:
-
类变量在整个实例化的对象中是公用的。所有实例共享一个属性 -
类变量定义在类中且在函数体之外 -
类变量通常不作为实例变量使用。 -
类方法的调用方式有 2 种, 既可以使用类名直接调用,也可以使用类的实例化对象调用。 -
可以通过类名修改类变量,会作用到所有的实例对象。 -
可以通过类对象可以访问类变量,但无法修改类变量的值。这是因为,通过类对象修改类变量的值,不是在给“类变量赋值”,而是定义新的实例变量。 -
可以动态的为类和对象添加类变量
实例变量:
-
在类的声明中,属性是用变量来表示的。这种变量就称为实例变量, -
是在类声明的内部但是在类的其他成员方法之外声明的。 -
不可以对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,此时访问到的是实例属性 当删除该实例属性后,再使用相同的名称,访问到的将是类属性。 -
实例变量指的是在任意类方法内部,以“self.变量名”的方式定义的变量,其特点是只作用于调用方法的对象。另外,实例变量只能通过对象名访问,无法通过类名访问。
Python类变量和实例变量(类属性和实例属性)
class CLanguage :
name = "C语言中文网"
add = "http://c.biancheng.net"
def say(self, content):
print(content)
print(CLanguage.name)
print(CLanguage.add)
clang1 = CLanguage()
print(clang1.name)
print(clang1.add)
CLanguage.name = "Python教程"
CLanguage.add = "http://c.biancheng.net/python"
print(CLanguage.name)
print(CLanguage.add)
clang2 = CLanguage()
CLanguage.catalog = 13
print(clang2.catalog)
局部变量:
实例化:
- 创建一个类的实例,类的具体对象。
- 创建类对象的过程,又称为类的实例化。
- 定义的类只有进行实例化,也就是使用该类创建对象之后,才能得到利用。
方法:
对象:
- 通过类定义的数据结构实例。
- 对象包括两个数据成员(类变量和实例变量)和方法。
访问类的属性:
-
hasattr(obj, name):检查是否存在一个属性。 -
getattr(obj, name[, default]) ;访问对象的属性。 -
setattr(obj, name, value) :设置一个属性。如果属性不存在,会创建一个新属性。 -
delattr(obj, name) :删除属性。
'''
__init__是类的构造函数或者初始化方法,当创建了这个类的实例就会调用该方法
self代表类的实例,代表当前对象的地址
self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
self 不是 python 关键字,可以换成别的也可以(一般习惯用self)
empCount是 类变量
'''
class Employee:
'所有员工的基类'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print "Total Employee %d" % Employee.empCount
emp1 = Employee('bob', 100)
hasattr(emp1, 'age')
getattr(emp1, 'age')
setattr(emp1, 'age', 8)
delattr(emp1, 'age')
3、继承与多态
python 多继承与继承原理及多继承中super本质
Python 类的继承和多态
python类的继承
Python 面向对象
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。
什么时候使用继承:
- 假如我需要定义几个类,而类与类之间有一些公共的属性和方法,这时我就可以把相同的属性和方法作为基类的成员,而特殊的方法及属性则在本类中定义。这样子类只需要继承基类(父类),子类就可以访问到基类(父类)的属性和方法了,它提高了代码的可扩展性和重用性。
判断继承:
-
isinstance(obj, Class) :如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。 -
issubclass(sub,sup) :用于检查类继承。判断一个类是另一个类的子类或者子孙类,
子类继承父类构造函数:
-
:子类可以没有构造函数,表示同父类构造一致: 子类不重写__init__()方法,实例化子类后,会自动调用父类的__init__()的方法。 -
子类重写__init__()方法,实例化子类后,将不会自动调用父类的__init__()的方法。 -
子类重写__init__()方法又需要调用父类的构造函数的方法: 子类既继承了父类一部分或者全部的属性,自己又新增一部分属性。(先继承再构造)
- 可以将实例用作属性添加到另一个类中去, 则每次调用__init__方法的时候都将执行该操作
多继承:
-
一个类继承自多个类就是多继承,它将具有多个类的特征。 -
如果子类和父类有相同的方法,就会调用子类中的方法。 -
如果不同的父类中存在着相同的方法名称,多个父类会根据它们在列表中的顺序被检查,如果对下一个类存在两个合法的选择,选择第一个父类
多态:鸭子类型
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
self.weight = 'weight'
def talk(self):
print("person is talking....")
class Book():
pass
class Janpanese(Person):
def listen(self):
print('is listening...')
class Chinese(Person):
def __init__(self, name, age, language):
Person.__init__(self, name, age)
self.language = language
self.book = Book()
def talk(self):
print('%s is speaking chinese' % self.name)
class American(Person, Chinese):
def __init__(self, name, age, language):
super(Person,self).__init__(name,age,)
super(Chinese,self).__init__(language)
self.language = language
def height(self):
print('is tall')
one = Person('w', 10)
two = American('w', 10, 'English')
print(isinstance(two, Person))
print(isinstance(two, Person))
print(isinstance(two, American))
print(isinstance(American, Person))
鸭子模型:
class WhoSay:
def say(self,who):
who.say()
class CLanguage:
def say(self):
print("调用的是 Clanguage 类的say方法")
class CPython(CLanguage):
def say(self):
print("调用的是 CPython 类的say方法")
class CLinux(CLanguage):
def say(self):
print("调用的是 CLinux 类的say方法")
a = WhoSay()
a.say(CLanguage())
a.say(CPython())
a.say(CLinux())
输出结果:
调用的是 Clanguage 类的say方法
调用的是 CPython 类的say方法
调用的是 CLinux 类的say方法
- 通过给 WhoSay 类中的 say() 函数添加一个 who 参数,其内部利用传入的 who 调用 say() 方法。这意味着,当调用 WhoSay 类中的 say() 方法时,我们传给 who 参数的是哪个类的实例对象,它就会调用那个类中的 say() 方法。
4、私有变量
单下划线、双下划线、头尾双下划线说明:
-
1)以双下划线开头,并且以双下划线结尾的,定义的是特殊方法或者变量,一般是系统定义名字 ,比如: -
_foo:以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问, 不能用于 from module import * -
__foo:双下划线的表示的是私有类型(private)的变量或者方法,只能是允许这个类本身进行访问。 在类内部的方法中使用时 self.__foo。 -
Python不允许实例化的类直接访问私有数据,会报错:类中无该属性 但是可以通过使用 object._className__attrName(即: 对象名._类名__私有属性名 )来访问
class JustCounter():
__secretCount = 0
publicCount = 0
def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount)
print(counter._JustCounter__secretCount)
5、实例方法、静态方法、类方法
Python实例方法、静态方法和类方法详解(包含区别和用法)
Python类调用实例方法
6、描述符
什么是描述符,Python描述符详解
7、运算符重载
- 重载运算符,指的是在类中定义并实现一个与运算符对应的处理方法,这样当类对象在进行运算符操作时,系统就会调用类中相应的方法来处理。
2、函数
1、形参和实参
Python函数值传递和引用传递(包括形式参数和实际参数的区别)
- 函数参数的主要限制是:关键字参数必须在位置参数之后(如果有的话)
形参:
- 形式参数:在定义函数时,函数名后面括号中的参数就是形式参数,
实参:
-
在调用函数时,函数名后面括号中的参数称为实际参数,也就是函数的调用者给函数的参数。 -
在调用函数,指定的实际参数的数量,必须和形式参数的数量一致(传多传少都不行),否则 Python 解释器会抛出 TypeError 异常,并提示缺少必要的位置参数。 -
在调用函数时,传入实际参数的位置必须和形式参数位置一一对应,否则会: 1)抛出 TypeError 异常 2)产生的结果和预期不符
Python函数参数传递机制(超级详细)
根据实际参数的类型不同,函数参数的传递方式可分为 2 种:
1)值传递:
2) 引用(地址)传递:
def demo(obj) :
obj += obj
print("形参值为:",obj)
print("-------值传递-----")
a = "C语言中文网"
print("a的值为:",a)
demo(a)
print("实参值为:",a)
'''
主程序首先创建一个列表对象,并定义一个a引用变量(其实就是一个指针)指向该对象。
此时内存中有两个东西:对象本身以及指向该对象的引用变量。
然后主程序开始调用 demo() 函数:
在调用 demo() 函数时,a变量作为参数传入 demo() 函数,
这里依然采用值传递方式:
把主程序中a 变量的值赋给 demo() 函数的 obj 形参,从而完成 demo() 函数的 obj 参数的初始化。
由于主程序中的 a是一个引用变量(也就是一个指针),
它保存了列表对象的地址值,
当把 a 的值赋给demo() 函数的 obj 参数后,系统复制了a变量,
即让demo() 函数的obj 参数也保存这个地址值,
即也会引用到同一个字典对象。
因此当程序在demo() 函数中操作 obj 参数时,
由于 obj 只是一个引用变量,故实际操作的还是字典对象。
此时,不管是操作主程序中的 a 变量,还是操作 demo() 函数里的obj 参数,其实操作的都是它们共同引用的字典对象,它们引用的是同一个字典对象。
'''
print("-----引用传递-----")
a = [1,2,3]
print("a的值为:",a)
demo(a)
print("实参值为:",a)
输出结果:
-------值传递-----
a的值为: C语言中文网
形参值为: C语言中文网C语言中文网
实参值为: C语言中文网
-----引用传递-----
a的值为: [1, 2, 3]
形参值为: [1, 2, 3, 1, 2, 3]
实参值为: [1, 2, 3, 1, 2, 3]
2、位置参数、关键字参数、默认参数
1、 位置参数,
1)在调用函数,指定的实际参数的数量,必须和形式参数的数量一致(传多传少都不行),
- 否则 Python 解释器会抛出 TypeError 异常,并提示缺少必要的位置参数。
2)在调用函数时,传入实际参数的位置必须和形式参数位置一一对应,否则会产生以下 2 种结果:
- 抛出 TypeError 异常
当实际参数类型和形式参数类型不一致,并且在函数中,这两种类型之间不能正常转换,此时就会抛出 TypeError 异常。
- 产生的结果和预期不符
调用函数时,如果指定的实际参数和形式参数的位置不一致,但它们的数据类型相同,那么程序将不会抛出异常,只不过导致运行结果和预期不符。
2、关键字参数
- 关键字参数是指使用形式参数的名字来确定输入的参数值。通过此方式指定函数实参时,不再需要与形参的位置完全一致,只要将参数名写正确即可。
def dis_str(str1,str2):
print("str1:",str1)
print("str2:",str2)
dis_str("http://c.biancheng.net/python/","http://c.biancheng.net/shell/")
dis_str("http://c.biancheng.net/python/",str2="http://c.biancheng.net/shell/")
dis_str(str2="http://c.biancheng.net/python/",str1="http://c.biancheng.net/shell/")
-
在调用有参函数时,既可以根据位置参数来调用,也可以使用关键字参数来调用。 -
在使用关键字参数调用时,可以任意调换参数传参的位置。 -
混合传参时关键字参数必须位于所有的位置参数之后,否则会报错。
3、默认参数(缺省参数)
3、不定长参数
跳转到: 3、变量:函数多值参数
4、匿名函数
关键字:
>>>strings = ['abc', 'aaa', 'cdfg', 'ba']
>>>strings.sort(key=lambda x: len(set(list(x))))
>>>strings
['aaa', 'ba', 'abc', 'cdfg']
5、局部函数
Python局部函数及用法(包含nonlocal关键字)
Python函数使用方法(高级用法)
在函数内部定义函数,此类函数又称为局部函数。
def outdef ():
name = "所在函数中定义的 name 变量"
def indef():
print("调用局部函数")
nonlocal name
print(name)
name = "局部函数中定义的 name 变量"
return indef
new_indef = outdef()
new_indef()
-
不加nonlocal关键字的话,会报错 UnboundLocalError: local variable ‘name’ referenced before assignment(局部变量 name 还没定义就使用) -
不可以通过global关键字解决,因为outdef函数中的name变量是局部变量 -
加了nonlocal关键字后,后面紧跟的print函数打印的是:所在函数中定义的 name 变量,即outdef函数中定义的name变量的值
6、闭包函数
什么是闭包,Python闭包(初学者必读)
def nth_power(exponent):
def exponent_of(base):
return base ** exponent
return exponent_of
square = nth_power(2)
cube = nth_power(3)
print(square(2))
print(cube(2))
输出:
4
8
-
外部函数 nth_power() 的返回值是函数 exponent_of(),而不是一个具体的数值。 -
在执行完 square = nth_power(2) 和 cube = nth_power(3) 后,外部函数 nth_power() 的参数 exponent 会和内部函数 exponent_of 一起赋值给 squre 和 cube,这样在之后调用 square(2) 或者 cube(2) 时,程序就能顺利地输出结果,
7、exec函数和eval函数
3、变量
Python学习——局部变量全局变量、函数缺省参数、函数多值参数、私有化
class G():
fly = False
def __init__(self):
selg._age = 1
self.long = 2
self.__width = 3
def run(self):
r = 4
print("I am running!.")
1、私有变量
【PYTHON】论Python的类中的私有变量、共有变量、全局变量、局部变量
私有化:
2、缺省参数(默认参数)
定义函数时可以给某个参数指定一个默认值,有默认值的参数就叫缺省参数
调用函数时如果没传值,则默认为函数内部定义的默认值 注:
3、函数多值参数(*args和**kargs)
Python中的*args和**kwargs是什么?该如何使用?
函数在不确定个数参数时会用到多值参数
python中有两种多值参数:
- 参数名前加一个 * 可以接收元组
- 参数名前增加两个 * 可以接收字典。
一般给多值参数命名时,习惯使用以下两个名字
1)*args:存放元组参数,前面有一个 * 2) * *kwargs:存放字典的参数,前面有两个
args是arguments的缩写,有变量的含义
kw是keyword的缩写,kwargs可以记忆键值对参
args 是 arguments 的缩写,表示位置参数;
kwargs 是 keyword arguments 的缩写,表示关键字参数
- *args 用来将参数打包成tuple(元组)给函数体调用,*用来创建元组,args是位置参数
def function(x, y, *args):
print(x, y, args)
function(1, 2, 3, 4, 5)
输出:
1 2 (3, 4, 5)
- **kwargs 用来将关键字参数打包成dict(字典)给函数体调用,双星号创建了字典,kwargs是关键字参数
def function(**kwargs):
print(kwargs)
function(a=1, b=2, c=3)
输出:
{'a': 1, 'b': 2, 'c': 3}
- arg就是指一个参数
- 参数arg、*args、**kwargs三个参数的位置必须是一定的。必须是(arg,*args,**kwargs)这个顺序,否则程序会报错。
- *args 必须放在 **kwargs 的前面,因为位置参数在关键字参数的前面。
def function(arg,*args,**kwargs):
print(arg,args,kwargs)
function(6,7,8,9,a=1, b=2, c=3)
输出:
6 (7, 8, 9) {'a': 1, 'b': 2, 'c': 3}
4、全局变量、局部变量
Python之全局变量、局部变量、类变量、实例变量的解读
全局变量:在模块内、所有函数外、所有class外
- 全局变量的默认作用域是整个程序,即全局变量既可以在各个函数的外部使用,也可以在各函数内部使用。
- 定义全局变量的方式有以下 2 种:
1)在函数体外定义的变量,一定是全局变量 2)在函数体内定义全局变量。即使用 global 关键字对变量进行修饰后,该变量就会变为全局变量。
局部变量:在函数内、在class的方法(类方法、静态方法、实例方法)内,且变量前面没有修饰
ahead = 'HelloWorld'
showList = []
def print_ahead():
print(ahead)
def print_other():
city = 'beijing'
print(city + ahead)
def print_list():
global showList
showList.append(1)
showList.append(2)
print(showList)
print_ahead()
print_other()
print_list()
Python变量作用域(全局变量和局部变量)
获取指定作用域范围中的变量:
1)globals()函数
2)locals()函数
-
在函数内部调用 locals() 函数,会获得包含所有局部变量的字典; -
在全局范围内调用 locals() 函数,其功能和 globals() 函数相同。 -
当使用 locals() 函数获得所有局部变量组成的字典时,可以向 globals() 函数那样,通过指定键访问对应的变量值,但无法对变量值做修改。
3)vars(object)
Pyname = "Python教程"
Pyadd = "http://c.biancheng.net/python/"
def text():
Shename = "shell教程"
Sheadd= "http://c.biancheng.net/shell/"
print("函数内部的 locals:")
print(locals())
print('locals内部['Shename']的值:', locals()['Shename'])
locals()['Shename'] = "shell入门教程"
print('修改后locals内部['Shename']的值:', Shename)
print("globals:")
print(globals())
print('globals['Pyname']:', globals()['Pyname'])
globals()['Pyname'] = "Python入门教程"
print('修改后globals['Pyname']:', Pyname)
text()
print("函数外部的 locals:")
print(locals())
输出:
函数内部的 locals:
{'Sheadd': 'http://c.biancheng.net/shell/', 'Shename': 'shell教程'}
locals内部['Shename']的值:shell教程
修改后locals内部['Shename']的值:shell教程
globals:
{ ...... , 'Pyname': 'Python教程', 'Pyadd': 'http://c.biancheng.net/python/', ......}
globals['Pyname']:Python教程
globals['Pyname']:Python入门教程
函数外部的 locals:
{...... , 'Pyname': 'Python教程', 'Pyadd': 'http://c.biancheng.net/python/', ...... }
5、类变量、实例变量
类变量:在class内,不在class的任何方法内
实例变量:在class的方法内,且使用self修饰的变量
class Person(object):
TAG = "Person"
def __init__(self, name):
print(Person.TAG)
self.personName = name
def print_name(self):
group = "BeiJing_"
print(group + self.personName)
if __name__ == "__main__":
p = Person("WangYuanWai")
p.print_name()
4、装饰器
概念:是一个闭包,把一个函数当做参数返回一个替代版的函数,本质上就是一个返回函数的函数。通过装饰器函数,可以在不修改原函数的前提下,来对函数的功能进行合理的扩充。
1)简单的装饰器:
def func1():
print('sunck is a good man')
def outer(func):
def inner():
print("********")
func()
return inner()
f = outer(func1)
输出: 2)@语法只是将函数传入装饰器函数
把@outer放在say函数前面,相当于执行了语句:
def outer(func):
def inner(*args,**kwargs):
print('&&&&&&&')
func(*args,**kwargs)
return inner
@outer
def say(name,age):
print('my name is %s,my age is %d'%(name,age))
say('y',20)
输出: 装饰器 Python @函数装饰器及用法(超级详细)
def funA(fn):
def say(arc):
print("Python教程:",arc)
return say
@funA
def funB(arc):
print("funB():", a)
funB("http://c.biancheng.net/python")
输出:
Python教程: http://c.biancheng.net/python
通过 funB() 函数被装饰器 funA() 修饰,funB 就被赋值为 say。这意味着,虽然我们在程序显式调用的是 funB() 函数,但其实执行的是装饰器嵌套的 say() 函数。
def funA(fn):
def say(*args,**kwargs):
fn(*args,**kwargs)
return say
@funA
def funB(arc):
print("C语言中文网:",arc)
@funA
def other_funB(name,arc):
print(name,arc)
funB("http://c.biancheng.net")
other_funB("Python教程:","http://c.biancheng.net/python")
输出:
C语言中文网: http://c.biancheng.net
Python教程: http://c.biancheng.net/python
5、迭代器、生成器
Python3 迭代器与生成器
1、迭代器
基本方法:
- iter() :创建迭代器对象
- 字符串,列表或元组对象都可用于创建迭代器
- next():遍历迭代器
list1=[1,2,3,4]
it1 = iter(list)
print (next(it))
print (next(it))
list2=[5,6,7,8]
it2 = iter(list)
for x in it2:
print (x, end=" ")
import sys
list=[1,2,3,4]
it = iter(list)
while True:
try:
print (next(it))
except StopIteration:
sys.exit()
1
2
3
4
Python退出程序 sys.exit()
- range函数返回一个迭代器,该迭代器返回一个等差整数序列(左闭右开):
range(10)
2、生成器
-
在 Python 中,使用了yield 的函数被称为生成器(generator)。 -
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。调用一个生成器函数,返回的是一个迭代器对象 -
生成器是构造新的可遍历对象的方式。普通函数执行并一次返回单个结果,而生成器‘惰性’地返回一个多结果序列,在每一个元素产生之后暂停,直到下一个请求。 -
如需创建一个生成器,只需要在函数中将返回关键字return替换为yield关键字。 -
当实际调用生成器时,代码并不会立即执行,直到请求生成器中的元素时,才会执行 -
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
import sys
def fibonacci(n):
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10)
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
生成器表达式:
gen = ( x+1 for x in range(100) )
def make_gen():
for x in range(100):
yield x+1
gen = make_gen()
3、比较return与yield
python-复盘-yield & return区别
共同点:
不同点:
-
如果要返回的数据是通过for等循环生成的迭代器类型数据(如列表、元组), return只能在循环外部一次性地返回, yeild则可以在循环内部逐个元素返回 -
yiled要迭代到哪个元素那个元素才即时地生成, 而return要用一个中间变量result_list保存返回值,当result_list的长度很长且每个组成元素内容很大时将会耗费比较大的内存,此时yield相对return才有优势。 -
return 是函数返回值,当执行到return,后续的逻辑代码不在执行。 yield是创建迭代器,可以用for来遍历,有点事件触发的意思 -
yield一般与循环一起用,相当于生成了一个容器(常见的就是字典),然后在这个容器里面存放了每次循环以后的值,并且就在那放着,不输出,不返回,等你下次需要他的时候直接取出来用就行(要用next和send函数调用)
def yield_test(n):
for i in range(n):
yield call(i)
print("i=",i)
print("do something.")
print("end.")
def call(i):
return i*2
for i in yield_test(5):
print(i,",")
>>>
0 ,
i= 0
2 ,
i= 1
4 ,
i= 2
6 ,
i= 3
8 ,
i= 4
do something.
end.
>>>
|