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('这是个测试函数')