1.对象、类、实例、属性、方法
–面向对象:Python中,所有数据类型都可以视为对象。
–面向对象的程序设计把计算机程序看成一组对象的集合,而每个对象都可以接收其它对象发过来的消息,计算机程序的执行就是一系列消息在各个对象之间传递。
–类:类是创建实例的模板
class Student(object):
pass
#class后面紧跟着类名,即Student,类名通常是大写开头,即大驼峰命名规则,紧接着是(object),表示该类是从哪个类继承下来的,通常没有合适的继承类,就使用object类,它是所有的类都会继承的类。
class Student(object):
def __init__ (self, name, score):
self.name = name
self.score = score
# 既然类是一个模板,那我们定义模板的时候,里面肯定是需要给它定义几种属性。通过'__init__'方法,在创建实例的时候,就会同时把name,score等属性绑定到实例上。
#__init__方法的第一个参数,永远是self,表示创建的实例本身。因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就是指向创建的实例本身。
#有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去
–实例:实例是一个个具体的对象
–方法:方法就是与实例绑定的函数,与普通函数不同,方法可以直接访问实例的数据。
- @property 装饰器
在面向对象的设计中,虽然我们不建议设置私有属性,但是一般会建议将属性标记为保护属性,即属性前加单下划线,建议外界不要直接访问。但如果要访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行访问和修改。而@property装饰器就可以包装getter和setter方法,使得对属性的访问既安全又方便。
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
# getter方法将self._name变为可以访问
@property
def age(self):
return self._age
# getter方法将self._age 变为可以访问
@age.setter
def age(self, age):
self._age = age
# setter 方法将self._age变为可以修改
def play(self):
if self._age <16:
print('%s正在玩飞行棋.' % self._name)
else:
print('%s正在玩斗地主.' % self._name)
def main():
person = Person('李邵阳', 12)
person.play()
person.age = 22
person.play()
# person.name 会报错,因为self._name无法通过setter修改,他还是受保护的属性
if __name__ == '__main__':
main()
---->
李邵阳正在玩飞行棋.
李邵阳正在玩斗地主.
2.生成器
(1)生成器(generator)能够迭代的关键是它有一个next()方法,
-
工作原理就是通过重复调用next()方法,直到捕获一个异常。
(2)带有 yield 的函数不再是一个普通函数,而是一个生成器generator。 -
可用next()调用生成器对象来取值。next 两种方式 t.next() | next(t)。
-
可用for 循环获取返回值(每执行一次,取生成器里面一个值)
(基本上不会用next()来获取下一个返回值,而是直接使用for循环来迭代)。
(3)yield相当于 return 返回一个值,并且记住这个返回的位置,下次迭代时,代码从yield的下一条语句开始执行。
(4).send() 和next()一样,都能让生成器继续往下走一步(下次遇到yield停),但send()能传一个值,这个值作为yield表达式整体的结果
——换句话说,就是send可以强行修改上一个yield表达式值。比如函数中有一个yield赋值,a = yield 5,第一次迭代到这里会返回5,a还没有赋值。第二次迭代时,使用.send(10),那么,就是强行修改yield 5表达式的值为10,本来是5的,那么a=10
def yield_test(n):
for i in range(n):
yield call(i)
print("i=",i)
print("Done.")
def call(i):
return i*2
for i in yield_test(5):
print(i,",")
'''程序执行流程
for i in range(5)(i=0) --> yield call(i) --->return i*2 ---> print(i,",") --->回到生成器里面执行print("i=",i)
'''
--->
0 ,
i= 0
2 ,
i= 1
4 ,
i= 2
6 ,
i= 3
8 ,
i= 4
Done.
def count_down(n):
while n >= 0:
newn = yield n
print('newn', newn)
if newn:
print('if')
n = newn
print('n =', n)
else:
n -= 1
cd = count_down(5)
for i in cd:
print(i, ',')
if i == 5:
cd.send(3)
'''
程序执行流程:
while 5 >= 0 -->yield n(return 5) -->print(i,',')(5,) --> if i == 5: cd.send(3) --> newn = 3 --> print ('if)(if) -->print('n =',n)(n = 3) -->while 3 >=0 --> yield 3(return 3) -->print(i,',')(3,) ---> if i == 5(3 == 5 False) --> newn = None --> if newn(if None 为False) -->n -=1 (n=2)......
'''
---->
5 ,
newn 3
if
n = 3
newn None
2 ,
newn None
1 ,
newn None
0 ,
newn None
上面第二段newn = yield n 这个表达式 程序运行到这一句时 ,因为有yield 所以要执行返回,把n赋给print(i,’,’),然后回到生成器里面,然后yield后面是一个 语句 n 这个语句并不是什么赋值语句,所以newn = None。