5.1 类定义和方法
1 .类的定义: 类 是一个独立存放变量(属性/方法)的空间class 类名: pass ? 实例名 = 类名()2.运算符“.” 调用类的属性或方法
实例可以访问类的属性 类不可以访问实例的属性 实例也是一个独立存放变量的空间 实例和实例没有关联 本身没有这个属性 就会去类中找3.私有属性
在python中有两私有属性,分别是在属性前加 一个下换线(_) 和两个下划线(__) 一个下滑线外部可以直接访问,二个下划线外部不可以直接访问4.方法
就是封装在类里的一种特殊的函数5.“实例方法” self代表实例本身
表示的是“实例”的行为给实例用的,和函数的传参一样,只是会先传一个自身的实例self, ? 方法总是定义在类中的,但是却叫“实例方法”,因为它表示该类所有实例所共有的行为
class persson(object): def eat(self): print(‘{}正在吃烦‘.format(self.name)) return 100 ? nanbei=persson() nanbei.name=‘南北‘ a=nanbei.eat() print(a)
5.2 初始化和析构 (dir查看属性与方法)
Python中有很多以双下划线开头且以双下划线结尾的固定方法。他们会在特定的时机被触发执行。
init 就是其中之一,它会在实例化之后自动被调用。以完成实例的初始化。
1. init 的参数传递过程:class person (object): def __init__(self,name): self.name=name print(‘{}正在上课‘.format(self.name)) ? nanbei=person(‘南北‘) nanbei.__init__(‘南北‘) person.__init__(nanbei,‘南北‘)2. “析构”:
通常在实例被销毁的时候, 长时间不用即可析构 ? __del__”就是一个析构函数了,当使用del 删除对象时,会调用他本身的析构函数。 ? 提示开发者,对象被销毁了,方便调试。进行以写必要的清理工作。 ? 当没有一个变量指向某个对象的时候,Python会自动销毁这个对象,以便回收内存空间。 ? 程序报错时 相当于结束 会进行空间释放3. del 关键字
可以删除一个变量的指向。
5.3 继承和魔术方法 super
1.继承一个类可以继承一个类,继承之后可以使用父类的方法和属性, 公用部分可以写成父类 在子类中重写不同部分 先在子类中找 再去父类中找 ? class Rec(object): def say_hello(self): print(‘aiwozhonghua ‘) ? class Son(Rec): pass ? s=Son() s.say_hello()
每个类中bases 特殊属性(返回tuple)
__bases__:查看类的直接父类 __mro__:查看类的继承路径2.多继承
当继承多个父类时,如果父类中有相同的方法, 那么子类会优先使用最先被继承的方法 (左边的) ? 当子类继承父类之后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法
class Base(object): def play (self): print(‘asdasd‘)
class A (Base): def play(self): print(‘健身卡‘)
class B(Base): def play(self): print(‘健身ASD卡‘)
class C(A,B): pass ? c=C() c.play() print(C.__mro__)
当子类重写父类方法之后,子类如果想再次调用父类的方法, 可以使用这两种方法
方法一:
class C(A, B):
def play(self): ? A.play(self) print(‘这是C‘) ? 方法二:
class C(A, B):
def play(self): ? super().play() print(‘这是C‘)
3.super 函数
可以调用父类的方法 (调用上一级) 在父类中也可以使用super函数 可以通过调用类的__mor__属性或者mro方法来查看类的继承关系
4.魔术方法 (应用并不多)
在python中,str和repr方法在处理对象的时候,分别调用的是对象的__str__和__repr__方法 ? print打印对象,调用str函数,如果对象没有定义__str__方法,则调用__repr__方法处理 ? 在交互模式下,直接输出对象,显示 __repr__ 的返回值1.str
尽可能的提供简洁且有用的信息。 让用户尽可能吸收到必要的信息。 必须要有返回值 且是字符串类型2.repr
尽可能向开发者提供创建该对象时的必要信息。 让开发者可以直接通过复制粘贴来重建对象。 必须要有返回值 且是字符串类型3.类的实例向函数一样被调用
正常情况下,实例是不能像函数一样被调用的,要想实例能够被调用,就需要定义 __call__ 方法
class Test (object): def hi (self): print(‘hi ‘)
def __call__(self, *args, **kwargs): self.hi() ? def test2(): print(‘haha‘) ? t=Test() t() #此时只会调用__call__方法 test2()4、class 查看类名
格式: 实例.__class__5、dict 查看全部属性,返回属性和属性值键值对形式
格式:实例.__dict__6、doc 查看对象文档,即类中(用三个引号引起来的部分)
格式:类名.__dict__7、bases 查看父类
格式:类名.__base__8.mro 查看多继承的情况下,子类调用父类方法时,搜索顺序
格式:子类名.__mro__
? class Rectang(object): def __init__(self,length,width): self.length=length self.width=width def get_area(self): print(self.length*self.width) def __add__(self, other): length=self.length+other.length width=self.width+other.width result=Rectang(length,width) return result class Square(Rectang): def __init__(self,side_length): super().__init__(side_length,side_length) def __call__(self, *args, **kwargs): return self.get_area() def __str__(self): return ‘边长为:{}‘.format(self.length) s=Square(150) print(s) s() a=Rectang(20,10) b=Rectang(50,30) new_rec=a+b # a.__add__(b) print(type(new_rec)) new_rec.get_area() ? ?
5.4 new方法 (重写后必须return一个实例出来)
1.new方法
return super().__new__(cls) ? 1、__new__方法是在类创建实例的时候自动调用的。 ? 2、实例是通过类里面的__new__方法是在 类 创建出来的。 ? 3、先调用__new__方法创建实例,再调用 __init__方法初始化实例。 4、__new__方法,后面括号里的cls代表的是类本身
在上面的例子中,我们可以看到创建实例的时候,自动调用了 new ,方法和 init 方法,并且 是先调用的 new 再调用的 init 方法,打印 cls 的时候显示的这个Base类
class Test (object): def __init__(self): print(‘init 方法‘) ? def __new__(cls, *args, **kwargs): print(‘new 方法‘) return super().__new__(cls) ? t=Test()
2.单例模式 (只生成一个实例)
class Test (object): __insance=None #1. 定义一个私有属性等于None def __init__(self): print(‘init 方法‘) def __new__(cls, *args, **kwargs): if cls.__insance is None: cls.__insance=super().__new__(cls) return cls.__insance a=Test b=Test print(a is b) print(id(a)) print(id(b)) ? ? #2. (然后我们判断它是不是等于None,如果等于None,我们调用父类的方法创建一个实例对象,并把返回的对象赋值给 __instance,并且返回__instance) ? #3. 如果__instance不等于None,那就说明已经创建了对象 我们直接把__instance返回出去。 ? ? #单例模式实现的原理:通过重写__new__方法,让__new__只能进行一次实例创建。 #在上面的例子中,我们可以看到两个实例的ID是相同的,意味着第二次创建的时候,并没有真正的去创建,而是引用的第一次创的实例,只是同一个实例的不同名字 ? ?
5.5 定制属性访问
查:
hasattr(re, ‘length‘) # 返回bool值 是否有这个属性 getattr(re, ‘length‘) # 返回属性值 获取属性的值 re . getattribute (‘length‘) 该方法在访问实例属性时,自动调用
re . getattr (‘length‘) 该方法在访问不存在的属性时,调用
改:
setattr(re , ‘length‘, 6) 有则改 无则增 re . setattr (‘length‘, 5) 该方法在访问实例属性时,自动调用
增:
re .aaa = 1 setattr(re, ‘bbb‘, 2) # 有bbb属性就改,没有就增 re. setattr (‘ccc‘, 3) # 同上
删:
delattr(re , ‘ccc‘) 删除实例属性 re . delattr (‘bbb‘) del re
5.6 描述方法 (了解)
__get__() #在访问该类创建的实例时调用 __set__() #在修改该类创建的实例时调用 __delete__() #在删除该类创建的实例时调用
5.7 装饰器
? def girl(): return ‘这是一个女孩‘ print(girl()) def modify(func): def wrapper(): result =func() return result+‘很6‘ return wrapper girl= modify(girl) print(girl()) ? ? ############################ ? def modify(func): def wrapper(): result =func() return result+‘很6‘ return wrapper @modify def girl(): return ‘这是一个女孩‘ print(girl()) ? ?python自带的三个内置装饰器
class Rectangle: def __init__(self, length, width): self.length = length self.width = width def area(self): areas = self.length * self.width return areas @property # 就像访问属性一样 少一个括号 def area(self): return self.width * self.length @staticmethod # 静态方法 和class类断开联系 def func(): print(‘staticmethod func’) @classmethod # 类方法 def show(cls): # cls代表类本身 不用实例化即可调用 print(cls) print(‘show fun‘)
5.8 类装饰器
class Test_Class: def __init__(self, func): self.func = func def __call__(self): print(‘类‘) return self.func @Test_Class def fun_test(): print(‘这是个测试函数‘)类也可以做装饰器,但是需要定义 call 方法
? class Rectangle: def __init__(self, length, width): self.length = length self.width = width def area(self): areas = self.length * self.width return areas @property def get_area(self): return self.length*self.width @staticmethod # 静态方法 和class类断开联系 def func(): print(‘staticmethod func‘) rec=Rectangle(10,8) print(rec.get_area) Rectangle.func() ? ######################################## # 类装饰器 import time class Myclass (object): def __init__(self,func): self.func=func def __call__(self, *args, **kwargs): start_time = time.time() self.func(*args) r_time = time.time() - start_time print(r_time) @Myclass def girl (name): print(‘girl name is {} ‘.format(name )) girl(‘ada‘) ? ######################################## ? 查看函数运行时间: ? import time def run_time (func): def wrapper(): start_time=time.time() result=func() r_time=time.time()-start_time print(r_time) return result return wrapper @run_time def say_hello(): print(‘hello‘) say_hello() ? ? ######################################## ? import time def run_time (func): def wrapper(): start_time=time.time() func() t=time.time()-start_time print(‘shijianwei{} ‘.format(t)) return wrapper() @run_time def test_type(): for i in range(1000): type(1) @run_time def test_isinstance(): for i in range(1000): isinstance(1,int) ? ?