第1月4周4日

  1. 函数的汇总
  2. 面向对象初识
  3. 面向对象的结构
  4. 类名的使用
  5. 对象的使用
  6. 类名称空间,对象名称空间
  7. 面向对象的组合

!!!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
  1. 函数是封装一个功能,面向对象是封装多个相关的功能
  2. 程序可扩展,对象都是一个个独立的,耦合性,差异性。

类,对象

具有相同属性或者功能的一类事物。
对象:是类的具体体现。

类名

  1. 查看类中所有属性及方法__dict__

Person.__dict__["animal"] = "低级动物"
单独的属性及方法可以查但是不能增删改
  1. 查看类中某个,某些属性,某个方法,用万能的点。
Person.animal
  1. 不建议通过__dict__执行方法

Person()

类名加括号整体叫一个空间
这个过程是一个实例化过程,他会实例化一个对象(他会在内存实例化一个对象空间)

实例化过程内部进行了三个阶段:

  1. 在内存中开辟了一个对象空间
  2. 自动执行类中的__init__方法,并且将对象空间传给self参数
  3. 执行__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>

类名调用的方法与对象调用的方法 区别

  1. 对象调用方法是找到模块里的类,然后在对象空间里创建一个变量指向类的方法。
  2. 类名调用方法由于没有默认的对象需要传值,保证方法执行。对象调用函数由于已经自动传递对象,所以不能再传参数。
  3. id值不同,因为不是同一个空间的方法
  4. 类型不同 一个是 method 一个是 function

通过 PyMethod_New实现的

函数和方法的区别是: 函数是属于 FunctionObject, 而 方法是属 PyMethodObject

Bound Method 和 Unbound Method, 他们的差别是什么?
Bound method 多了一个实例绑定的过程!

  1. 对象为什么能调用类中的属性与方法?
  1. 类能不能调用对象的属性?

代码从上往下执行,遇到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)

点调用会增加对象属性。

类空间没有指向对象空间指针

不能

  1. 对象与对象之间能不能互相调用?
    没有指针所以不能互相调用
    同一个类实例化出来的对象之间是不能互相访问的
    不同类实例化的对象有可能互相访问。

给对象封装属性:任意位置都可以增加,类的外边,在任意类的方法里,在init里都可以。

原文地址:https://www.cnblogs.com/yonghuierming/p/9528284.html