一.类装饰器
1.无参类装饰器
class Decorator:
def __init__(self,m): # 用来接收外部传进来的函数引用
self.m=m
def __call__(self, *args, **kwargs):
self.m(*args,**kwargs)
print("涂粉...")
print('涂口红')
print('变年轻了')
@Decorator # girl=Decorator(girl)
def girl():
print('俺是大妈...')
girl()
执行步骤如下:
- girl=Decorator(girl)
- 将函数girl的引用传入装饰器中
- 后面使用girl()调用这个函数,也就是装饰器中的m()
- 记得我们学过,函数也是一种对象,如果我们想要调用函数这个对象,我们必须重写__call__方法;
- 重写__call__方法,并且在__call__中进行调用.
2.带参数的装饰器之函数实现
class Decorator:
def __init__(self,n):
self.n=n # 已确定n传进来了
def __call__(self,f):
def wrapper(*args, **kwargs):
r=f(*args, **kwargs)
print(r)
print('涂口红')
print('变年轻了')
return wrapper
@Decorator(5) # girl=Decorator(girl)
def girl(*args, **kwargs):
print(args,kwargs)
print('俺是大妈...')
return '但是:'
girl('hello',m='world')
- @Decorator(5)第一次将装饰器的参数通过__init__(self,n)传入类中,让n来接收
- 我们现已接收到了装饰器的参数,(记住,这时候没有调用__call__,调用__call__()是通过装饰器的再次装饰而调用的,如果想要调用__call__()方法,必须通过创建对象调用),通过装饰器的再次装饰,创建了一个装饰去decorato()对象,这就调用了__call__()方法,将函数girl的引用传了进来,也就是f.
- 为了装饰,我们覆盖魔术方法__call__()并将要装饰的函数通过return wrapper返回出去,girl来接收
- 这是girl=wrapper,通过girl(‘hello’,m=‘world’)对wrapper对函数的调用,我们再次进入到wrapper函数中,这次带进来的参数是(‘hello’,m=‘world’).
- 调用f函数,将通过wrapper接收到的参数通过函数r=f(*args, **kwargs),接收函数f,也就是要装饰的对象的返回值r
3.带参数的装饰器之类实现
class Decorator:
def __init__(self,n):
self.n=n # 已确定n传进来了
def __call__(self,func):
print(func) # 已经将函数的引用传了进来
class inner_class:
def __init__(self,*args,**kwargs):
print(args)
print(kwargs)
self.func=func
def __call__(self, *args, **kwargs):
r=self.func(*args, **kwargs)
print(r)
print("涂粉...")
print('涂口红')
print('变年轻了')
return inner_class(func)
# 将其传出去之后,经过girl('hello',m='world'),创建了内部类inner_class的对象,
# 通过__init__()接收参数,通过__call__()调用新创建的这个对象(只有实现__call__方法,对象才能像函数一样调用)
@Decorator(5) # girl=Decorator(girl)
def girl(*args, **kwargs):
print(args,kwargs)
print('俺是大妈...')
return '但是:'
girl('hello',m='world')
二.元类
1.什么是元类
元类就是创建类的类,它是所有类的鼻祖(包括object),int是用来创建整型对象的,str是用创建字符对象的,而type是用来创建类对象的(包括整型,字符型等,我说的是一切对象,python中一切皆对象中的对象),元类就是创建类对象这种东西的.type是python的内建函数,如果把类比作模板,那么元类就是创建模板的东西.
2.初学一段话
元类被称为 Python 中的“深奥的巫术”。尽管你需要用到它的地方极少(除非你基于 zope 编程),可事实上它的基础理论其实令人惊讶地易懂。
一切皆对象
一切都有类型
“class”和“type”之间本质上并无不同
类也是对象
它们的类型是 type
以前,术语 type 用于内置类型,而术语 class 用于用户定义的类,但自 Pythoon 2.2 以来“class”和“type”本质上并无不同。
对于旧风格(old-style)类的类型是 types.ClassType
类的类是……
它的元类……
就像对象是类的实例一样,类是它的元类的实例。
调用元类可以创建类。
确切来说,Python 中的其它对象也是如此。
因此当你创建一个类时……
解释器会调用元类来生成它……
定义一个继承自 object 的普通类意味着调用 type 来创建它:
3.type内建函数
- 类是对象的类,类的类是type(包括object),默认元类是type
使用底层的东西(内建函数type)创建一个类
class A(object):
num = 100
def print_b(self):
print(self.num)
@staticmethod
def print_static():
print("----haha-----")
@classmethod
def print_class(cls):
print(cls.num)
B = type("B", (A,), {"print_b": print_b, "print_static": print_static, "print_class": print_class})
b = B()
b.print_b()
b.print_static()
b.print_class()
- 用法
1]type(对象)–>返回当前对象的类型
2]type(name,bases,attrs) ----> name类名,bases:tuple保存所有的父类,attrs{}字典,类中的所有属性,所有的类底层都是经过type构建出来的,我们现在就可以自定义一个元类
3]自定义元类
class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
print(name)
print(bases)
print(attrs)
attrs['b'] = 'world'
if attrs.get('test'):
attrs.pop('test')
return type.__new__(cls, name, bases, attrs)
class MyList(object, metaclass=ListMetaclass):
a = 'hello'
def test(self):
print('---->test')
l = MyList()
print(MyList.__dict__)
print(l)
print(l.a)
# print(l.b)
# l.test()
元类就是类的类,默认是type,所有的类都要经过type,但是我们可以自定元类,就像所有类的父类都是object一样,默认是object,但我们可以更改它
4.元类的作用
- 拦截类的创建
- 修改类
- 返回修改之后的类
5.__metaclass__属性
你可以在定义一个类的时候为其添加__metaclass__属性。
class Foo(object):
__metaclass__ = something…
pass
如果你这么做了,Python就会用元类来创建类Foo。小心点,这里面有些技巧。你首先写下class Foo(object),但是类Foo还没有在内存中创建。Python会在类的定义中寻找__metaclass__属性,如果找到了,Python就会用它来创建类Foo,如果没有找到,就会用内建的type来创建这个类。把下面这段话反复读几次。
class Foo(Bar):
pass
Python做了如下的操作:
- Foo中有__metaclass__这个属性吗?如果是,Python会通过__metaclass__创建一个名字为Foo的类(对象)
- 如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。
- 如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。
- 如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。
- 现在的问题就是,你可以在__metaclass__中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以。
三.单例设计模式
1.学前一席话
单例是一种 设计模式 ,应用该模式的类只会生成一个实例。
单例模式保证了在程序的不同位置都 可以且仅可以取到同一个对象实例 :如果实例不存在,会创建一个实例;如果已存在就会返回这个实例。
因为单例是一个类,所以你也可以为其提供相应的操作方法,以便于对这个实例进行管理。
举个例子来说,比如你开发一款游戏软件,游戏中需要有“场景管理器”这样一种东西,用来管理游戏场景的切换、资源载入、网络连接等等任务。
这个管理器需要有多种方法和属性,在代码中很多地方会被调用,且被调用的必须是同一个管理器,否则既容易产生冲突,也会浪费资源。
这种情况下,单例模式就是一个很好的实现方法。
单例模式广泛应用于各种开发场景,对于开发者而言是必须掌握的知识点,同时在很多面试中,也是常见问题。
2.实现单例实现之__new__()魔术方法
class Person:
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(cls, *args, **kwargs)
return cls.__instance
def __init__(self):
print('---->init')
p1 = Person()
p2 = Person()
p3 = Person()
print(id(p1))
print(id(p2))
print(id(p3))
3.单例模式实现之函数装饰器实现
def func_decorator(cls):
_instance = {}
def wrapper(*args, **kwargs):
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return wrapper
@func_decorator # 1.cls = cls_decorator() 2. Singleton = cls
class Singleton:
def __init__(self):
print('---->Singleton init')
print(Singleton)
s1 = Singleton() # cls()
s2 = Singleton()
print(s1 is s2)
4. 单例模式实现之类装饰器实现
class cls_decorator:
def __init__(self, f):
self.f = f
self.__instance = {}
def __call__(self, *args, **kwargs):
if self.f not in self.__instance:
self.__instance[self.f] = self.f() # self.f = Singleton Singleton()
return self.__instance[self.f] # {'Singleton':<Singleton object at 0x00000000022205F8>}
@cls_decorator # 1.cls = cls_decorator() 2. Singleton = cls
class Singleton:
def __init__(self):
print('---->Singleton init')
print(Singleton)
s1 = Singleton() # cls()
s2 = Singleton()
print(s1 is s2)