- 函数的汇总
- 面向对象初识
- 面向对象的结构
- 类名的使用
- 对象的使用
- 类名称空间,对象名称空间
- 面向对象的组合
!!!note listcomps map
!!!
import time
def timmer(fun):
def wrapper(*args):
start = time.time()
fun(*args)
end = time.time()-start
return end
return wrapper
@timmer
def func1(iterate):
s = 0
for i in iterate:
s += i
print(s)
def func3(i):
s = 0
s += i
@timmer
def func2(iterate):
s = map(func3,iterate)
print(s)
@timmer
def func4(l):
s = [i for i in range(10)]
print(s)
from collections import defaultdict
d = defaultdict(list)
l = [1,2,3,4,5,6,7,8,9]
for i in range(100000):
d["for"].append(func1(l))
d["map"].append(func2(l))
d["listcomp"].append(func4(l))
for i in d:
avg = sum(d[i])/100000
print("%s:%s"%(i,avg))
!!!note
生成器对象的close方法会在生成器对象方法的挂起处抛出一个GeneratorExit异常。GeneratorExit异常产生后,系统会继续把生成器对象方法后续的代码执行完毕。
!!!
"生成器"
def func():
for i in range(6):
yield i
g = func()
print(g.__next__())
try:
g.close()
except StopIteration:
def myGenerator():
try:
yield 1
print("Statement after yield")
except GeneratorExit:
print("Generator error caught")
print("End of myGenerator")
gen = myGenerator()
print(gen.__next__())
gen.close()
!!!note GeneratorExit StopIteration
StopIteration
由迭代器的next()方法引发,表示没有其他值。这是从Exception而不是StandardError派生的,因为这在其正常应用程序中不被视为错误。
GeneratorExit
调用生成器的close()方法时引发。它直接继承自BaseException而不是StandardError,因为它在技术上不是错误。
"generator 与 StopIteration 捕获不同"
from random import randint
def Gen(n):
i = 0
while (i<n):
i = i + 1
try:
res = yield randint(0,100)
except GeneratorExit:
print("get the stand error")
if __name__ == "__main__":
c = Gen(100)
print(c.__next__())
c.throw(GeneratorExit)
print(c.__next__())
18
Exception ignored in: <generator object Gen at 0x103cd2e60>
get the stand error
13
get the stand error
RuntimeError: generator ignored GeneratorExit
当主程序结束前,系统产生GeneratorExit异常,被生成器对象方法的except语句捕获,但是此时while语句还没有退出,因此后面还会执行“yield ”这一语句,从而发生RuntimeError。
!!!
!!!note 生成器
在python3.3前,如果生成器返回值,会报错
return 表达式的值会传给调用方,赋值给StopIteration 异常的一个属性。
yield from 结果会在内部自动捕获StopIteration 异常。
它表示:*在生成器 gen 中使用 yield from subgen()时,subgen 会获得控制权,把产出的值传给gen的调用方,即调用方可以直接控制subgen。于此同时,gen会阻塞,等待subgen终止。
yield from 的主要功能是打开双向通道,把最外层的调用方与最内层的子生成器连接起来,使两者可以直接发送和产出值,还可以直接传入异常,而不用在中间的协程添加异常处理的代码。
def gen():
for c in "AB":
yield c
for i in range(1,3):
yield i
print(list(gen()))
def gen():
yield from "AB"
yield from range(1,3)
print(list(gen()))
!!!
[lambda :x for x in range(10)]
listcomps 先指向range对象,然后更新x的值,返回9个函数。
(lambda :x for x in range(10))
生成器表达式指向range对象,返回None。结束
面向对象
class A:
name = "alex" # 静态属性
def func1(self):# 动态属性,方法
pass
函数编程vs 面向对象编程 的区别
class Shopping_Car:
def __init__(self):
pass
- 函数是封装一个功能,面向对象是封装多个相关的功能
- 程序可扩展,对象都是一个个独立的,耦合性,差异性。
类,对象
具有相同属性或者功能的一类事物。
对象:是类的具体体现。
类名
- 查看类中所有属性及方法__dict__
Person.__dict__["animal"] = "低级动物"
单独的属性及方法可以查但是不能增删改
- 查看类中某个,某些属性,某个方法,用万能的点。
Person.animal
- 不建议通过__dict__执行方法
Person()
类名加括号整体叫一个空间
这个过程是一个实例化过程,他会实例化一个对象(他会在内存实例化一个对象空间)
实例化过程内部进行了三个阶段:
- 在内存中开辟了一个对象空间
- 自动执行类中的__init__方法,并且将对象空间传给self参数
- 执行__init__方法 给对象空间封装相应的属性
class Person:
def __init__(self):
print(self)
p = Person()
p和self 都指向了创建了内存空间
可以更改空间里的值。
对象
对象操作对象空间
对象查看对象空间所有属性
print(p.__dict__)
对对象操作对象的某个属性 增删改查
print(type(p.work)) #对象调用方法 类型 method id值不同
print(type(Person.work)) #类调用方法 类型 function id值不同
<bound method Person.work of <__main__.Person object at 0x102dce518>>
<function Person.work at 0x102dc5950>
类名调用的方法与对象调用的方法 区别
- 对象调用方法是找到模块里的类,然后在对象空间里创建一个变量指向类的方法。
- 类名调用方法由于没有默认的对象需要传值,保证方法执行。对象调用函数由于已经自动传递对象,所以不能再传参数。
- id值不同,因为不是同一个空间的方法
- 类型不同 一个是 method 一个是 function
通过 PyMethod_New实现的
函数和方法的区别是: 函数是属于 FunctionObject, 而 方法是属 PyMethodObject
Bound Method 和 Unbound Method, 他们的差别是什么?
Bound method 多了一个实例绑定的过程!
- 对象为什么能调用类中的属性与方法?
- 类能不能调用对象的属性?
代码从上往下执行,遇到class 类名 就会创建这么一个空间,并为空间添加名称与值的地址对应关系
遇到类名()马上创建对象空间,里面存在一个指示牌,类对象指针。指针创建了对象与类空间的指向关系。顺着指针找到类空间的__init__方法 执行完init建立变量名与值的地址的映射关系。
先从自己空间去找,没有此属性他会通过类对象指针从类空间去找,类空间中找不到,会去父类空间去找.
对象只能查看类中的属性,不能增删改类空间的属性
class Person:
wow = "wow"
def __init__(self,name,age,sex):
print(self)
self.name = name
self.age = age
self.sex= sex
def eat(self):
print("chi")
def work(self):
print("work")
p = Person("alex",13,"man")
p.wow = p.wow #先通过指针取到类空间的属性值,再加到对象空间里的创建的wow变量名中。但他们并不是同一个地址。
print(p.wow)
print(p)
print(p.__dict__)
print(Person.__dict__)
print(id(p.work))
print(id(Person.work))
print(p.wow)
点调用会增加对象属性。
类空间没有指向对象空间指针
不能
- 对象与对象之间能不能互相调用?
没有指针所以不能互相调用
同一个类实例化出来的对象之间是不能互相访问的
不同类实例化的对象有可能互相访问。
给对象封装属性:任意位置都可以增加,类的外边,在任意类的方法里,在init里都可以。