1.面向对象进阶

  1)元类

    1.1.1:python创建类原理

    python创建类:

      class ObjectCreator:

        pass

    写了class,python编译器就自动创建了class类了,内部创建的原理:先在内部找属性__metaclass__;__init__等做出相应的处理后再通过type元组来创建:type(类名, 由父类名称组成的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))如:Test2 = type("Test2",(),{}) #定了一个Test2类;

    元类就是用来创建这些类(对象)的,元类就是类的类,你可以这样理解为

    MyClass = MetaClass() #使用元类创建出一个对象,这个对象称为“类”

    MyObject = MyClass() #使用“类”来创建出实例对象

    1.1.2:python对象属性__metaclass__的有趣地方

    __metaclass__属性:创建类时会先在里面查找是否有__metaclass__属性,有的话就通过这个属性指定的方法创建类;没有就往上级找指到找到,没有找到就通过type方式创建



class Foo(object):
    __metaclass__ = something…
    ...省略...



    例子:通过__metaclass__属性来控制模块里所有的类的属性都应该是大写形式:


#-*- coding:utf-8 -*-
def upper_attr(future_class_name, future_class_parents, future_class_attr):

    #遍历属性字典,把不是__开头的属性名字变为大写
    newAttr = {}
    for name,value in future_class_attr.items():
        if not name.startswith("__"):
            newAttr[name.upper()] = value

    #调用type来创建一个类
    return type(future_class_name, future_class_parents, newAttr)

class Foo(object, metaclass=upper_attr):
    bar = 'bip'

print(hasattr(Foo, 'bar'))
print(hasattr(Foo, 'BAR'))

f = Foo()
print(f.BAR)




   2)动态语言

    1.2.1定义:

      动态语言是高级程序设计语言的一个类别,具体:在运行时可改变其结构的语言。如:新的函数对象代码可以被引进,已有的函数可被清除。

    1.2.2 动态给实例绑定属性:仅作用于当前实例


>>> class Person(object):
    def __init__(self, name = None, age = None):
        self.name = name
        self.age = age
>>> P = Person("小明", "24")
>>> P.sex = "male"  #动态给实例绑定属性
>>> P.sex
'male'
>>>


    1.2.3 动态给类绑定属性:能作用于之后通过类创建的实例


>>> P1 = Person("小丽", "25")
>>> P1.sex

Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    P1.sex
AttributeError: Person instance has no attribute 'sex'

>>>> Person.sex = None #给类Person添加一个属性
>>> P1 = Person("小丽", "25")
>>> print(P1.sex) #如果P1这个实例对象中没有sex属性的话,那么就会访问它的类属性
None #可以看到没有出现异常
>>>




    1.2.4 例子:给实例绑定属性,方法;给类绑定属性,方法,其中给实例绑定方法是需注意P.run = types.MethodType(run, P)这种形式而不是直接P.run=run


import types

#定义了一个类
class Person(object):
    num = 0
    def __init__(self, name = None, age = None):
        self.name = name
        self.age = age
    def eat(self):
        print("eat food")

#定义一个实例方法
def run(self, speed):
    print("%s在移动, 速度是 %d km/h"%(self.name, speed))

#定义一个类方法
@classmethod
def testClass(cls):
    cls.num = 100

#定义一个静态方法
@staticmethod
def testStatic():
    print("---static method----")

#创建一个实例对象
P = Person("老王", 24)
#调用在class中的方法
P.eat()

#给这个对象添加实例方法
P.run = types.MethodType(run, P)
#调用实例方法
P.run(180)

#给Person类绑定类方法
Person.testClass = testClass
#调用类方法
print(Person.num)
Person.testClass()
print(Person.num)

#给Person类绑定静态方法
Person.testStatic = testStatic
#调用静态方法
Person.testStatic()


View Code


    1.2.5 运行时删除属性方法

      del 对象.属性名;delattr(对象, "属性名")

    1.2.6 通过__slots__来限制

      在class定义后加上这个限制如:使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的



>>> class Person(object):
    __slots__ = ("name", "age")

>>> P = Person()
>>> P.name = "老王"
>>> P.age = 20
>>> P.score = 100
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
AttributeError: Person instance has no attribute 'score'
>>>



   3)生成器和迭代器

    1.3.1  生成器

      1.3.1.1 定义 

        Python一边循环一边计算的机制,成为生成器:generator

      1.3.1.2 创建方法

        列表生成式改[] 改为 (),生成器保存的是算法


python re 创建pattern python创建类temperature_Code

In [15]: L = [ x*2 for x in range(5)]

In [16]: L
Out[16]: [0, 2, 4, 6, 8]

In [17]: G = ( x*2 for x in range(5))

In [18]: G
Out[18]: <generator object <genexpr> at 0x7f626c132db0>




      1.3.1.3 方法使用

        yield:感觉他会将一个值缓存起来next一下就会拿出来

          带有 yield 的函数在 Python 中被称之为 generator(生成器);

          一般next(含有yield的函数)就能获得值,当拿不到下一个值时,可通过捕获StopIteration异常来处理异常,一般结束数据会保存在这个异常对象value中

            例子:


In [30]: def fib(times):
   ....:     n = 0
   ....:     a,b = 0,1
   ....:     while n<times:
   ....:         yield b
   ....:         a,b = b,a+b
   ....:         n+=1
   ....:     return 'done'
   ....: 

In [31]: F = fib(5)

In [32]: next(F)
Out[32]: 1

In [33]: next(F)
Out[33]: 1

In [34]: next(F)
Out[34]: 2

In [35]: next(F)
Out[35]: 3

In [36]: next(F)
Out[36]: 5

In [37]: next(F)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-37-8c2b02b4361a> in <module>()
----> 1 next(F)

StopIteration: done


        next:获得生成器的下一个值

        __next__():跟next()差不多

    1.3.2 迭代器

      1.3.2.1 定义

        迭代是访问集合的一种方式;迭代器对象时可记住遍历位置的对象;迭代器对象从集合第一个位置开始迭代,直到所有元素被访问完结束

      1.3.2.2 使用

        可迭代对象:能直接作用于for循环的对象称为可迭代对象:Iteratable

              判断是否是Iteratable:isinstance([],Iteratable)

        迭代器:可被next函数调用并返回下一个值称为Iterator对象

            判断是否是Iterator对象:insinstance((x for x in range(10)),Iterator)

      1.3.2.3 方法使用

        iter():生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator ,

            把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数。

          如isinstance(iter([]), Iterator)

  4)装饰器

    装饰器在程序开发中会经常用到一个功能,顾名思义:给原有方法封装一个额外方法,这样既能保证原有代码不变,又能扩展新的功能,遵循了“开发封闭”原则,非常完美!

    写代码遵循原则:“开放封闭”,封闭已实现的功能代码块;开放对外扩展开发

    例子:


def w1(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        func()
    return inner

@w1
def f1():
    print('f1')
python执行过程:执行w1函数,并将@w1下面函数作为w1参数,即:@w1等价于w1(f1),最终当用户调用f1时,会将f1作为参数传入w1(f1),
之后w1返回做了额外代码处理后将新的f1返回,再执行f1()就是)就是修饰后的实例了,完美!



    例子:


#定义函数:完成包裹数据
def makeBold(fn):
    def wrapped():
        return "<b>" + fn() + "</b>"
    return wrapped

#定义函数:完成包裹数据
def makeItalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped

@makeBold
def test1():
    return "hello world-1"

@makeItalic
def test2():
    return "hello world-2"

@makeBold
@makeItalic
def test3():
    return "hello world-3"

print(test1()))
print(test2()))
print(test3()))

运行结果:
<b>hello world-1</b>
<i>hello world-2</i>
<b><i>hello world-3</i></b>