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 创建方法
列表生成式改[] 改为 (),生成器保存的是算法
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>