10.描述器和装饰器

1.__new__方法

class Base:
    def __init__(self):
        print('这是init里的方法')
    def __new__(cls, *args, **kwargs): #cls表示类本身(self是实例本身)
        print('这是在new里的方法')
        return object.__new__(cls) #通过本句调用__init__
a = Base()
ssh://[email protected]:1234/home/pyvip/.virtualenvs/py3env/bin/python3 -u /home/pyvip/py_case/file.py
这是在new里的方法
这是init里的方法

四点说明

1)__new__方法是在类创建实例的时候自动调用的,但不会自动调用__init__方法。

2)实例是通过类里面的__new__方法是在类中创建出来的。

3)先调用__new__方法创建实例,通过object.__new__(cls)调用 __init__方法初始化实例。

4)__new__方法,后面括号里的cls代表的是类本身

单例模式

class Base:
    __instance=None
    def __new__(cls, *args, **kwargs):
        if cls.__instance == None:
            cls.__instance=object.__new__(cls)
            return cls.__instance
        else:
            return cls.__instance
a = Base()
b = Base()
print(id(a),id(b))
3072519532 3072519532

定义一个私有属性__instance等于None,然后我们判断它是不是等于None,如果等于None,我们调用父类的方法创建一个实例对象,并把返回的对象赋值给 __instance,并且返回__instance, 如果__instance不等于None,那就说明已经创建了对象我们直接把__instance返回出去。

单例模式实现的原理:通过重写__new__方法,让__new__只能进行一次实例创建。

在上面的例子中,我们可以看到两个实例的ID是相同的,意味着第二次创建的时候,并没有真正的去创建,而是引用的第一次创的实例,只是同一个实例的不同名字。

2.定制属性

增:

object.name = value 有则改,无则增
setattr(object, 'name', val)  将实例object的属性name赋值为val 
object.__setattr__(name, val) 

删:

delattr(object, value) 
object.__delattr__(value)
del object

改:

setattr(object, 'name', val)  
object.__setattr__('name', value)

查:

hasattr(object, 'name') # 返回bool值
getattr(object, 'name') # 返回属性值

object. __getattribute__('name') # 返回属性值

定制属性的访问

class Base:
    num = 6
    def __getattr__(self, item):
        return 'no find'
a = Base()
print(getattr(a,'num'))
print(getattr(a,'age'))
6        #存在,输出值
no find  #不存在,输出类中__getattr__的返回值,若无__getattr__方法则会报错

3.装饰器

功能:在不改变原来的函数的基础上添加新功能

def AAA(fun): #装饰器需要使用闭包
    def BBB(x): #x是fun的参数
        print('-----')
        fun(x) #调用fun函数
        print('-----')
    return BBB #AAA调用BBB函数
@AAA     #@AAA的功能相当于CCC = AAA(CCC)这一句代码
def CCC(x):
    print(x)
CCC('我是装饰器')
-----
我是装饰器
-----

Python自带的三个装饰器

@property

让方法像属性一样被调用(调用时直接 实例名.属性名而不需要 实例名.属性名())

@staticmethod 

静态方法,类内无法使用self,和类无联系

@classmethod

类方法

例:

class AAA:
    n='sakura'
    age=18
    @property
    def name(self):
        print(self.n)
    @staticmethod
    def out():
        print(AAA.age) #此时无法使用self调用,只能用类名.属性来调用
    @classmethod
    def sex(cls): 
        print(cls.name) #类名.属性返回一个地址
        print(cls().name) #类名()变为一个地址,类名().属性进入方法

t = AAA()
t.name
t.out()
t.sex()

sakura
18
<property object at 0xb7190414>
sakura
None

类装饰器

__call__方法,使实例(类)像函数一样被调用(上边是函数修饰函数,现在是类修饰函数)

class Test_Class:
    def __init__(self, func):
        self.func = func
    def __call__(self):
        print('')
        return self.func
@Test_Class
def fun_test():
    print('这是个测试函数')

猜你喜欢

转载自blog.csdn.net/weixin_42089175/article/details/80518718
今日推荐